# Minstrel A self-hosted music server that thinks for you. Smart shuffle, contextual likes, ListenBrainz-aware radio, and Lidarr automation — server-side, so every client (web, mobile, Subsonic third-party) gets the same intelligence. > State and intelligence belong on the server, not the client. ## Highlights - **OpenSubsonic-compatible.** Existing Subsonic clients (DSub, Symfonium, play:Sub, etc.) connect with no special configuration. - **Server-side smart shuffle.** Track-similarity vectors, dual-like model (general + contextual), and session memory keep mixes coherent across devices. - **ListenBrainz radio.** Session-aware "more like this" pulls from ListenBrainz similarity data, not a static genre tag. - **Lidarr integration.** Triggered scans, request-driven album imports, and a quarantine flow when something doesn't fit. - **Built-in web SPA.** Full-feature library, search, queue, playlists, and admin — no separate frontend container to deploy. - **Flutter mobile client in flight.** Tracking issue [#356](https://git.fabledsword.com/bvandeusen/minstrel/issues/356). ## Quickstart ```yaml # compose.yaml services: minstrel: image: git.fabledsword.com/bvandeusen/minstrel:latest ports: ['4533:4533'] volumes: - ./music:/music:ro - minstrel-data:/data environment: MINSTREL_DATABASE_URL: postgres://minstrel:minstrel@db:5432/minstrel?sslmode=disable MINSTREL_LIBRARY_SCAN_PATHS: /music depends_on: [db] db: image: postgres:17 environment: POSTGRES_USER: minstrel POSTGRES_PASSWORD: minstrel POSTGRES_DB: minstrel volumes: [pgdata:/var/lib/postgresql/data] volumes: minstrel-data: pgdata: ``` ```bash docker compose up -d ``` After the stack is up, visit `http://localhost:4533/register` and create your admin account. The first user to register on a fresh instance is automatically marked as the administrator; subsequent users can register through the same form (or via invite tokens generated from the admin Users panel, depending on how you configure registration). For the full configuration surface, see [`config.example.yaml`](./config.example.yaml). ## Configuration Most operators only need the env vars in the quickstart above. A few extras worth knowing: - `MINSTREL_BRANDING_APP_NAME` — rename the instance ("Family Jukebox", "Office Music"). Surfaces in the header, browser tab, and OG share previews. - `MINSTREL_STORAGE_DATA_DIR` — defaults to `./data`. Holds playlist cover collages and other generated artefacts. - `MINSTREL_LIBRARY_SCAN_PATHS` — colon-separated list of music library roots to scan. Supports multiple roots (`/music:/podcasts`). ListenBrainz integration (per-user scrobble + similarity tokens) and Lidarr integration (URL + API key) are configured through the admin Settings UI rather than env vars or yaml — per Minstrel's "config in UI" rule, integration settings live where operators can edit them without restarting. Most operational keys have a `MINSTREL_
_` env override. Recommendation and events tuning are yaml-only. See [`config.example.yaml`](./config.example.yaml) for the authoritative surface. ## Updating - `:main` — rolling, follows the dev branch's tested tip. Recommended only for the operator who's running an upstream-watching deployment. - `:v1.0.x` — pinned releases. Recommended default. Database migrations run automatically at startup; rollbacks require restoring a Postgres dump. ## Specs Authoritative scope lives under [`docs/`](./docs): - [Server spec](./docs/smart-music-server-spec.md) — current implementation focus. - [Client spec](./docs/smart-music-client-spec.md) — Flutter companion app. ## Development Two concurrent dev processes: 1. **Backend:** `docker compose up` — Postgres + Minstrel on `:4533`. 2. **Frontend:** `cd web && npm install && npm run dev` — Vite dev server on `:5173` with HMR. The Vite server proxies `/api/*` and `/rest/*` to `:4533` so session cookies work. ### Testing - Unit + race (no DB): `make test-short`. - Full suite incl. integration tests: `make test-integration`. This runs against a dedicated `minstrel_test` database so a test run never truncates your dev `minstrel` data (admin user, library, likes). It brings up the compose Postgres and creates the test DB if missing. - CI runs both: a fast `go test -short -race` gate plus an integration job with its own ephemeral Postgres (`.gitea/workflows/test-go.yml`). ### Production build `docker build -t minstrel .` runs the SvelteKit build inside a `node` stage, copies the output into the `golang` stage, and `//go:embed`s it into the final binary. The container serves the SPA from `/` alongside the API surfaces; no separate static-file server is required. ### Branches - Day-to-day work happens on `dev` (or feature branches merged into `dev`). - `main` is **protected** — changes land via PR from `dev`. - Releases are cut by tagging `v*` off `main`; the release workflow builds and pushes the container image to the Gitea registry. Task and milestone tracking: Fable (`Minstrel` project, id 12). ## License See [LICENSE](./LICENSE).