The Northern projects / tesla-plex

tesla plex player

A lightweight, dark-themed Plex music player built for Tesla's in-car browser.
active
๐Ÿ”’ The live player sits behind a passphrase and connects to a personal Plex server, so public access isn't the point โ€” this page is a walkthrough of how it's built.

A single static HTML file that streams directly from a Plex server over the car's Wi-Fi or LTE, with touch targets sized for driving gloves and a color palette that disappears into the dashboard. Zero dependencies, no build step, ~60 KB of HTML, CSS, and JavaScript talking to the Plex REST API directly from the browser.

Credentials stay in localStorage, encrypted with AES-256-GCM and unlocked with a passphrase โ€” a shared car never has the library token in plaintext on disk.

Why not the built-in apps?

Tesla ships Spotify, TIDAL, and a few others โ€” but none of them see a self-hosted Plex library. Lossless FLACs, niche live recordings, ripped CDs, the post-rock archive that doesn't stream anywhere โ€” all of it lives on Plex. This is the bridge.

The cache โ€” the real trick

Driving through canyons, tunnels, or out-of-coverage stretches would normally kill streaming playback. So the player aggressively pre-caches upcoming tracks in the background: while you're listening to track 1, tracks 2โ€“5 are already decoded and sitting in memory as Blob URLs, ready to play the instant you hit next โ€” or the instant the car loses signal.

Serial download queue

All transcode requests route through a single global queue with a 5-second gap between requests. Plex only tolerates one transcode per client ID at a time; anything parallel causes truncated audio.

Per-browser tuning

Chromium (Tesla) holds up to 10 MP3 blobs (~5 MB each, ~50 MB total). Safari caches 3 decoded WAVs (~40 MB each) to sidestep its audio limits.

Near-gapless transitions

Because the next track is already decoded, skipping is effectively instant โ€” no network round-trip, no transcode wait. Not true gapless, but close.

Truncation detection

Frame-based validation on every download. Short files (especially long live recordings) auto-retry once in the same cache slot; double failures self-heal on the next cycle.

Artwork pre-warmed too

Album art thumbnails are preloaded into the browser image cache during track pre-cache, so the "Now Playing" view never shows a broken image when signal drops.

Online/offline handoff

Listens to the browser's online/offline events. When the car drops signal mid-drive, cached tracks keep playing; reconnect is transparent when signal returns.

Built for the dashboard

Audio only, no video

Tesla allows audio while driving but blocks video playback. The player is <audio>-only by design โ€” no HTML5 video element ever.

Giant touch targets

Everything is sized for a phone-sized thumb through a glove. No dropdowns, no hover states, no tooltips โ€” tap targets are 48px+ minimum.

Dark palette

Near-black background with soft foreground contrast. Designed to blend with the dashboard at night and reduce glare during daytime driving.

Browse & search

Artists, albums, playlists, recently added. Full-library search across artists, albums, and tracks โ€” results paginated and lazily loaded.

Queue & shuffle

Build a play queue, reorder, shuffle, or just let the current album ride out. Queue state survives page reloads via localStorage.

Encrypted credentials

Server URL, relay URL, and Plex token are sealed in an AES-256-GCM blob in localStorage. Unlock with a passphrase โ€” nothing in plaintext on disk.

No phone required

Pure web app. Open the URL in Tesla's browser, unlock, and drive. No pairing, no Bluetooth, no aux.

AI DJ

A Pages Function that asks Claude Haiku to build a 30-track queue from a mood or free-text prompt, using the user's actual Plex library as context. The browser sends the prompt + Plex token to the function; the function pulls library metadata (artists, genres, play counts), asks Claude for a ranked artist/genre list, then materializes that into a real track queue from Plex. Tap a preset or type whatever you want to hear.

๐ŸŒ™ Night drive โ˜€๏ธ Morning ๐Ÿ”๏ธ Focus ๐ŸŽ‰ Energy ๐Ÿ˜Œ Unwind ๐ŸŽน Classical mood
Keyboard shortcuts
Space play / pause โ† โ†’ seek ยฑ10s โ‡ง โ† / โ†’ prev / next โ†‘ โ†“ volume S shuffle / search
Stack

Single index.html (~60 KB, zero deps) served from Cloudflare Pages ยท Plex REST API over HTTPS ยท Web Crypto for AES-256-GCM with PBKDF2 (100k iterations, SHA-256) ยท localStorage for encrypted credential blob and queue state ยท Pages Functions + Claude Haiku for the AI DJ.

HTML Plex API Cloudflare Pages Pages Functions Claude Haiku Web Crypto Tesla