Next.js Player (radio-web/)
The companion player is a minimal Next.js 16 (Turbopack) / React 19 application. It is deliberately focused: play the HLS stream, show the station, respect the user's theme.
Stack
| Piece | Value |
|---|---|
| Framework | Next.js 16 (Turbopack, App Router) |
| React | 19 |
| Stream | HLS — https://api.mediahubnetwork.net/loklok/index.m3u8 (same-origin cookie flow) |
| HLS playback | Native <audio>/<video> HLS on Safari/iOS; hls.js fallback for other browsers |
| hls.js source | jsDelivr CDN |
Key implementation points
HLS URL constant
The stream URL is a single constant at the top of app/player.jsx — the one
place to change when the MediaMTX endpoint moves.
Playback strategy
if (video.canPlayType('application/vnd.apple.mpegurl')) {
// native HLS (Safari, iOS)
} else {
// hls.js fallback for Chrome, Firefox, Edge, Android
}
Theme persistence
The theme is stored in localStorage('radio:theme'); the app reads it on boot and
persists changes, giving a consistent dark/light experience across sessions.
Running it
Dev
cd radio-web
npm run dev -- -p 3456
Production (start-player.sh)
A watchdog script (radio-web/start-player.sh) on the production node:
- Starts
next start -p 4477from/home/sms/radio/radio-web. - Monitors the process and restarts it if it dies.
- Wired into cron with
@reboot sleep 25. - Serves the compiled player app to listeners at
http://files.mediahubnetwork.net:4477/.
The app is a client-side page (app/page.jsx → app/player.jsx, pure CSS in
app/player.css — no Tailwind build). A .dark class on <html> toggles the
theme, persisted to localStorage('radio:theme').
Where it fits
- Stream source: MediaMTX HLS (
/loklok/index.m3u8). - Metadata: the classic pages' Socket.io feed is the canonical now-playing source; the player keeps to pure playback plus theme, staying small and fast.
- Note: Chrome may need hls.js for HLS support; the primary PWA (static page with hls.js + OGG fallback) is the more broadly-compatible player.
See also
- Streaming — the HLS ingest path.
- Classic pages — the Socket.io frontends.