182 lines
4.2 KiB
Markdown
182 lines
4.2 KiB
Markdown
# RadioPlayer
|
|
|
|
RadioPlayer is a Vite + React web app for browsing, playing, and casting radio stations.
|
|
It uses a managed catalog from `public/stations.json`, exposes a same-origin managed endpoint at `/api/managed-stations.json`, supports user stations with local persistence, and includes scripts to refresh station data from Radio.si.
|
|
|
|
## Features
|
|
|
|
- Station library with search, category tabs, favorites, recents, sorting, and pagination.
|
|
- Country filtering plus a country picker to choose which Radio Browser countries are synced and shown.
|
|
- Audio playback with previous/next controls, volume/mute, and coverflow quick picks.
|
|
- Google Cast and AirPlay output support.
|
|
- User station management with local import/export/reset tooling.
|
|
- Managed catalog fallback chain: remote endpoint -> cached remote -> bundled `stations.json`.
|
|
- Production service worker with app shell caching, station sync cache, and periodic refresh registration.
|
|
- PWA install prompt and offline-friendly launch behavior.
|
|
|
|
## Requirements
|
|
|
|
- Node.js 18+
|
|
- npm
|
|
- For production managed endpoint: PHP-enabled web server with rewrite support (Apache + `.htaccess` in this repo)
|
|
|
|
## Getting Started
|
|
|
|
Install dependencies:
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
Run development server:
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
Build for production:
|
|
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
Preview production build locally:
|
|
|
|
```bash
|
|
npm run preview
|
|
```
|
|
|
|
Deploy built assets with the included script:
|
|
|
|
```bash
|
|
bash sync.sh
|
|
```
|
|
|
|
## Managed Catalog Endpoint
|
|
|
|
Runtime managed endpoint path:
|
|
|
|
```text
|
|
/api/managed-stations.json
|
|
```
|
|
|
|
In production this is served by:
|
|
|
|
- `public/.htaccess` rewrite rule
|
|
- `public/api/managed-stations.php`
|
|
|
|
Response shape:
|
|
|
|
```json
|
|
{
|
|
"schemaVersion": 1,
|
|
"updatedAt": "2026-04-29T07:39:58.374Z",
|
|
"stations": []
|
|
}
|
|
```
|
|
|
|
In dev/preview, Vite middleware in `vite.config.js` serves the same envelope from `stations.json`.
|
|
|
|
If the endpoint is unavailable, frontend and service worker fall back to bundled `public/stations.json`.
|
|
|
|
## Station Data Refresh
|
|
|
|
Refresh managed stations from Radio.si:
|
|
|
|
```bash
|
|
npm run update:stations
|
|
```
|
|
|
|
Refresh and rebuild in one command:
|
|
|
|
```bash
|
|
npm run update:stations:build
|
|
```
|
|
|
|
Custom source and output:
|
|
|
|
```bash
|
|
node scripts/update-stations.mjs <source-url> <output-path>
|
|
```
|
|
|
|
## Cron Automation (Server)
|
|
|
|
Helper script:
|
|
|
|
```bash
|
|
bash scripts/cron-refresh-stations.sh
|
|
```
|
|
|
|
Update-only helper script:
|
|
|
|
```bash
|
|
bash scripts/cron-update-stations.sh
|
|
```
|
|
|
|
The script:
|
|
|
|
- acquires a lock file to prevent overlapping runs,
|
|
- runs station refresh and build,
|
|
- optionally runs `DEPLOY_CMD`,
|
|
- writes logs to `/tmp/radioplayer-refresh-stations.log` by default,
|
|
- rotates logs automatically when they exceed 1 MB, keeping 5 archives by default.
|
|
|
|
The update-only script:
|
|
|
|
- acquires its own lock file,
|
|
- runs only `npm run update:stations`,
|
|
- optionally runs `POST_UPDATE_CMD`,
|
|
- writes logs to `/tmp/radioplayer-update-stations.log`,
|
|
- uses the same log rotation behavior.
|
|
|
|
Example crontab (every 6 hours):
|
|
|
|
```cron
|
|
0 */6 * * * REPO_DIR=/opt/www/virtual/RadioPlayer DEPLOY_CMD='rsync -av --delete /opt/www/virtual/RadioPlayer/dist/ /opt/www/virtual/RadioPlayer/' /opt/www/virtual/RadioPlayer/scripts/cron-refresh-stations.sh
|
|
```
|
|
|
|
Example update-only crontab (every 2 hours):
|
|
|
|
```cron
|
|
0 */2 * * * REPO_DIR=/opt/www/virtual/RadioPlayer /opt/www/virtual/RadioPlayer/scripts/cron-update-stations.sh
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```text
|
|
index.html
|
|
privacy.html
|
|
package.json
|
|
public/
|
|
.htaccess
|
|
api/
|
|
managed-stations.php
|
|
data/
|
|
radio-stations.json
|
|
radio-stations-sync.json
|
|
manifest.json
|
|
stations.json
|
|
sw.js
|
|
scripts/
|
|
bump-sw-cache-version.mjs
|
|
cron-refresh-stations.sh
|
|
cron-update-stations.sh
|
|
import-radio-stations.ts
|
|
update-stations.mjs
|
|
src/
|
|
App.jsx
|
|
main.jsx
|
|
player.js
|
|
styles.css
|
|
radio/
|
|
storage/
|
|
```
|
|
|
|
## Notes
|
|
|
|
- Service worker is only active in production builds. In dev, SW registrations and caches are cleared automatically.
|
|
- `src/main.jsx` registers background sync / periodic sync where supported.
|
|
- `src/player.js` also refreshes managed catalog on app focus after a timeout (fallback for browsers without periodic sync).
|
|
- `sync.sh` deploys `dist/` only.
|
|
- If you edit stations manually, rerun `npm run update:stations` to resync from upstream when needed.
|