diff --git a/docs/superpowers/specs/2026-04-24-web-ui-player-design.md b/docs/superpowers/specs/2026-04-24-web-ui-player-design.md new file mode 100644 index 00000000..d0bb44bc --- /dev/null +++ b/docs/superpowers/specs/2026-04-24-web-ui-player-design.md @@ -0,0 +1,423 @@ +# Web UI Player — Design Spec + +**Date:** 2026-04-24 +**Status:** Design approved +**Follows:** [Web UI Library Views](2026-04-23-web-ui-library-views-design.md) — tracks surfaced by the library plan finally become playable. + +## Goal + +Let an authenticated user click any track on an album page and hear it — plus skip/seek/shuffle/repeat/volume, a persistent bottom-bar UI, and OS-level media controls via the MediaSession API. After this lands, the web client is a functional music player for sequential playback through the library. + +## Non-goals + +Explicit YAGNI — kept out of this plan so scope stays tight: + +- **No server-side listen-history recording.** The spec's `play_events` / `sessions` tables exist in the server design but no `/api/*` endpoints are implemented yet. Once those land, a follow-up "session reporting" sub-plan wires the player to POST events. +- **No scrobbling to ListenBrainz.** Dependent on server event endpoints + scrobble queue — later plan. +- **No contextual likes or "like this vibe".** Out of scope until session reporting exists. +- **No cross-refresh persistence.** Reload drops playback state (queue, position, current track). Volume is the only thing that persists. +- **No queue UI / "up next" panel.** The user sees the current track in the bar; they don't get a separate list view of what's coming. Queue visibility is a natural follow-up. +- **No keyboard shortcuts.** Space/arrow keys don't control playback in this plan — a separate "keyboard shortcuts" sub-plan will add them. +- **No crossfade, gapless playback, replay-gain, equalizer.** Baseline HTMLAudio only. +- **No cast / AirPlay / Chromecast.** Browser-local playback only. +- **No keyboard-driven seeking beyond the native `` behavior.** + +## Architecture + +**Single global player store** as a Svelte 5 rune module — imported by `+layout.svelte`, `Shell`, `PlayerBar`, and `TrackRow`. The store is pure state + action functions; it never touches the `