MusicSeed — Dependency & Workflow Architecture
React web surface + standalone REST API · August 2026 · SQLite only No Docker No ML runtime REST API Next.js web
This document explains every dependency MusicSeed relies on today — Python packages, data stores, network services — and how data flows through the four main workflows (import, enrich, sonic retrieval, recommend) and the two surfaces (CLI, and the Next.js web UI via the REST API). It exists to track how small the install surface has become, so publishing MusicSeed as open source means a new user needs as little as possible.
socket only;
servers on other subnets are found through the optional plex.tv/api/resources
account lookup (httpx, needs a Plex token). uv is development-only tooling — the
end-user install is plain python3 -m venv + pip. That's the whole
thing — no server, no containers, no native ML libraries.
1. The big picture
Python packages (core)
6
sqlalchemy, pyyaml, httpx, numpy, pydantic, rich — all pure-Python or widely pre-built wheels.
Python packages (surfaces)
2 + 3 + Node
cli: typer, rich · api: fastapi, uvicorn, python-multipart · web: next, react, react-dom (Node). Web talks to api over HTTP; api and cli depend on core via editable paths.
External processes
0
No database server, no container runtime, no daemon. Plex itself is the only assumed service.
2. Dependency ledger (before → after)
Python packages
| Package | Role | Status |
|---|---|---|
| sqlalchemy | ORM over the SQLite state file | kept core |
| httpx | HTTP to Plex API + ListenBrainz/MusicBrainz/Spotify | kept core |
| numpy | Sonic vector math (matmul, cosine) at query time | kept core |
| pydantic | Config + service result models | kept core |
| pyyaml | config.yaml loading | kept core |
| rich | Progress rendering inside import/enrich pipelines | kept core |
| typer | CLI framework | kept cli |
| fastapi | REST API request handling | kept api |
| uvicorn | ASGI server for the API | kept api |
| python-multipart | HTML form parsing (setup wizard, credential forms) | kept api |
| next / react / react-dom | Next.js + React client-rendered web UI (Node) | kept web |
| jinja2 | Server-rendered templates | removed · React rewrite |
| htmx (vendored file) | Fragment updates without a JS build step | removed · React rewrite |
| essentia-tensorflow | Self-generated audio embeddings (MusiCNN) | removed · Phase 1 |
| psycopg[binary] | PostgreSQL driver | removed · Phase 3 |
| pgvector | Vector column type + cosine-distance query | removed · Phase 2 |
Infrastructure & system requirements
| Component | Former role | Status |
|---|---|---|
| PostgreSQL 16 server | MusicSeed state database | removed · Phase 3 |
| Docker / docker-compose | Ran the Postgres container | removed · Phase 3 |
| pg_trgm extension | Trigram indexes (never queried) | removed · Phase 3 |
| TensorFlow runtime | Pulled in by essentia; amd64-only | removed · Phase 1 |
| Audio-file access | Reading music files to embed them | removed · Phase 1 |
| Stored embeddings | Vector(200) column, zero-padded from 50 | removed · Phase 2 |
What remains external (and can't be removed)
| Dependency | Why it exists | Access |
|---|---|---|
| Plex metadata DB | Source of truth for artists/albums/tracks/tags/play history | read-only, stdlib sqlite3 |
| Plex blobs DB | Plex's own 50-dim sonic analysis vectors | read-only, at query time |
| Plex HTTP API | Creating/populating playlists; triggering sonic analysis | optional, token-gated |
| ListenBrainz / MusicBrainz | Popularity enrichment via recording MBIDs | optional, rate-limited |
| Spotify Web API | Fallback popularity/metadata when MBIDs are missing | optional, credentialed |
sonic.py → SonicVectors) when a recommendation runs. Nothing is copied, embedded,
or indexed — so there is no vector column, no ANN index, and no embedding pipeline to maintain.
3. Workflows
3.1 Import — Plex metadata → musicseed.db
musicseed import — one-way copy of artists, albums, tracks, genres, moods, styles, play history. The Plex file is never written to.3.2 Enrich — popularity signals (async, resumable)
musicseed enrich --source listenbrainz|spotify — attempted tracks are flagged so interrupted runs resume. This is the only workflow that spends third-party API calls, which is why old Postgres data was migrated rather than re-fetched.3.3 Sonic retrieval — vectors at query time (no storage)
3.4 Recommend — six signals, explainable
musicseed recommend previews; playlist / populate ask for confirmation, then write to Plex over the HTTP API — the only workflow that mutates anything outside musicseed.db.4. What a brand-new user needs (open-source readiness)
Prerequisites
· Python 3.12+, SQLite 3, Node.js/npm (install only)
· Plex Media Server with a music library, sonically analyzed
· Optional: Spotify API credentials (fallback enrichment only)
Install (from a git clone)
./scripts/install.sh
musicseed then open http://127.0.0.1:8789
The first-run wizard discovers Plex, initializes the database, and walks through import/enrichment. Node is not needed after install.
Still on the road to pip install musicseed
| Gap | Notes |
|---|---|
| PyPI packaging | core + cli + web are separate distributions joined by editable paths; decide on one combined package or publish them all. |
| Plex DB discovery | Server discovery is solved (GDM/SSDP; plex.tv/api/resources for other subnets). On-disk db_path probes macOS and Linux candidates; Windows is untested. |
| Sonic analysis coverage | Recommendation quality depends on Plex having analyzed the library; sonic-probe reports coverage, sonic-refresh triggers the Butler task. |
5. Verify the current state
cd core && uv run ruff check src
cd api && uv run ruff check src && uv run pytest tests -q
cd cli && uv run ruff check src && uv run pytest tests -q
cd web && npx tsc --noEmit && npm run lint
python3 -m compileall -q core/src/musicseed api/src/musicseed_api cli/src/musicseed_cli
cd cli && uv run musicseed-cli init-db # creates the SQLite file
uv run musicseed-cli status # shows DB path + file size
uv run musicseed-cli recommend --seed-id 123 --limit 20 --explain