
Dumpert is a Dutch video site I've watched for years, but there's never been an Apple TV app, so I built one. DumpertTV is an unofficial, open-source tvOS client. Here's how it's put together and a few things that were more interesting than I expected.
Disclaimer up front: this project is not affiliated with Dumpert or DPG Media B.V. It's an independent app that uses the public Dumpert API.
The stack
-
Swift 6 with strict concurrency (
completemode) across every target - SwiftUI for all UI, tvOS 18+
-
XcodeGen so the
.xcodeprojis generated from aproject.ymland never committed - CloudKit, GroupActivities (SharePlay), Vision, AVKit, Swift Testing
One actor for the network, one source of truth for the UI
The whole networking layer is an actor. That makes per-request state like ETags and retry bookkeeping thread-safe without a single lock:
actor DumpertAPIClient {
private var etags: [URL: String] = [:]
func fetch<T: Decodable>(_ endpoint: APIEndpoint) async throws -> T {
// Exponential backoff on 5xx + network errors; honours 304 Not Modified.
try await fetchWithRetry(endpoint, attempt: 0)
}
}
The UI reads from a single @Observable @MainActor repository injected through the SwiftUI environment — no Combine, no view models competing over the same state:
@Observable @MainActor
final class VideoRepository {
private(set) var hotshiz: [MediaItem] = []
let apiClient: APIClientProtocol // protocol-backed for testing
}
ContentView()
.environment(videoRepository)
Views just read repository.hotshiz; updates flow automatically. With Swift 6's strict concurrency on, the compiler kept me honest about every actor hop.
Things that were trickier than expected
-
tvOS focus + a top tab bar. Getting a Netflix-style hero carousel to behave with the focus engine took real care. It also made automating screenshots interesting — scripted remote input doesn't reliably drive the simulator, so I added
#if DEBUGlaunch-argument hooks to jump straight to any tab/category for a capture script. - Face-centered thumbnails. Dumpert thumbnails are arbitrary crops, so I run Vision face detection and bias the crop toward detected faces. On a 55" screen the difference is night and day.
- CloudKit delta sync with change tokens for watch progress, settings and search history — resume-where-you-left-off works across multiple Apple TVs.
- Top Shelf extension that surfaces trending content on the home screen, sharing data with the app through an App Group.
-
SharePlay (
GroupActivities) for synchronized "watch together" playback.
Testing
80+ unit tests with Swift Testing, covering API decoding, the CloudKit merge logic, search/filter state, and autoplay/up-next playlist navigation. Protocols (APIClientProtocol, CacheServiceProtocol) make the network and disk layers easy to mock.
Try it / read the source
- Source (MIT): https://github.com/rm335/dumpert-apple-tv
- DOC: https://rm335.github.io/dumpert-apple-tv/
- Free public TestFlight beta: https://testflight.apple.com/join/TXTUMzEq
Feedback and PRs welcome, especially from anyone doing focus-heavy tvOS SwiftUI. The hero-carousel focus work was the fiddliest part, and I'd love to compare notes.
Top comments (0)