Skip to main content

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

PieceValue
FrameworkNext.js 16 (Turbopack, App Router)
React19
StreamHLS — https://api.mediahubnetwork.net/loklok/index.m3u8 (same-origin cookie flow)
HLS playbackNative <audio>/<video> HLS on Safari/iOS; hls.js fallback for other browsers
hls.js sourcejsDelivr 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 4477 from /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.jsxapp/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