A Self-Hosted YouTube Media Center -- iOS App
NullFeed is a self-hosted YouTube media center that delivers a streaming-service-quality browsing and playback experience for your personal YouTube library. The Flutter app targets iOS, connecting to the NullFeed backend running on Docker (Unraid or any Docker host).
Think Netflix, but for your YouTube subscriptions -- channel-centric navigation, resume-aware playback, multi-user profiles, and AI-powered discovery.
- Instant Playback with Progressive Quality -- Start watching immediately, even before a video finishes downloading to the server. The app begins playback with a low-quality stream, then seamlessly upgrades to the full-quality version once it's ready -- no buffering, no interruption.
- Channel-Centric Navigation -- Browse your subscriptions like shows in a streaming app, with channel art, banners, and episode lists.
- Resume-Aware Home Screen -- Continue Watching, New Episodes, and Recently Added rows keep you up to date.
- Native Video Playback -- AVPlayer-backed playback with seeking and Picture-in-Picture.
- Multi-User Profiles -- Netflix-style profile picker with independent subscriptions, watch history, and recommendations per user.
- AI-Powered Discover Tab -- Claude-powered channel and video suggestions based on your subscription graph.
- Real-Time Download Tracking -- WebSocket-driven progress indicators for active downloads.
- Adaptive Layout -- Single codebase optimized for iPhone and iPad.
- Offline Metadata Caching -- Hive-based local storage for user sessions and cached metadata.
- Dark Theme -- Media-center-class dark UI with true black backgrounds and deep purple accents.
Coming soon.
- Flutter SDK 3.41+ (stable channel)
- Xcode 26 with iOS SDK
- CocoaPods (installed via
gem install cocoapodsor bundled with Xcode) - A running NullFeed backend instance
- iOS 17+ device or simulator
-
Clone the repository:
git clone https://github.com/windoze95/nullfeed-flutter.git cd nullfeed-flutter -
Install dependencies:
flutter pub get
-
Run code generation (Freezed models, Riverpod, JSON serialization):
dart run build_runner build --delete-conflicting-outputs
-
Install iOS pods:
cd ios && pod install && cd ..
-
Run on iOS Simulator:
flutter run
NullFeed follows a clean, provider-based architecture with clear separation of concerns.
All application state is managed through Riverpod providers with code generation (riverpod_generator). Providers are organized by domain:
| Provider | Responsibility |
|---|---|
authStateProvider |
User session and profile management |
channelsProvider |
Channel list with subscribe/unsubscribe |
homeFeedProvider |
Aggregated home feed data |
discoverProvider |
AI recommendation state |
downloadProvider |
Real-time download progress |
videoProvider |
Video metadata and playback state |
settingsProvider |
Server URL and quality preferences |
webSocketConnectionProvider |
WebSocket lifecycle tied to auth state |
Declarative routing via go_router with support for deep linking and tab-based navigation across five main sections:
- Home -- Resume-aware feed with Continue Watching, New Episodes, Recently Added rows
- Library -- All subscribed channels in a grid layout
- Discover -- AI-powered channel recommendations
- Downloads -- Active and completed download queue
- Settings -- Server connection, quality preferences, profile management
All backend communication uses Dio with interceptors for request logging, retry logic, and user session headers. WebSocket connections are managed separately via web_socket_channel for real-time events: download progress, completion notifications, new episode alerts, and recommendation refresh signals.
Immutable data models generated by Freezed with JSON serialization via json_serializable. Models map directly to the backend API contract.
Hive provides lightweight local persistence for user sessions, server connection details, and cached metadata for offline resilience.
The adaptive_layout.dart widget handles layout differences between iPhone and iPad form factors.
flutter build ios --releaseOpen ios/Runner.xcworkspace in Xcode to archive and distribute via TestFlight or the App Store.
After modifying any Freezed model, Riverpod provider, or JSON-annotated class:
dart run build_runner build --delete-conflicting-outputsFor continuous rebuilds during development:
dart run build_runner watch --delete-conflicting-outputsOn first launch, the app prompts you to enter your NullFeed server address:
- Server URL:
http://<server-ip>:8484(or your custom port)
This is stored locally via Hive and can be changed at any time in Settings. The settings screen includes a connection test to verify the backend is reachable.
After connecting, select or create a user profile to begin using the app.
| Repository | Description |
|---|---|
| nullfeed-backend | Python/FastAPI backend -- Docker-based server with yt-dlp, Celery, Redis, and SQLite |
| nullfeed-flutter (this repo) | Flutter client for iOS |
| nullfeed-tvos | Native Swift/SwiftUI tvOS app |
| nullfeed-demo | FastAPI demo server with Creative Commons content for App Store review |
This project is licensed under the GNU General Public License v3.0.