## Project **Jam Session** A locally-hosted web application for collaborative music queuing at gatherings. People connected to the home network can add YouTube songs to a shared queue, vote on what plays next, and skip songs democratically — all without accounts or logins, using ephemeral nicknames valid for the session. The host machine plays the music through mpv + yt-dlp (ad-free), and playback survives server restarts because mpv runs as a separate process. **Core Value:** The music keeps playing no matter what — server crashes, disconnects, browser restarts, nothing should interrupt audio playback on the host machine. ### Constraints - **Tech stack**: Backend must run on Linux (host machine), control mpv via IPC, and serve a web UI - **Network**: LAN-only, no WAN exposure required - **Music source**: YouTube only for v1, with adapter pattern for future sources - **Auth**: None — ephemeral nicknames tied to session - **Playback**: mpv + yt-dlp for audio-only, ad-free YouTube playback - **Resilience**: mpv as separate process, web server must handle reconnection and state resync ## Technology Stack ## Recommended Stack ### Core Technologies | Technology | Version | Purpose | Why Recommended | |------------|---------|---------|-----------------| | Python | 3.12+ | Backend language | yt-dlp is a Python package — direct integration. Unix socket IPC, process management, and async I/O are all mature in Python. | | FastAPI | 0.115+ | Web framework | Built-in WebSocket support, async-first, automatic OpenAPI docs, lightweight. Pydantic models for request/response validation. | | uvicorn | 0.34+ | ASGI server | Production-grade async server for FastAPI with autoreload for development. | | yt-dlp | 2025.5+ | YouTube URL resolution | Python package. Extract audio stream URLs, metadata (title, duration, thumbnail). Ad-free by nature — resolves direct stream URLs, no browser embeds. | | mpv | 0.39+ | Audio playback engine | Runs as independent process, JSON IPC over Unix socket for control. Survives server restarts. `--vid=no` for audio-only mode. | ### Supporting Libraries | Library | Version | Purpose | When to Use | |---------|---------|---------|-------------| | python-socketio + aiohttp | latest | WebSocket abstraction | If you want higher-level WebSocket messaging with room/channel support instead of raw FastAPI WebSocket | | aiofiles | 24.1+ | Async file I/O | Saving/loading session state to disk | | Jinja2 | 3.1+ | HTML templating | Server-side rendering for the web UI (bundled with FastAPI) | | httpx | 0.28+ | Async HTTP client | If adding music source adapters that call external APIs | ### External Dependencies (System) | Tool | Purpose | Notes | |------|---------|-------| | mpv | Audio playback | Must be installed on host system. Use `--input-ipc-server=/tmp/jam-session-mpv.sock` for control. | | yt-dlp | YouTube extraction | Can be pip-installed as a package or used as CLI fallback. | | ffmpeg | Audio processing | Used internally by yt-dlp for format conversion. Install via system package manager. | ## Installation # Core Python packages # Optional: higher-level WebSocket abstraction # System dependencies (Fedora example) ## Alternatives Considered | Recommended | Alternative | When to Use Alternative | |-------------|-------------|-------------------------| | Python + FastAPI | Node.js + Express | If team is JS-only and doesn't mind yt-dlp child process overhead | | Python + FastAPI | Go + Fiber | If you want a compiled binary with zero Python dependency on the host | | Raw FastAPI WebSocket | python-socketio | If you want automatic reconnection, rooms, and event namespacing built in | | Vanilla JS frontend | Svelte or Solid | If the web UI grows complex enough to warrant reactive state management | | yt-dlp Python API | yt-dlp CLI via subprocess | If you prefer process isolation at the cost of parsing stdout | ## What NOT to Use | Avoid | Why | Use Instead | |-------|-----|-------------| | YouTube iframe embeds | Has ads, requires a browser open on host, no IPC control, can't survive server restarts | mpv + yt-dlp for direct audio stream playback | | Flask | Synchronous, no built-in WebSocket, clumsy async support | FastAPI (async-native, WebSocket built in) | | SQLite / PostgreSQL | Overkill for an ephemeral party queue stored in memory | In-memory Python data structures + optional JSON file persistence | | React / Next.js | Heavy for a simple queue UI. Build step complexity for a LAN party app. | Vanilla JS + WebSocket, or minimal Svelte | | Docker | Adds complexity for a local-only app. mpv needs direct audio device access anyway. | Run directly on the host | ## Stack Patterns by Variant - Use FastAPI with raw WebSocket endpoints - Vanilla JS frontend with `new WebSocket()` and DOM manipulation - Queue stored as Python list in memory - Jinja2 templates for HTML pages - Add proper REST API endpoints alongside WebSocket - Use Pydantic models for all data structures (reusable across web and GTK) - Keep WebSocket as the real-time transport, REST for CRUD operations - Define a `MusicSource` abstract base class with `resolve(url) -> AudioTrack` method - YouTube implementation as first adapter - Spotify/Apple Music as future implementations ## Version Compatibility | Package A | Compatible With | Notes | |-----------|-----------------|-------| | yt-dlp 2025.x | Python 3.10+ | Check yt-dlp release notes for Python version deprecations | | FastAPI 0.115+ | uvicorn 0.34+ | Standard pairing, always compatible | | mpv 0.39+ | JSON IPC protocol v1 | JSON IPC is stable across mpv releases | ## Sources - [mpv manual](https://mpv.io/manual/stable/) — JSON IPC protocol, command reference, option reference - [yt-dlp GitHub](https://github.com/yt-dlp/yt-dlp) — Python API embedding, format selection, supported sites - FastAPI docs — WebSocket endpoints, async patterns ## Conventions Conventions not yet established. Will populate as patterns emerge during development. ## Architecture Architecture not yet mapped. Follow existing patterns found in the codebase. ## Project Skills No project skills found. Add skills to any of: `.claude/skills/`, `.agents/skills/`, `.cursor/skills/`, `.github/skills/`, or `.codex/skills/` with a `SKILL.md` index file. ## GSD Workflow Enforcement Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync. Use these entry points: - `/gsd-quick` for small fixes, doc updates, and ad-hoc tasks - `/gsd-debug` for investigation and bug fixing - `/gsd-execute-phase` for planned phase work Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it. ## Developer Profile > Profile not yet configured. Run `/gsd-profile-user` to generate your developer profile. > This section is managed by `generate-claude-profile` -- do not edit manually.