# NoGood Radio Integration - Background Music Player ## Concept Add a **persistent music player** that plays NoGood Radio while users browse the app on desktop. Think of it like Spotify's mini-player, but for skate culture radio. --- ## How It Would Look (Desktop) ### Option 1: Bottom Bar Player (Spotify-style) ✅ RECOMMENDED ``` ┌──────────────────────────────────────────────────────┐ │ Regular App Content │ │ (Map, Spots, Events, etc.) │ │ │ │ │ │ │ └──────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────┐ │ 🎵 NoGood Radio 🔊──── ▶️ ⏸️│ │ Now Playing: Lo-Fi Skate Beats │ └──────────────────────────────────────────────────────┘ ↑ Persistent player bar (always visible) ``` **Layout Details:** ``` ┌───────────────────────────────────────────────────────────┐ │ 🎧 NoGood Radio | Now Playing: Chill Skate Mix | 🔊──────── | ▶️ ⏸️ 🔇 ✕ │ └───────────────────────────────────────────────────────────┘ ↑ ↑ ↑ ↑ Logo/Icon Track info Volume Controls ``` **Features:** - Sticks to bottom of screen - Plays while navigating between pages - Volume slider - Play/Pause button - Minimize/Close button - Shows current track/show name - Doesn't interrupt browsing --- ### Option 2: Floating Mini Player (Draggable) ``` Regular App Content ┌──────────────────────┐ │ 🎵 NoGood Radio │ │ ▶️ Lo-Fi Beats │ │ 🔊────── [–] [✕] │ └──────────────────────┘ ↑ Draggable, can be moved anywhere ``` **Features:** - Floats above content - User can drag to preferred position - Minimizes to small icon - Expands on hover - Less obtrusive than bottom bar --- ### Option 3: Sidebar Docked Player ``` ┌────────┬─────────────────────────────────┐ │ Nav │ Main Content │ │ Links │ (Spots, Events, etc.) │ │ │ │ │ ────── │ │ │ │ │ │ 🎵 ▶️ │ │ │ NoGood │ │ │ Radio │ │ │ │ │ │ 🔊──── │ │ └────────┴─────────────────────────────────┘ ↑ Docked in sidebar (desktop only) ``` **Features:** - Always visible in navigation - Compact vertical design - Doesn't cover content - Desktop-only (sidebar space) --- ## Detailed UI/UX Design (Option 1 - Bottom Bar) ### Collapsed State (Default) ``` ┌─────────────────────────────────────────────────────────────────┐ │ 🎧 NoGood Radio • Now Playing: Sunset Session Mix 🔊──── ▶️ [–]│ └─────────────────────────────────────────────────────────────────┘ ``` **Elements:** - **Logo**: 🎧 or NoGood brand icon - **Station name**: "NoGood Radio" - **Track info**: Scrolling text if too long - **Volume slider**: 🔊────── - **Play/Pause**: ▶️ / ⏸️ - **Minimize**: [–] (collapses to icon only) **Colors:** - Background: Dark gradient (matches app theme) - Accent: `#ccff00` (brand yellow) - Text: White/gray --- ### Minimized State (When User Clicks [–]) ``` ┌──────────────────┐ │ 🎧 ▶️ 🔊──── [+]│ └──────────────────┘ ↑ Small bar, bottom-right ``` **Elements:** - Just icon, play button, volume - Expand button [+] to restore - Stays out of the way --- ### Expanded State (When User Clicks for More Info) ``` ┌─────────────────────────────────────────────────────┐ │ 🎧 NoGood Radio [–] [✕]│ │ │ │ Now Playing: │ │ 🎵 Sunset Session Mix - Track 04 │ │ │ │ ▶️ ⏸️ | 🔊──────────── | 12:34 / 45:00 │ │ │ │ 📻 About NoGood Radio: │ │ Curated skate culture music 24/7 │ │ │ │ ⚡ Support NoGood │ │ [Zap 100] [Zap 500] [Zap 1000] │ │ │ │ 🔗 [Visit zap.stream] [Share Radio] │ └─────────────────────────────────────────────────────┘ ``` **Height**: ~250px (slides up from bottom) **Features**: - Show more info about current track - Zap button to support NoGood - Links to their platform - About section --- ## Mobile Experience **Recommendation**: **Don't show on mobile** **Why:** - Mobile users often have their own music playing - Takes up valuable screen space - Audio conflicts with phone calls - Data usage concerns - Better UX to keep mobile clean **How to detect**: ```typescript const isDesktop = window.innerWidth > 768; // Only render player if isDesktop === true ``` --- ## Technical Implementation ### Component Structure ``` App.tsx └─ Layout.tsx └─ AppRouter (pages) └─ RadioPlayer.tsx (NEW - conditional, desktop only) ``` ### RadioPlayer Component ```tsx import { useState, useRef, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { Slider } from '@/components/ui/slider'; import { Play, Pause, Volume2, VolumeX, Minimize2, Maximize2, X } from 'lucide-react'; export function RadioPlayer() { const [isPlaying, setIsPlaying] = useState(false); const [volume, setVolume] = useState(0.7); const [isMinimized, setIsMinimized] = useState(false); const [isExpanded, setIsExpanded] = useState(false); const [isMuted, setIsMuted] = useState(false); const audioRef = useRef(null); // Stream URL (NoGood Radio on zap.stream) const streamUrl = "https://stream.zap.stream/nogoodradio"; // Only show on desktop const isDesktop = window.innerWidth > 768; if (!isDesktop) return null; // Audio controls const togglePlay = () => { if (audioRef.current) { if (isPlaying) { audioRef.current.pause(); } else { audioRef.current.play(); } setIsPlaying(!isPlaying); } }; const handleVolumeChange = (value: number[]) => { const newVolume = value[0]; setVolume(newVolume); if (audioRef.current) { audioRef.current.volume = newVolume; } setIsMuted(newVolume === 0); }; const toggleMute = () => { if (audioRef.current) { audioRef.current.muted = !isMuted; setIsMuted(!isMuted); } }; return ( <> {/* Audio element (hidden) */}