9.1 KiB
UI Rework Plan
Status: planned, not started. This document captures the target direction for a richer player UI (reference: the "LocalTunes" three-pane mockup) and what it implies for both the frontend and the backend. It is a plan to execute later, not a description of the current app.
1. Vision
Move from the current functional-but-plain single-content-column layout to a polished, artwork-forward three-pane music player in the spirit of modern desktop players (Spotify / Apple Music / the LocalTunes reference):
- Left: persistent navigation rail (library sections + a personal/"your music" group).
- Center: scrollable content (Home, Library, Vibe, etc.) — artwork-rich cards, horizontal carousels, hover-to-play.
- Right: persistent Now Playing panel — large artwork, track info, transport, and an Up Next / queue list.
- Bottom: full-width global playback bar (shuffle / prev / play / next / repeat, scrubber, volume, queue toggle) that's always visible regardless of route.
- Top: global search field + (future) user/account menu.
Accent-driven, rounded, soft-gradient cards; dark by default but fully themeable via tokens.
2. Layout structure
┌────────────────────────────────────────────────────────────────────────────┐
│ Top bar: [logo] [ global search ⌘K ] [bell] [avatar ▾] │
├───────────────┬────────────────────────────────────────────┬───────────────┤
│ Nav rail │ Content (router Outlet) │ Now Playing │
│ - Home │ Good evening 👋 │ [ artwork ] │
│ - Songs │ Quick Access cards │ Title/Artist │
│ - Albums │ Recently Played (carousel, View all) │ scrubber │
│ - Artists │ Made for you (mixes carousel) │ transport │
│ - Genres │ ... │ Up Next list │
│ - Playlists │ │ │
│ - Folder │ │ (collapsible)│
│ ────────── │ │ │
│ Now Playing │ │ │
│ Recently … │ │ │
│ Most Played │ │ │
│ Favorites │ │ │
│ ────────── │ │ │
│ Settings │ │ │
│ Theme │ │ │
│ About │ │ │
├───────────────┴────────────────────────────────────────────┴───────────────┤
│ Bottom bar: [art] Title/Artist ♥ ⇄ ◀ ▶▶ ⏯ ▶▶ ↻ 🔊────── queue ▤ │
└──────────────────────────────────────────────────────────────────────────────┘
The right Now-Playing panel and the bottom bar are partly redundant by design (desktop players do this): the bottom bar is the always-on minimal transport; the right panel is the expanded view with queue and large art, and is collapsible.
3. Design tokens / theming
This rework is the right moment to finish theming. Today only the shell consumes tokens
(--bg, --surface, --text, --accent from src/lib/theme.ts). Target:
- Expand the token set:
--bg,--bg-elevated,--surface,--surface-hover,--border,--text,--text-muted,--accent,--accent-hover,--on-accent, plus gradient stops for cards (--card-grad-a/b). - Drive Tailwind from the tokens: extend
tailwind.config.jstheme.colorsto reference the CSS variables (e.g.bg: 'var(--bg)',surface: 'var(--surface)',accent: 'var(--accent)') so components use semantic classes (bg-surface,text-muted,bg-accent) instead of hard-codedbg-zinc-900etc. This makes every component themeable without per-component edits. - Keep the existing presets (Dark / Midnight / Forest / Plum), add a light option, and keep
initTheme()applying the persisted choice before first paint. - The reference's purple accent → add a "Default (Purple)" preset.
4. Component inventory (new / reworked)
| Component | Purpose |
|---|---|
AppShell |
3-pane grid (rail / content / now-playing) + top bar + bottom bar. Replaces Layout. |
NavRail |
Sections + personal group + settings group; active state via --accent. |
TopBar |
Global search (debounced, ⌘K focus), account menu (stub until auth). |
NowPlayingPanel |
Right rail: large art, info, scrubber, transport, Up Next queue (reorder/remove). Collapsible. |
PlaybackBar |
Bottom global transport (always visible). Reworks NowPlayingBar. |
MediaCard |
Square artwork card with hover play overlay (used by carousels + grids). |
Carousel / ShelfRow |
Horizontal scroll row with title + "View all". |
QuickAccessCard |
Wide gradient card (Favorites / Recently Added / Most Played / Folder). |
TrackRow |
Reusable list row (replaces the per-page LibraryTrackRow) with art, actions, now-playing highlight. |
Artwork |
Resolves album/track artwork URL with a graceful gradient placeholder fallback. |
State: keep Zustand usePlaybackStore (current/queue/isPlaying/position/volume) and
useVibeStore; add a small useUiStore for panel collapse + theme if useful. The Up Next
list is just the playback queue.
5. Backend work this UI implies (gaps)
The mockup assumes data we don't serve yet. Each is a discrete backend task:
- Artwork serving —
albums.artwork_id/ Cover-Art URLs are stored but never served. NeedGET /api/albums/:id/artwork(and/or per-track) that streams/redirects to the cached cover, plus a placeholder when absent. Without this every card is a gradient placeholder. - Playlists — the rail shows "Playlists"; there are no playlist tables/endpoints. Needs
playlists+playlist_trackschema and CRUD + reorder endpoints. (Net-new feature.) - "Most Played" — derivable now via
GET /api/tracks?sort_by=play_count&order=DESC. Wire a dedicated view/shelf. - "Recently Added" — needs reliable
mtime/created_atsorting (currently sorted client-side). Consider acreated_atcolumn + a sorted endpoint. - "Made for you" mixes — map to the Vibe engine: per-genre/seed mixes via
/api/vibe/from-genreand saved seeds. No new engine work, just presentation + maybe a "mixes" endpoint that returns a handful of seed suggestions. - Folder browse — the rail shows "Folder"; there's no filesystem-browse endpoint. Needs
a sandboxed
GET /api/library/browse?path=underMUSIC_DIR(reuse the stream route's traversal guard). Optional / later. - Typesense search — the redesigned top-bar search wants fast fuzzy results; finish the
Typesense indexing pipeline (collection + reindex job + index-on-enrich) so search graduates
from the Postgres ILIKE fallback. (Already tracked in
progress.md.)
6. Suggested phasing
- Tokenise theming — extend tokens + wire Tailwind to CSS vars; migrate existing components to semantic colour classes. (Unblocks real theming; low risk, high leverage.)
- AppShell + PlaybackBar + NowPlayingPanel — the structural 3-pane shell with the always-on transport and queue, reusing the current playback store/audio engine.
- MediaCard / Carousel / Artwork + artwork backend endpoint — make the content artwork-forward; redesign Home around Quick Access + shelves.
- Library/Discover/Vibe pages restyled onto the new components.
- New features as desired: Playlists, Folder browse, Most Played/Recently Added shelves, Typesense search.
7. Non-goals (for the first rework pass)
- Auth / multi-user (still single-user).
- Mobile/responsive layout (target desktop first; the 3-pane collapses later).
- Real-time collaborative features.
8. Open questions
- Keep both the right Now-Playing panel and the bottom bar, or collapse to one? (Plan assumes both, panel collapsible.)
- Artwork storage: serve via a backend proxy/cache, or store files locally and serve static?
- Playlists: is this in scope for the rework, or a separate feature track?