New /library: GET /api/library lists LibraryItems enriched with rgMbid + year
from the matching MonitoredRelease. Client renders a cover-art grid with a live
filter; clicking an album opens the AlbumModal (tracklist). Added Library to the
nav. The album-only overview to see everything downloaded.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Discography now has category tabs (All/Albums/Singles/EPs/Live/Comps/Other
with counts, defaults to Albums), cover-art thumbnails, and clicking an album
opens the AlbumModal with its tracklist. Detail GET gains ?all=true so the
client filters by tab (studio-only default still governs the artists-list
counts). Replaces the old flat date-sorted list + show-all toggle.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CoverArt loads album art from the Cover Art Archive CDN by release-group MBID
(browser-side, cached, graceful placeholder fallback). AlbumModal shows cover +
tracklist (fetched from MB) with slots for a status chip and context actions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Settings onto the Pressing Plant system: credentials with clear set/unset
affordances, a Library section that shows the configured /music path with a
"change MUSIC_DIR in docker-compose + rebuild" note (honest about the mount
being non-remountable from the UI), restyled scan trigger/result, and the
discovery section. All logic and aria-labels preserved. Completes the
frontend redesign (all pages + shell on one system, both themes).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Convert the remaining pages onto the Pressing Plant system: PageHead
component, shared list-row / toggle / small+ghost button / tracklist classes,
and page wrappers trimmed now that the shell provides masthead + nav. All
logic and test hooks (aria-labels, button text) preserved. Verified in the
real app across both themes (Playwright): artists/discover/wanted/discography
render cohesively with real data.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Home reads /api/requests + /api/wanted + /api/artists: summary tiles
(on the press / pressed / wanted / watching), the on-the-press job list
(state -> stripe + chip + stepped bar via describeJob; needs-attention shows
a literal recovery note), a request form (test hooks preserved), an empty
state, and a recently-pressed deadwax list. Verified in the real app (dark
desktop + mobile); light theme matches the approved comp.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root layout now wraps every page in the editorial column with a masthead
(wordmark + tagline + live worker dot) and a contents-bar nav with active
state via usePathname. Theme toggle stamps data-theme on <html> and persists
to localStorage. Pages no longer repeat the ad-hoc nav line.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
globals.css defines the manila/spruce palette as CSS custom properties for
both themes (prefers-color-scheme + explicit data-theme override), paper
grain, base reset, focus-visible, reduced-motion. Fraunces vendored as woff2
and wired via next/font/local with a Palatino/Georgia fallback.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wrap the WatchedArtist.create + MonitoredRelease.createMany in a
$transaction so a mid-write failure can't leave a followed artist with
no releases (a state the 409 duplicate-follow guard would then wedge).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each MB search result on /artists now links its name to
/discover/artist/[mbid] (the read-only disco + tracklist + own-state
preview), so you can preview before following there too — same wiring
the discovery feed already uses.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- preview-client want() no longer flips the Monitored badge when the POST fails
(deferred item #1 from the discovery-preview whole-branch review).
- README: discovery section notes the artist preview page.
- Plan Notes + project-state: TODO to reuse the preview page from the /artists
live search (wire artists-client.tsx hits to /discover/artist/[mbid]).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The placeholder algorithm string (contribution_5_threshold_15_limit_50) is not a
permitted enum member of the LB Labs endpoint — every lookup 400'd, making discovery
inert. Verified against the live API 2026-07-12: the days_7500/contribution_3/
threshold_10/limit_100 variant returns rows shaped {artist_mbid,name,comment,score},
which the existing defensive parser already handles. Fixed in both the worker adapter
and the web seed-search client (kept in sync).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the per-artist release-type filter toggle: off (default) restricts
a discography view to core studio releases, on shows everything
(live, compilations, etc.).
Type the POST request param (_request: Request) to match the test's
call signature and keep tsc --noEmit clean, per Next.js route handler
convention already used elsewhere in the codebase.
Test suites were running DELETE FROM.../deleteMany() against whatever
DATABASE_URL pointed to, which was the live app database, wiping user
credentials and library. Add a guard in both the worker conftest and
web test setup that raises before any cleanup unless the target DB
name ends in '_test'. Default DATABASE_URL to lyra_test when unset in
the worker, and make `npm test` target lyra_test explicitly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The worker's enqueue_due refuses to enqueue when a non-terminal job
already exists for a release. The search-now route enqueued
unconditionally, so two clicks (or a click racing the worker sweep)
could create two concurrent pipelines for the same album, both
importing and colliding on LibraryItem's @@unique([artist,album]).
Mirror the worker's guard: no-op if a job in a non-terminal state
(anything other than imported/needs_attention) already exists for the
release.