A sleek, dark-themed internet radio player with 50,000+ stations worldwide, mood-based discovery, country filtering, and favorites. Live at radio.recepguzel.com.
- Live streaming — play any of 50,000+ stations from the Radio Browser public API, no account required
- Search — search stations by name globally or scoped to a selected country
- Country filter — browse by country from the dropdown; Canada and Türkiye are pinned at the top
- Mood / AI curation — four mood presets (Focus, Chill, Night, Vibe) map to genre tags and surface matching stations
- Favorites — heart any station to save it; persisted in browser
localStorage(survives page reloads, device-local) - Media Session API — lock screen / Android Auto controls: play, pause, next, previous track
- Animated player bar — fixed footer with live signal indicator, bitrate, codec, and buffering state
Guzel Radio is also available as a native Android application with premium features:
- Download APK: Latest Release (guzel-radio.apk)
- Features:
- Android Auto support with Spotify-like "Now Playing" UI.
- Live RDS/Metadata (Artist - Song Title) support.
- First-run Wizard to select your preferred country.
- Edge-to-Edge immersive dark-mode UI.
- Nano Banana custom icon.
Experience Guzel Radio directly on your wrist with a standalone Wear OS application.
- Download APK: Latest Release (guzel-radio-wear.apk)
- Standalone Streaming: Play radio directly from your watch over Wi-Fi or LTE.
- Rotating Bezel Support: Adjust volume naturally using the physical bezel on Galaxy Watch Classic models.
- Media Controls: Full control over playback and station switching.
Since smartwatches lack USB ports, use "Sideloading" via Wi-Fi:
- Enable Developer Mode: On your watch, go to
Settings > About Watch > Software Infoand tapSoftware Version7 times. - Enable Wireless Debugging: In
Settings > Developer Options, turn onADB DebuggingandWireless Debugging. - Install via Phone (Easiest):
- Install the Bugjaeger app on your Android phone.
- Connect to your watch's IP address (found in Wireless Debugging settings).
- Select
guzel-radio-wear.apkand tap Install.
- Install via PC:
adb connect [WATCH_IP] adb install guzel-radio-wear.apk
| Layer | Library |
|---|---|
| UI framework | React 19 |
| Build tool | Vite 6 |
| Styling | Tailwind CSS 4 |
| Animations | Motion (Framer Motion) |
| Icons | Lucide React |
| Station data | radio-browser.info public API |
No backend, no database — fully static SPA.
src/
├── App.tsx # Main component — all UI, state, playback logic
├── main.tsx # React entry point
├── index.css # Global styles / Tailwind base
├── types.ts # RadioStation and PlaybackState interfaces
└── services/
├── radioService.ts # radio-browser.info API calls
└── geminiService.ts # Mood → genre mapping (static, no external API call)
Prerequisites: Node.js 18+
npm install
npm run dev # starts on http://localhost:3000Other scripts:
npm run build # production build → dist/
npm run lint # TypeScript type check
npm run preview # preview production build locallyNo API keys needed — the radio-browser.info API is public and free.
The live site is hosted on a self-managed server behind nginx with Let's Encrypt TLS.
Push to main → GitHub webhook fires → deploy.sh on the server clones the repo, builds inside a node:20-alpine Docker container, and rsyncs the output to the nginx document root. Manual deploy:
bash ~/radio/deploy.shAll station data comes from the Radio Browser API:
| Endpoint | Purpose |
|---|---|
/json/stations/topclick/{n} |
Trending stations |
/json/stations/byname/{query}?country=X |
Name search with optional country filter |
/json/stations/bycountry/{country} |
All stations in a country |
/json/stations/bytag/{tag} |
Stations by genre tag (used by mood curation) |
Stored in browser localStorage under the key waveform_favorites as a JSON array of station objects. Device-local — clearing browser storage removes them.