Feed tab: Replaced news/transaction feed with league-wide highlights and condensed game replays. FeedViewModel now fetches highlights from all games concurrently, splits into condensed games vs individual highlights. Cards show team color thumbnails with play button overlay. Today tab: Removed duplicate Live games shelf — LiveSituationBar already shows all live games at the top, so the shelf was redundant. Intel tab: Removed schedule section (already on Today tab). Updated header description and stat pills. Added division hydration to standings API call so division names display correctly instead of "Division". Focus: Added .platformFocusable() to standings cards and leaderboard cards so tvOS remote can scroll horizontally through them. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mlbTVOS
Personal MLB streaming app for Apple TV and iPhone/iPad, built with SwiftUI. Streams live and archived MLB games, plus a few non-MLB channels (MLB Network, an authenticated private feed).
Targets
mlbTVOS— tvOS application (primary)mlbIOS— iOS/iPadOS application (shares most sources with the tvOS target)mlbTVOSTests— Swift Testing unit tests
The Xcode project is generated from project.yml via
XcodeGen. After editing
project.yml or adding/removing source files, run:
xcodegen generate
Building
Requires Xcode 26.3+ and tvOS/iOS 18.0 SDKs.
# tvOS
xcodebuild build -project mlbTVOS.xcodeproj -scheme mlbTVOS \
-destination 'platform=tvOS Simulator,name=Apple TV 4K (3rd generation)'
# Tests
xcodebuild test -project mlbTVOS.xcodeproj -scheme mlbTVOSTests \
-destination 'platform=tvOS Simulator,name=Apple TV 4K (3rd generation)'
Features
Dashboard
Today's live/scheduled/final games, standings ticker, and special channel entry points. Tapping a game opens the Game Center with at-bat timeline, pitch sequence, spray chart, and strike zone overlays.
Multi-stream view
Up to four simultaneous streams in an adaptive grid. Only one stream holds audio focus at a time; tap any tile to transfer focus. Streams can be single broadcasts, team-filtered feeds, or special channels.
Single-stream player
Full-screen AVPlayer with HLS adaptive streaming, custom HTTP headers, and automatic retry on failure.
Special playback channels
- MLB Network — 24/7 channel via the public MLB stream
- Werkout NSFW — authenticated private feed served by
ofappon the home server; uses a JWT cookie and rotates clips through a per-model random shuffle
Video shuffle (per-model random)
VideoShuffle groups clips by source folder (e.g. which model/creator
the video came from) and picks randomly one bucket at a time, excluding
the previously-played bucket. This guarantees no back-to-back same
source and produces a roughly uniform distribution across sources even
when one source dominates the raw data by a large factor. See
mlbTVOS/Services/VideoShuffle.swift and
mlbTVOSTests/VideoShuffleTests.swift for the pure functions and
their test coverage.
Architecture
mlbTVOS/mlbTVOSApp.swift— app entry point, creates a singleGamesViewModelinjected into the environmentmlbTVOS/ViewModels/GamesViewModel.swift— observable state store for games, standings, active streams, audio focus, and video shuffle bags; fetches from MLB Stats API and the auxiliary stream servicemlbTVOS/ViewModels/GameCenterViewModel.swift— per-game live data (at-bats, pitches, box score) used by the Game Center screenmlbTVOS/Services/— API clients (MLBStatsAPI,MLBServerAPI) and pure helpers (VideoShuffle)mlbTVOS/Views/— SwiftUI screens and component library (Components/AtBatTimelineView,PitchSequenceView,SprayChartView,StrikeZoneView, etc.)
All new Swift code uses Swift 6 strict concurrency
(SWIFT_STRICT_CONCURRENCY: complete).
Configuration
No secret management is set up. The authenticated feed cookie is
hardcoded in mlbTVOS/Views/DashboardView.swift
(SpecialPlaybackChannelConfig.werkoutNSFWCookie) and must be refreshed
manually when the JWT expires — generate a new one from the ofapp
server's jwt_secret using the same userId and a longer exp.