Files
muzick/docs/ui-rework.md
T

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.js theme.colors to 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-coded bg-zinc-900 etc. 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:

  1. Artwork servingalbums.artwork_id / Cover-Art URLs are stored but never served. Need GET /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.
  2. Playlists — the rail shows "Playlists"; there are no playlist tables/endpoints. Needs playlists + playlist_track schema and CRUD + reorder endpoints. (Net-new feature.)
  3. "Most Played" — derivable now via GET /api/tracks?sort_by=play_count&order=DESC. Wire a dedicated view/shelf.
  4. "Recently Added" — needs reliable mtime/created_at sorting (currently sorted client-side). Consider a created_at column + a sorted endpoint.
  5. "Made for you" mixes — map to the Vibe engine: per-genre/seed mixes via /api/vibe/from-genre and saved seeds. No new engine work, just presentation + maybe a "mixes" endpoint that returns a handful of seed suggestions.
  6. Folder browse — the rail shows "Folder"; there's no filesystem-browse endpoint. Needs a sandboxed GET /api/library/browse?path= under MUSIC_DIR (reuse the stream route's traversal guard). Optional / later.
  7. 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

  1. Tokenise theming — extend tokens + wire Tailwind to CSS vars; migrate existing components to semantic colour classes. (Unblocks real theming; low risk, high leverage.)
  2. AppShell + PlaybackBar + NowPlayingPanel — the structural 3-pane shell with the always-on transport and queue, reusing the current playback store/audio engine.
  3. MediaCard / Carousel / Artwork + artwork backend endpoint — make the content artwork-forward; redesign Home around Quick Access + shelves.
  4. Library/Discover/Vibe pages restyled onto the new components.
  5. 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?