2.6 KiB
Replace In-App Player with Navidrome Deep Link — Design Spec
Date: 2026-09-04 Status: Approved design, pending implementation Parent: docs/superpowers/specs/2026-09-03-wave1-hygiene-listening-design.md (supersedes its "Mini player" section)
Purpose
The built-in album player (global audio element + mini-bar) is removed. Listening happens in the user's Navidrome web UI; the item page links directly to the matched album there. Rationale: Navidrome's player is better than ours, and the in-app player added a global-audio architecture for a preview-quality experience.
Removals
web/src/player/(PlayerContext, MiniBar) and their tests; PlayerProvider/MiniBar wiring inweb/src/App.tsx- Backend stream/tracks/played routes (
server/src/routes/streamRoutes.ts) and their tests - api methods
getAlbumTracks,markPlayed,streamUrl; typesTrack,AlbumTracks; ItemPage'susePlayer/loadwiring and media mocks - Media-prototype mocks in
web/test/item.test.tsx(no audio element remains)
Changes
GET /api/collection/:iddetail —matchedAlbumgainswebUrl: string: the Navidrome album URL built server-side as<subsonic_url>/app/#/album/<subsonicId>(trailing slashes stripped from the configured base; null-safe —matchedAlbumstays null when unmatched, and when no Subsonic config existswebUrlis still constructed from the stored URL only if the album row exists; unmatched → null either way).- Item page — the ▶ Play album button becomes an anchor "Listen in Navidrome ↗" (
target="_blank"rel="noreferrer"), shown whenevermatchedAlbum != null(regardless of rip status — the album exists in Navidrome if it matched). - "Last played X ago" stays. Stamping now comes solely from library sync reading the server's recently-played list (
getAlbumList2?type=recent, opportunisticplayed/playedAtfield). No in-app stamping.
Unchanged
Stats, loans, rip queue, export/backup, sync, matching, all plan-1/2 APIs except the removed routes.
Error handling
No new failure modes. The link is a static anchor; a wrong Subsonic URL produces a broken link the same way a wrong URL breaks sync — surfaced by Settings, not the item page.
Testing
- Backend: detail test asserts
matchedAlbum.webUrl(http://n.local/app/#/album/<subsonicId>); stream tests deleted with the routes - Web: item tests assert the link (href + target) replaces the player tests; api.test drops the removed methods; player/minibar test files deleted
Manual device checklist
- Link opens Navidrome's album page from the phone (PWA → browser tab)