Files
TermorServer/SUBSONIC_SERVER_BLUEPRINT.md

15 KiB

Subsonic Server Blueprint

Goal

Build a self-hosted music server with:

  • a Subsonic-compatible API for third-party clients
  • a modern web interface inspired by Aonsoku
  • an architecture that is simpler to build than a full Navidrome fork
  • a codebase that can grow into a serious long-term project

This project should not try to clone Navidrome feature-for-feature on day one. The right approach is:

  • build a focused backend with strong library and streaming fundamentals
  • build a separate SPA frontend with a polished listening experience
  • support the Subsonic API where it matters
  • keep a separate internal web API for faster frontend development

Reference Direction

What to take from Navidrome

  • overall product shape: self-hosted music server
  • robust scanning and indexing mindset
  • low-overhead backend architecture
  • Subsonic compatibility strategy
  • cover art, streaming, playlists, favorites, search, multi-user

What to take from Aonsoku

  • modern visual language
  • frontend stack direction
  • player UX patterns
  • layout ideas for home, album, artist, playlist, queue, lyrics
  • separation between data fetching, UI state, and playback state

What not to copy directly

  • do not embed the frontend tightly into the backend from day one
  • do not aim for full Subsonic coverage immediately
  • do not duplicate Navidrome's whole surface area before the core works well

Backend

  • Language: Go
  • HTTP router: chi
  • Config: viper or a smaller env-based config layer
  • Database: SQLite for MVP
  • Migrations: goose or atlas
  • Tag reading: a mature tag library for MP3/FLAC/M4A/OGG metadata
  • Background jobs: in-process worker loops
  • File watching: fsnotify or polling fallback
  • Auth: session + token support
  • Logging: slog or logrus

Frontend

  • Framework: React
  • Build tool: Vite
  • Language: TypeScript
  • Routing: React Router
  • Server state: TanStack Query
  • Client state: Zustand
  • UI primitives: Radix UI
  • Styling: Tailwind CSS
  • Forms: React Hook Form + Zod
  • Audio playback: HTMLAudioElement first, optional HLS/transcoding later

Infra

  • Single binary backend for local/self-hosted use
  • Separate frontend app built into static assets
  • Docker support early
  • Local dev via docker-compose or separate dev servers

High-Level Architecture

music files
  -> scanner
  -> metadata extractor
  -> database index
  -> artwork cache

clients
  -> web SPA
  -> third-party Subsonic clients

backend
  -> auth
  -> library API
  -> Subsonic compatibility API
  -> streaming/transcoding
  -> playlist/favorites/history
/
  apps/
    web/
  cmd/
    server/
  internal/
    auth/
    config/
    db/
    httpapi/
    library/
    media/
    playlist/
    scanner/
    subsonic/
    users/
  migrations/
  assets/
  scripts/
  deploy/
  docs/

API Strategy

Use two APIs.

1. Subsonic-compatible API

Purpose:

  • support existing clients
  • preserve compatibility expectations
  • allow easy migration from other Subsonic servers

Examples:

  • /rest/ping
  • /rest/getLicense
  • /rest/getArtists
  • /rest/getArtist
  • /rest/getAlbum
  • /rest/getSong
  • /rest/stream
  • /rest/getCoverArt
  • /rest/search3
  • /rest/getRandomSongs
  • /rest/getStarred2
  • /rest/star
  • /rest/unstar
  • /rest/createPlaylist
  • /rest/updatePlaylist
  • /rest/getPlaylists
  • /rest/getPlaylist
  • /rest/scrobble

2. Internal web API

Purpose:

  • reduce frontend complexity
  • return cleaner payloads than Subsonic XML/legacy JSON
  • aggregate data for fast UI screens

Examples:

  • GET /api/me
  • GET /api/home
  • GET /api/artists
  • GET /api/artists/:id
  • GET /api/albums/:id
  • GET /api/tracks/:id
  • GET /api/playlists
  • GET /api/playlists/:id
  • POST /api/queue/scrobble
  • GET /api/search?q=...
  • GET /api/browse/recent
  • GET /api/browse/random
  • POST /api/favorites/:id
  • DELETE /api/favorites/:id

Data Model

Core entities:

  • users
  • artists
  • albums
  • tracks
  • genres
  • album_art
  • playlists
  • playlist_tracks
  • favorites
  • play_history
  • scan_jobs
  • library_roots

Important fields:

users

  • id
  • username
  • password_hash
  • is_admin
  • last_login_at
  • created_at

artists

  • id
  • name
  • sort_name
  • album_count
  • song_count
  • biography
  • cover_art_id

albums

  • id
  • artist_id
  • title
  • sort_title
  • year
  • genre
  • cover_art_id
  • track_count
  • duration_seconds
  • album_artist
  • release_type

tracks

  • id
  • album_id
  • artist_id
  • title
  • track_number
  • disc_number
  • year
  • genre
  • duration_seconds
  • bitrate
  • sample_rate
  • file_path
  • file_size
  • suffix
  • content_type
  • lyrics_embedded
  • cover_art_id
  • created_at
  • updated_at

playlists

  • id
  • user_id
  • name
  • comment
  • public
  • created_at
  • updated_at

Phased Delivery Plan

Phase 0: Foundation

Outcome:

  • repo initialized
  • dev tooling set up
  • backend and frontend boot independently

Deliverables:

  • monorepo or single repo with apps/web and Go backend
  • linting and formatting
  • basic CI
  • environment examples
  • Dockerfile and local compose

Phase 1: Library Core

Outcome:

  • server can scan a music folder and build a usable index

Deliverables:

  • config for music folder paths
  • scanner for recursive file discovery
  • metadata extraction
  • SQLite schema
  • initial scan endpoint/job
  • rescan changed files
  • artist/album/track records
  • cover art extraction or sidecar loading

Phase 2: Playback Core

Outcome:

  • music can be streamed and played in the web app

Deliverables:

  • authenticated stream endpoint
  • range requests
  • MIME/content-type handling
  • artwork endpoint
  • queue and now-playing state in frontend
  • album/artist pages
  • playable track lists

Phase 3: Subsonic Compatibility MVP

Outcome:

  • major Subsonic clients can connect

Deliverables:

  • auth handshake support
  • required response envelope
  • core artist/album/song endpoints
  • stream endpoint compatibility
  • cover art compatibility
  • search support
  • favorites support
  • playlists support

Phase 4: Product UX

Outcome:

  • the web app feels like a polished daily driver

Deliverables:

  • home page
  • recent albums
  • random picks
  • favorites
  • search experience
  • playlists
  • mini player + full player
  • keyboard shortcuts
  • responsive layout

Phase 5: Power Features

Outcome:

  • project becomes meaningfully competitive

Deliverables:

  • on-the-fly transcoding
  • lyrics
  • listening history
  • scrobble
  • share links
  • radio/mixes
  • folder browsing
  • multi-library
  • admin dashboard

Frontend Product Shape

Core Screens

  • login
  • home
  • artists list
  • artist detail
  • album detail
  • playlist detail
  • search
  • queue
  • settings
  • full-screen player or expanded player panel

UX Goals

  • art-forward layout
  • fast navigation
  • minimal friction to start playback
  • stable queue behavior
  • good empty/loading/error states
  • pleasant desktop and mobile behavior

Visual Direction

  • dark-first listening UI is acceptable, but keep theme system flexible
  • strong album art presence
  • large typography for hero sections
  • compact dense lists where appropriate
  • smooth transitions for queue and player states
  • do not overbuild visual effects before playback and browsing feel solid

Backend Module Breakdown

internal/config

Responsibilities:

  • env/file config loading
  • defaults
  • path validation

internal/db

Responsibilities:

  • DB connection
  • migrations
  • query helpers
  • transactional boundaries

internal/scanner

Responsibilities:

  • directory crawl
  • changed file detection
  • deleted file cleanup
  • scheduling rescans

internal/library

Responsibilities:

  • domain services for artists/albums/tracks
  • browse/search logic
  • cover art association

internal/media

Responsibilities:

  • file streaming
  • range requests
  • transcoding hooks
  • content-type detection
  • artwork serving

internal/subsonic

Responsibilities:

  • request parsing
  • auth compatibility
  • response shaping
  • endpoint mapping from internal domain services

internal/auth

Responsibilities:

  • password hashing
  • sessions/tokens
  • permissions

internal/httpapi

Responsibilities:

  • REST endpoints for the web app
  • JSON response contracts
  • middleware

Detailed MVP Checklist

Project Setup

  • Choose repository structure and naming
  • Initialize Go module
  • Initialize frontend app in apps/web
  • Add root .editorconfig
  • Add root .gitignore
  • Add backend formatter/linter commands
  • Add frontend formatter/linter commands
  • Add shared Makefile or task runner
  • Add .env.example
  • Add docker-compose.yml
  • Add backend Dockerfile
  • Add frontend Dockerfile if needed
  • Add CI workflow for lint/build/test

Backend Bootstrap

  • Create cmd/server/main.go
  • Add config loading
  • Add HTTP server bootstrap
  • Add graceful shutdown
  • Add structured logging
  • Add health endpoint
  • Add request logging middleware
  • Add panic recovery middleware
  • Add CORS strategy for local dev

Database

  • Choose migration tool
  • Create initial schema migration
  • Add DB connection setup
  • Add migration runner at startup
  • Add indexes for artist/album/track lookup
  • Add indexes for search
  • Add repository helpers or query layer

Auth and Users

  • Create users table
  • Implement password hashing
  • Implement login endpoint
  • Implement session or bearer token issuance
  • Implement auth middleware
  • Implement current user endpoint
  • Implement admin bootstrap user creation
  • Add logout endpoint

Library Scanning

  • Add library roots table
  • Add config for one or more music paths
  • Recursively discover supported audio files
  • Ignore unsupported file types
  • Read tags from files
  • Map tags into normalized artist/album/track model
  • Extract embedded artwork when present
  • Load folder sidecar artwork when present
  • Persist scan results transactionally
  • Track deleted files and remove stale DB rows
  • Add initial full scan command
  • Add rescan endpoint or admin action
  • Add filesystem watch or scheduled scan
  • Record scan job progress
  • Expose scan status endpoint

Browse API

  • List artists
  • Artist detail with albums
  • Album detail with tracks
  • Track detail
  • Recent albums
  • Random albums or songs
  • Favorites listing
  • Search endpoint
  • Pagination support
  • Sorting support

Streaming

  • Implement authenticated stream endpoint
  • Support range requests
  • Support HEAD where appropriate
  • Return correct content type
  • Handle missing files gracefully
  • Add cover art endpoint
  • Add basic download endpoint

Playlists and History

  • Create playlists table
  • Create playlist tracks table
  • Add create playlist endpoint
  • Add rename playlist endpoint
  • Add delete playlist endpoint
  • Add reorder tracks endpoint
  • Add add/remove track endpoints
  • Add listening history table
  • Record play/scrobble events
  • Add recently played endpoint

Favorites

  • Add favorites table
  • Star track
  • Unstar track
  • Star album if desired
  • Unstar album if desired
  • Star artist if desired
  • Unstar artist if desired

Subsonic Compatibility

  • Implement request auth parsing
  • Support username/password auth where needed
  • Support token/salt auth
  • Add common Subsonic response builder
  • Implement ping
  • Implement getLicense
  • Implement getArtists
  • Implement getArtist
  • Implement getAlbum
  • Implement getSong
  • Implement stream
  • Implement getCoverArt
  • Implement search3
  • Implement getRandomSongs
  • Implement getStarred2
  • Implement star
  • Implement unstar
  • Implement playlist endpoints
  • Implement scrobble
  • Test against at least one existing Subsonic client

Frontend Bootstrap

  • Create Vite React TypeScript app
  • Configure routing
  • Configure Tailwind
  • Add Radix UI primitives
  • Add TanStack Query client
  • Add Zustand stores
  • Add API client layer
  • Add auth persistence strategy
  • Add theme tokens and CSS variables

Frontend App Shell

  • Login page
  • App layout with sidebar/topbar/player area
  • Responsive navigation
  • Toast/notification system
  • Error boundary
  • Query loading/error patterns

Frontend Music Views

  • Home page
  • Artists grid/list page
  • Artist detail page
  • Album detail page
  • Playlist page
  • Search results page
  • Favorites page
  • Recently played page

Frontend Player

  • Global player store
  • Queue model
  • Play/pause
  • Next/previous
  • Seek bar
  • Volume control
  • Repeat modes
  • Shuffle
  • Track switching
  • Keyboard shortcuts
  • Mini player
  • Expanded player

Quality and Testing

  • Unit tests for scanner parsing
  • Unit tests for auth
  • Unit tests for Subsonic envelope formatting
  • Backend integration tests for browse endpoints
  • Backend integration tests for stream endpoint
  • Frontend component tests for player and key pages
  • Frontend E2E smoke tests
  • Test with a realistic sample library
  • Test on Windows paths
  • Test on Linux paths
  • Test large album art and missing metadata edge cases

Deployment

  • Build production frontend assets
  • Serve frontend assets from backend or reverse proxy
  • Docker image for all-in-one deployment
  • Persistent DB volume
  • Persistent cache volume
  • Music folder mount strategy
  • Reverse proxy example
  • HTTPS deployment notes
  • Backup/restore notes

Nice-to-Have After MVP

  • On-the-fly transcoding
  • Multi-bitrate streaming profiles
  • Lyrics support
  • Last.fm or ListenBrainz scrobbling
  • Shareable public links
  • Smart playlists
  • Radio or generated mixes
  • Folder view
  • Multi-library roots with permissions
  • Podcast support
  • Admin analytics page
  • PWA support

Suggested MVP Cut Line

If we want the fastest realistic first release, include only:

  • auth
  • scanner
  • artists/albums/tracks browse
  • cover art
  • streaming
  • search
  • favorites
  • playlists
  • recent albums
  • Subsonic core endpoints
  • polished web player

Delay until later:

  • transcoding
  • lyrics
  • podcasts
  • radio
  • advanced admin tools
  • recommendations and smart mixes
  1. Backend bootstrap and DB
  2. Scanner and normalized schema
  3. Browse endpoints
  4. Stream and cover art endpoints
  5. Web login and app shell
  6. Artist/album pages
  7. Queue and player
  8. Search and favorites
  9. Playlists
  10. Subsonic compatibility layer
  11. Docker and deployment polish

Practical Recommendation

The best implementation strategy is:

  • build your own backend
  • use Navidrome as a behavior reference, not a codebase to fork
  • use Aonsoku as a frontend inspiration and partial architectural reference
  • prioritize a strong MVP over broad feature parity

If you want, the next step should be scaffolding the actual repository:

  • Go backend skeleton
  • React frontend skeleton
  • initial DB schema
  • first endpoints
  • first app shell