Where things live
frontend/
index.html the page frame
sw.js service worker (offline)
vendor/ Bootstrap + icons, served by Nessie
css/
themes.css colour themes
layout.css the page grid
components.css everything else
js/
main.js starts everything
router.js #address → view
api.js every server call
events.js component → app events
identity.js who's listening
integrations.js is Lidarr on?
ai-prompt.js search box as AI prompt
offline.js talks to sw.js
connection.js can the server be reached?
downloads.js albums, playlists, mixes kept
native.js inside an app? which one?
theme.js theme choice
track-cache.js tracks by id
lib/ html``, format, reorder
player/ Player + two outputs
components/ <nessie-…> elements
views/ one module per page
settings/ one module per tab
v2/ the classic UI
app/
main.py builds the FastAPI app
cli.py python -m app.cli …
core/
config.py settings (env, .env, JSON)
editable_settings.py
db/session.py engine, get_db()
api/ routes, one file per area
auth.py require_user/admin/ai
caching.py ETags, AppFiles (no-cache)
schemas/ Pydantic: JSON in and out
models/ SQLAlchemy tables
repositories/ queries (tracks, plays…)
services/ the real work:
player.py mpv over IPC
library_scanner.py
smart_playlists.py, mix_rules.py
ai_playlists.py Claude
identity.py profiles
ownership.py who may do what to a playlist or mix
stats.py listening stats
lyrics.py .lrc, tags, LRCLIB
integrations/ Lidarr
metadata/ MusicBrainz, Wikidata…
alembic/versions/ database migrations
tests/ pytest; tests/e2e: Playwright
mobile/ the Android and iOS apps (Capacitor)
www/ their own pages
android/ the Gradle project
ios/ the Xcode project (SPM)
NessieTests/ swift test: queue, plays, car ids