Music Hub Architecture
Version: v0.1.1
Last Updated: 2026-03-20
Overview
Music Hub is a local-first music system with one desktop hub as the source of truth:
desktop/: Electron app plus the backend APImobile/: Expo / React Native companionlanding/: public marketing sitedocs/: this documentation site
The desktop app owns scanning, metadata, database persistence, streaming, pairing, and remote/share entrypoints.
Runtime shape
desktop/
electron/main.cjs Electron shell + splash + app lifecycle
src/index.ts Express server bootstrap
src/api/index.ts Canonical API entrypoint
src/api/routes.ts Main route surface
src/database/ Active native SQLite runtime
src/scanner/ Folder scanning
src/metadata/ Embedded tag extraction
src/enrichment/ Background enrichment pipeline
src/streaming/ Direct + HLS playback
src/auth/ Pairing + refresh-token flow
src/media-access/ Signed media/share sessions
src/tunnel/ Cloudflare + embedded Tailscale
ui-src/ React rendererThe historical desktop/src/core/database tree still exists as an archived sql.js prototype, but the active runtime uses desktop/src/database.
Core data flow
Scan and ingest
- User adds one or more folders.
- Scanner walks the filesystem and compares it against the indexed set.
- Metadata extraction reads embedded tags and artwork.
- The desktop DB stores tracks, artists, albums, playlists, saved state, playback state, and enrichment data.
- The UI receives updates over SSE.
Playback
- Clients read the shared playback session from
/api/playback/session. - Local-safe formats can use direct streaming.
- Remote and public-share playback use HLS or signed media routes.
- Playback session, queue, and history are persisted in the hub DB so desktop and mobile can restore state.
Sharing
- A share page loads only public bootstrap data.
- Bootstrap returns a short-lived
shareSessionIdandmediaToken. - The share client renews the session with
/api/share/session/heartbeat. - Audio/artwork requests are authorized through the issued media token.
Networking and trust model
The desktop backend now has an explicit trust boundary:
- Loopback requests are treated as local admin traffic.
- Forwarded or non-loopback requests are treated as remote.
- Remote
/api/*access is auth-by-default.
Public exceptions are deliberately small:
GET /api/pingGET /api/info- pair/refresh endpoints
- share bootstrap and share heartbeat endpoints
Sensitive local-only flows include:
- pairing arm status
- QR generation helpers
- database rebuild
Pairing model
Remote access is no longer anonymous.
- Desktop user arms pairing locally.
- QR/share config includes a one-time
pairingCodewhile armed. - Mobile exchanges that code for access + refresh tokens.
- Mobile silently refreshes access tokens and stores auth state per hub/origin.
This keeps Cloudflare/Tailscale access usable without falling back to a single long-lived static secret for every client.
Storage and recovery
Current desktop persistence is native SQLite via better-sqlite3-multiple-ciphers.
Key behaviors:
- DB path defaults to
~/.music-hub/music.db - startup checks
user_versionand integrity databaseHealthis surfaced through/api/infoand/api/settings- incompatible or faulted DBs are preserved and archived instead of being silently wiped
- local rebuild is explicit through
POST /api/database/rebuild
Remote access
Supported remote paths today:
- Cloudflare quick tunnel
- embedded Tailscale /
tsnet
The server binds to loopback by default and only broadens network exposure when LAN/remote access is explicitly enabled.
Public web surface
There is no general-purpose browser control app for remote users. The public browser surface today is:
- landing marketing site
- docs site
- standalone share pages for playlists, artists, albums, and tracks
Share pages are intentionally narrow: bootstrap-only data fetch, tokenized playback, and no access to the full protected library API.
Current status
What is true in the current codebase:
- desktop DB runtime is native SQLite, not sql.js
- playback/session persistence is shared between clients
- remote auth uses pair + refresh tokens
- public share pages use signed bootstrap/media sessions
- degraded DB states surface explicitly and can be rebuilt locally
- docs and landing are separate Next-based surfaces