# 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 serving** — `albums.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?
