🎧 Your Personal Streaming Service https://www.navidrome.org
  • Go 81.5%
  • JavaScript 15.1%
  • Rust 2.2%
  • Go Template 0.5%
  • Makefile 0.3%
  • Other 0.4%
Find a file
Deluan Quintão c22ce9ebb2
feat(api): add the API v1 foundation behind DevAPIv1 (#6227)
* feat(api): add OpenAPI v1 spec skeleton, lint ruleset and bundle tooling

vacuum v0.30.6's `bundle --composed` mangles component names for this
spec's multi-file layout (duplicates Problem as Problem__schemas etc.),
so api-bundle uses the Redocly CLI (npx @redocly/cli bundle) instead.

* fix(api): pin the Redocly CLI version

Tried moving components out of the root document (per libopenapi's
nested_files example) so vacuum's own bundler could produce clean
names, but any component declared via $ref inside components.* still
gets a __<parent>-suffixed twin regardless of collisions elsewhere, so
vacuum's --composed bundler can't cleanly bundle this spec. Pin the
already-working Redocly fallback to an exact version instead of
@latest.

* fix(api): bundle the OpenAPI spec with vacuum

vacuum's --composed bundler suffixes any component reached via a $ref
written directly inside the root document's own components.* block,
regardless of collisions elsewhere. Dropping the root-level schemas/
parameters/responses declarations (keeping only securitySchemes, and
leaving every component file under api/openapi/components/ untouched)
lets vacuum bundle cleanly with no __ suffixes, going back to Go-only
tooling. Components nothing references yet (ListMeta, offset, limit,
BadRequest, Unauthorized, Forbidden, NotFound) are absent from the
bundle until a later task's operation references them.

* fix(api): make spec lint rules cover all schemas and error codes

nd-schema-property-descriptions targeted $.components.schemas, but our
schemas live in path/response files, not the root document, so it was
dead code; switched to $..properties[*] to walk every resolved schema
wherever it ends up. nd-error-responses-are-problems only checked a
hardcoded status-code list; switched to a patternProperties schema
matching the full 4xx/5xx range. Also: api-diff now diffs against the
merge-base with API_DIFF_BASE (falling back to its tip with a notice
if no merge-base exists), gen no longer depends on api-gen until Task
3 wires up oapi-codegen, and api-lint suppresses vacuum's banner.

* feat(api): embed the bundled OpenAPI spec and expose its version

* feat(api): generate the v1 server interface with oapi-codegen

* feat(api): add RFC 9457 problem responses for API v1

* feat(api): add API v1 router with /server discovery and spec routes

* fix(api): serve the OpenAPI document without range support

* feat(api): mount API v1 behind the DevAPIv1 flag

* chore(ci): lint, regenerate and diff the OpenAPI v1 spec

* refactor(api): tighten spec version access, lint rules and test naming

* refactor(api): simplify spec routes, tests and OpenAPI tooling

Share one If-None-Match parser (utils/req) between the image and spec
routes, declare the YAML spec response as an object so tests need no
decoder override, and reuse ETag/304 spec components.

Install the OpenAPI tools only when missing or at a different version,
fail api-diff when its base ref does not exist, and in CI cache the
tools, fold regeneration into the go generate check, and fetch only the
PR base commit for the breaking-change gate.

* refactor(api): raise the list limit maximum to 2000 and drop the flag test

* feat(api): treat added enum values as non-breaking

Enums in API v1 are open: clients must accept unknown values. api-diff
now downgrades response-property-enum-value-added to INFO, while
removing a value from a request enum stays breaking.

* feat(api): gate breaking changes on x-stability-level

Every operation declares x-stability-level (alpha, beta, stable). oasdiff
ignores breaking changes to alpha operations and rejects lowering a
level, so unreleased endpoints can evolve while beta and stable ones
stay additive. All current operations start as alpha.

* feat(api): declare loginMethods as an enum

Prefix generated enum constants with their type name so enums sharing a
value (for example password) cannot collide in package apiv1.

* feat(api): send Allow on 405 and answer HEAD wherever GET is routed

chi only sets Allow in its default 405 handler, so the problem-format
handler now builds it by matching each method against the v1 router.
HEAD requests fall back to the GET route, as RFC 9110 expects.

* refactor(api): hash the spec ETag with xxh3

The bytes are compiled in, and the digest was truncated to 64 bits
anyway, so this matches the artwork ETags instead of paying for
cryptographic strength we discard.

* docs(api): explain the about:blank problem type

* feat(api): make code the problem identifier and omit a blank type

RFC 9457 says clients switch on the type URI, but no adopter surveyed
ships both a populated type and a separate code. Declare code as an
enum, and send type only once a problem has semantics of its own.

* fix(api): advertise the configured base path in the served OpenAPI spec

With BaseURL=/music the API is mounted at /music/api/v1, but the spec
told clients to call /api/v1 at the host root. The server now rewrites
servers[0].url to BasePath + /api/v1 when it serves the document.

Relative server URLs were tested first: "." and "../v1" work in
openapi-generator, Swagger UI and Redoc, but Scalar resolves them
against the page origin, so it breaks even without a base path. The
committed bundle keeps /api/v1, and a test pins that it appears exactly
once, which the rewrite relies on.
2026-09-26 15:27:23 -04:00
.devcontainer chore(deps): upgrade to Go 1.27 (#5990) 2026-08-30 12:43:15 -04:00
.github feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
adapters refactor(persistence): stateless repositories with per-call context (#6149) 2026-09-25 18:06:10 -04:00
api feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
cmd feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
conf feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
consts feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
contrib fix(contrib): support libblas in systemd sandbox (#6190) 2026-09-21 09:06:12 -04:00
core refactor(scanner): remove the unused legacy ffmpeg metadata extractor (#6231) 2026-09-26 12:30:52 -04:00
db refactor(persistence): stateless repositories with per-call context (#6149) 2026-09-25 18:06:10 -04:00
git feat(plugins): experimental support for plugins (#3998) 2025-06-22 20:45:38 -04:00
log refactor(log): replace sort with slices.SortFunc and use atomic for currentLevel 2026-09-06 13:08:05 -04:00
model fix(scanner): register .webm as audio/webm (#6230) 2026-09-26 11:43:00 -04:00
persistence refactor(persistence): stateless repositories with per-call context (#6149) 2026-09-25 18:06:10 -04:00
plugins refactor(persistence): stateless repositories with per-call context (#6149) 2026-09-25 18:06:10 -04:00
release fix(release): repair root-owned artwork and plugins folders on upgrade (#6143) 2026-09-17 17:17:56 -04:00
resources fix(scanner): register .webm as audio/webm (#6230) 2026-09-26 11:43:00 -04:00
scanner refactor(scanner): remove the unused legacy ffmpeg metadata extractor (#6231) 2026-09-26 12:30:52 -04:00
scheduler fix(log): change debug log level to trace to reduce log noise from cron 2026-08-06 00:40:58 -04:00
scripts build(worktree): add script for setting up git worktrees 2026-03-17 21:34:00 -04:00
server feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
tests refactor(scanner): remove the unused legacy ffmpeg metadata extractor (#6231) 2026-09-26 12:30:52 -04:00
ui fix(auth): ExtAuth logout redirect on unauthenticated loads, and warning spam from untrusted sources (#6176) 2026-09-19 17:08:49 -04:00
utils feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
.dockerignore fix: add music.old to .dockerignore and .gitignore 2026-02-06 07:40:05 -05:00
.git-blame-ignore-revs Move project to Navidrome GitHub organization 2021-02-06 21:47:19 -05:00
.gitignore ci: run the plugins test suite in parallel processes (#6051) 2026-08-30 16:57:40 -04:00
.golangci.yml refactor(persistence): stateless repositories with per-call context (#6149) 2026-09-25 18:06:10 -04:00
.nvmrc chore(deps): update all dependencies (#4618) 2025-10-25 17:05:16 -04:00
.octocov.yml ci: exclude tests/ from the coverage report on pull requests too (#6070) 2026-09-01 23:02:15 -04:00
CODE_OF_CONDUCT.md Use Contributor Covenant v2.0 2020-07-21 14:40:21 -04:00
context7.json Add context7.json with URL and public key 2026-04-14 19:19:42 -04:00
CONTRIBUTING.md docs: update commit message format in CONTRIBUTING.md 2026-02-20 11:00:34 -05:00
Dockerfile build(docker): add curl to container image (#6111) (#6116) 2026-09-09 11:38:59 -04:00
go.mod feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
go.sum feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
LICENSE Change license to GPLv3 2020-01-22 14:48:38 -05:00
main.go feat(server): implement FTS5-based full-text search (#5079) 2026-02-21 17:52:42 -05:00
Makefile feat(api): add the API v1 foundation behind DevAPIv1 (#6227) 2026-09-26 15:27:23 -04:00
Procfile.dev chore(deps): upgrade to Go 1.24.1 (#3851) 2025-03-17 21:08:10 -04:00
README.md feat(subsonic): add structured sidecar lyrics support with OpenSubsonic v2 karaoke cues and agent layers (#5076) 2026-06-19 12:00:58 -04:00
reflex.conf fix(reflex): exclude .worktrees from the reflex configuration regex 2026-09-07 14:43:18 -04:00

Navidrome logo

Navidrome Music Server  Tweet

Last Release Build Downloads Docker Pulls Dev Chat Subreddit Contributor Covenant Gurubase

Navidrome is an open source web-based music collection server and streamer. It gives you freedom to listen to your music collection from any browser or mobile device. It's like your personal Spotify!

Note: The master branch may be in an unstable or even broken state during development. Please use releases instead of the master branch in order to get a stable set of binaries.

Check out our Live Demo!

Any feedback is welcome! If you need/want a new feature, find a bug or think of any way to improve Navidrome, please file a GitHub issue or join the discussion in our Subreddit. If you want to contribute to the project in any other way (ui/backend dev, translations, themes), please join the chat in our Discord server.

Installation

See instructions on the project's website

Cloud Hosting

PikaPods has partnered with us to offer you an officially supported, cloud-hosted solution. A share of the revenue helps fund the development of Navidrome at no additional cost for you.

PikaPods

Features

  • Handles very large music collections
  • Streams virtually any audio format available
  • Reads and uses all your beautifully curated metadata
  • Great support for compilations (Various Artists albums) and box sets (multi-disc albums)
  • Multi-user, each user has their own play counts, playlists, favourites, etc...
  • Very low resource usage
  • Multi-platform, runs on macOS, Linux and Windows. Docker images are also provided
  • Ready to use binaries for all major platforms, including Raspberry Pi
  • Automatically monitors your library for changes, importing new files and reloading new metadata
  • Supports lyrics from sidecar .ttml, .yaml/.yml Lyricsfile, .elrc, .lrc, .srt, .txt files and embedded TTML, Enhanced LRC, LRC, SRT, and plain-text tags (via lyricspriority)
  • Themeable, modern and responsive Web interface based on Material UI
  • Compatible with all Subsonic/Madsonic/Airsonic clients
  • Transcoding on the fly. Can be set per user/player. Opus encoding is supported
  • Translated to various languages

Translations

Navidrome uses POEditor for translations, and we are always looking for more contributors

Documentation

All documentation can be found in the project's website: https://www.navidrome.org/docs. Here are some useful direct links:

Screenshots