An explainable music-intelligence platform for finding a recording by title, artist, or remembered lyrics—and then following its artists, genres, versions, credits, provenance, and musical context.
- Progressive local-first search across editorial data, MusicBrainz, and Apple Music.
- Typed query intent (artist, track, lyrics, or mixed), confidence, provider health, filters, typo tolerance, result explanations, pagination, and measured latency.
- Explore, genre, artist, song, and side-by-side version comparison experiences.
- Private listening insights with diversity metrics and explainable recommendations.
- Versioned bookmarks, comparisons, and recent searches stored only in the browser.
- Rich song provenance, legal playback destinations, and authorized lyrics links.
- Optional exact Spotify links and ACRCloud audio or humming identification.
- A React and TypeScript client with resilient request caching and accessible routing.
- Optional Supabase authentication and private cross-device libraries.
- Optional Redis response caching, request coalescing, and assistant rate limits.
- A grounded OpenClaw discovery agent with structured citations and confidence labels.
- OpenTelemetry instrumentation, structured logs, and optional Sentry reporting.
The React/Vite client consumes versioned Zod contracts. The Node service classifies intent, returns local matches immediately, federates provider requests, normalizes results, deduplicates versions, and applies relevance ranking. A deterministic content-based engine turns browser-supplied profile metadata into taste metrics and recommendations with a human-readable reason for every result.
Every managed service is optional. Redis falls back to a bounded process-local cache; Supabase can add authenticated cross-device persistence; and the complete search, discovery, compare, and insights journey works without credentials.
Requires Node.js 22 or newer.
npm ci
npm run build:web
npm startOpen http://localhost:3000.
For separate hot-reload servers during development, run these in two terminals:
npm run dev
npm run dev:webThe API runs on port 3000 and Vite runs on port 5173.
The app works without a .env file. Optional integrations can be configured by
copying .env.example to .env.
Search combines three layers:
- The locally enriched catalog for detailed pages and remembered-lyric matching.
- MusicBrainz for broad open recording metadata.
- Apple Music's official Search API for commercial-catalog coverage, artwork, legal previews, and exact Apple Music track links.
No single provider contains every recording ever made. When one remote provider is unavailable, the others continue to return results.
The default profile never leaves the browser except as transient metadata sent to the recommendation endpoint; the server does not persist it. Bookmarks contain metadata and source URLs—not audio files. Liner Notes does not scrape or reproduce full lyrics. It links to authorized lyric destinations and labels unavailable capabilities honestly.
Copy .env.example to .env and add credentials as needed.
- Spotify client credentials resolve exact track URLs and add Spotify's 0–100 popularity score as a secondary search-ranking signal. Spotify does not expose lifetime stream totals through its public Web API, so the app never labels this score as a stream count. Without credentials, the interface provides a correctly encoded Spotify search link.
- ACRCloud credentials enable audio-file and humming identification.
- OpenClaw credentials enable a read-only assistant panel that can answer questions using the current search or song context.
MUSICBRAINZ_CONTACTidentifies this application in MusicBrainz API requests.
Credentials are used only on the server and are never exposed to browser code.
npm test
npm run test:e2eThe suite covers intent classification, explainable recommendations, local-first and federated contracts, relevance, provider normalization, deduplication, outages, caching, authentication boundaries, grounded-agent evaluation, and static assets. Playwright exercises search, song, comparison, and private-insights journeys on desktop and mobile Chromium and checks accessibility with Axe.
Run npm run benchmark to reproduce the local ranking benchmark. On the release
workstation, version 0.2.0 completed 100 representative searches at 0.168 ms p50,
0.344 ms p95, and 1.348 ms maximum. These figures measure only the in-process
ranking algorithm and do not represent network-provider or production latency.
Apply supabase/migrations/001_library.sql to a Supabase project, then configure
the three SUPABASE_* values. Set REDIS_URL to an Upstash Redis connection URL.
Secrets are read only by the server; never use the Supabase service-role key in a
Vite environment variable or browser bundle.
render.yaml defines the production web service. Configure secrets in Render,
deploy the Docker image, and use /api/health for readiness and /api/status for
provider, cache, and runtime diagnostics.
The repository includes a non-root production container and GitHub Actions checks.
docker build -t liner-notes-search .
docker run --rm -p 3000:3000 --env-file .env liner-notes-searchUse /api/health for readiness probes and /api/status for runtime and provider
configuration diagnostics. Secrets remain server-side environment variables.