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>
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.
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.
Qobuz's email/password API login returns 401 even with valid credentials
(a known Qobuz limitation, unaffected by streamrip version). Add settings
fields for a Qobuz user ID + auth token (token stored encrypted); when both
are present StreamripClient uses use_auth_token=True, else falls back to
email/password.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>