A Self-Hosted YouTube Media Center -- Apple TV App
NullFeed is a self-hosted YouTube media center that delivers a streaming-service-quality browsing and playback experience on the big screen. This native SwiftUI app targets Apple TV, 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, all built for the 10-foot experience.
- 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.
- Top Shelf Integration -- Continue Watching items surface on the tvOS home screen, so you can jump back into a video without opening the app.
- Native Video Playback -- AVPlayer-backed playback with full seeking support.
- Focus-Optimized UI -- Designed for the 10-foot display with focus states, smooth animations, and Siri Remote navigation.
- Multi-User Profiles -- 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.
- Dark Theme -- Media-center-class dark UI built for the big screen.
Coming soon.
- Xcode 16+
- XcodeGen (
brew install xcodegen) - Swift 6
- tvOS 17+ simulator or Apple TV device
- A running NullFeed backend instance
-
Clone the repository:
git clone https://github.com/windoze95/nullfeed-tvos.git cd nullfeed-tvos -
Generate the Xcode project:
xcodegen generate
-
Open the project:
open NullFeed.xcodeproj
-
Select the NullFeed scheme, choose an Apple TV simulator or device, and build & run.
MVVM with @Observable, zero third-party dependencies.
All ViewModels use Swift's @Observable macro with @MainActor isolation. Dependencies are injected through the SwiftUI @Environment, with the app entry point wiring up core services:
| ViewModel | Responsibility |
|---|---|
AppState |
Session lifecycle, authentication state |
AuthViewModel |
Server connection and profile selection |
HomeViewModel |
Aggregated home feed data |
LibraryViewModel |
Channel list with subscribe/unsubscribe |
ChannelDetailViewModel |
Single channel videos and metadata |
DiscoverViewModel |
AI recommendation state |
PlayerViewModel |
Video playback and progressive quality |
SettingsViewModel |
Server URL and quality preferences |
TabView with NavigationStack provides tab-based navigation across four 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
- Settings -- Server connection, quality preferences, profile management
Deep linking via nullfeed:// URL schemes enables playback from the Top Shelf and other system surfaces.
All backend communication uses URLSession with async/await. A generic request builder handles method, path, body, and token-based auth headers. No third-party networking libraries.
A persistent URLSessionWebSocketTask connection provides real-time updates with auto-reconnect. Event types include download progress, download complete, preview ready, new episode, and recommendation ready.
Standard Swift Codable structs with snake_case key decoding and ISO 8601 date parsing (with fractional seconds support) via a shared JSONDecoder configuration.
Lightweight persistence for server URL, session token, selected user, and quality preferences. An App Group (group.codes.julian.nullfeed) shares credentials with the Top Shelf extension.
On 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 UserDefaults 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.
GitHub Actions handles continuous integration:
- CI -- Builds and runs tests on PRs to
main - TestFlight -- Archives and uploads to TestFlight on pushes to
main
| Repository | Description |
|---|---|
| nullfeed-backend | Python/FastAPI backend -- Docker-based server with yt-dlp, Celery, Redis, and SQLite |
| nullfeed-flutter | Flutter client for iOS |
| nullfeed-tvos (this repo) | 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.