TLTV client application. Stream viewer with federation support and a management dashboard for cathode servers.
tltv:// URIsnpm install
cp .env.example .env
# Edit .env — set VITE_TLTV_NODE to your cathode's address
npm run dev
docker build -t phosphor .
docker run -p 3000:80 phosphor
In the cathode dev stack:
cd ../cathode
docker compose -f docker-compose.dev.yml up -d --build phosphor
The production image runs as a non-root user. Source maps are disabled.
Phosphor is a SvelteKit SPA that builds to static files served by sirv. No server-side rendering — everything runs in the browser.
lib/tltv/ TLTV protocol SDK (pure TypeScript, zero deps)
URI parsing, Ed25519 verification, channel resolution,
node discovery, peer exchange
lib/cathode/ Cathode management client (pure TypeScript)
Implements BackendAdapter interface — when other TLTV
servers appear, add a new adapter here
lib/themes/ Viewer theming via CSS custom properties
Built-in: Midnight, Phosphor Green, Broadcast, Ice Planet
Custom: import/export JSON, stored in localStorage
lib/stores/ Svelte 5 reactive state (runes)
The protocol SDK and cathode client are framework-free TypeScript with no Svelte imports. They're structured for extraction into standalone packages when needed.
Connect to a cathode instance at /control with URL + API key. If no playout backend is running at the target address, the connect form shows an error instead of entering a broken dashboard. Sidebar groups: Station, Content, Network, Settings (plus dynamic Plugins group when plugins are loaded).
Dynamic sidebar entries for each loaded plugin with dedicated settings pages.
The VITE_TLTV_NODE env var tells the dev server which TLTV node to use as the default hint for channel resolution (e.g. localhost:8888). Vite proxies /api/*, /hls/*, /tltv/*, and /.well-known/tltv to this address so local-mode viewing and management work without CORS issues.
In production this env var isn't needed — phosphor is served from the same origin as cathode, so location.host is the TLTV node.
TLTV channel IDs are Ed25519 public keys — cryptographic identifiers with no server information embedded. Resolution requires at least one hint about where to find the channel:
tltv://[email protected]:8888 Full URI with hint
tltv://TVxxx... Bare ID — resolves via local node + peer discovery
Resolution verifies Ed25519 signatures (rejects invalid), checks protocol version (v === 1), and follows migration documents (up to 5 hops). After tuning, metadata is refreshed every 60s to detect stream URL changes, name changes, and key migrations. The guide polls every 30s.
Themes control the viewer experience (player, channel bar, TV guide). The management dashboard uses a fixed admin look regardless of theme.
Built-in themes: Midnight (default), Phosphor Green, Broadcast, Ice Planet. Custom themes are JSON objects with CSS custom property overrides. See src/lib/themes/types.ts for the full token list.