# RadioPlayer RadioPlayer is a Vite + React web app for browsing, playing, and casting radio stations. It loads its bundled managed catalog from `public/stations.json`, exposes that catalog through a same-origin backend endpoint at `/api/managed-stations.json`, supports custom stations, and includes a built-in updater for refreshing the managed list from the live Radio.si feed. ## Features - Station browser with search, categories, favourites, and recent stations - Audio playback with previous/next station controls - Cast support - Production service worker for app-shell caching, offline launch support, and faster repeat visits - App install prompt for supported browsers - Custom station editor - Live station metadata and artwork rendering ## Requirements - Node.js 18 or newer - npm ## Getting Started Install dependencies: ```bash npm install ``` Start the development server: ```bash npm run dev ``` Build for production: ```bash npm run build ``` Preview the production build: ```bash npm run preview ``` Run the production build with the bundled same-origin backend endpoint: ```bash npm run serve:backend ``` Deploy the built frontend plus backend server files to the remote host: ```bash bash sync.sh ``` ## Station Data The app keeps the editorial managed list in `public/stations.json`. At runtime, the frontend prefers the same-origin managed endpoint: ```text /api/managed-stations.json ``` That endpoint returns: ```json { "schemaVersion": 1, "updatedAt": "2026-04-29T07:39:58.374Z", "stations": [] } ``` If the backend endpoint is unavailable, the frontend and service worker fall back to the bundled `stations.json` file. To refresh the file from the remote source, run: ```bash npm run update:stations ``` That command fetches the latest station list from: ```text https://data.radio.si/api/radiostations?857df78efd094abcb98c7bbb53303c3d ``` and rewrites `public/stations.json` while preserving the existing JSON structure used by the app. The backend endpoint reads from that file and wraps it in the runtime envelope shown above. You can also pass a custom source URL or a custom output path if needed: ```bash node scripts/update-stations.mjs ``` ## Project Structure ```text index.html package.json public/ manifest.json stations.json sw.js server/ index.mjs managedCatalogData.mjs src/ App.jsx main.jsx player.js styles.css scripts/ update-stations.mjs ``` ## Notes - The app uses a module-based frontend build, so `src/main.jsx` is the browser entry point. - The service worker is registered only in production builds. During development, existing service workers and caches are cleared automatically to avoid stale assets while iterating. - The updater script uses the remote feed as the source of truth for the station list and writes the merged result into `public/stations.json`. - Vite dev and preview both expose `/api/managed-stations.json` on the same origin via middleware, and `npm run serve:backend` serves the built app plus the same endpoint from Node. - `sync.sh` now deploys both the built frontend files and the `server/` runtime so the same-origin backend can be started remotely with `node /opt/www/virtual/RadioPlayer/server/index.mjs`. - If you add or edit stations manually, re-run `npm run update:stations` when you want to sync back to the remote catalog. - Static-only deployments still work because the frontend falls back to bundled `stations.json`, but a true same-origin backend endpoint requires deploying a server that answers `/api/managed-stations.json`.