A polished, self-hosted web player for Subsonic and OpenSubsonic music libraries.
Stream from Navidrome, Gonic, Airsonic, and other compatible servers through a responsive interface built for desktop and mobile.
Features · Screenshots · Quick Start · Docker · Contributing
|
|
| Now-playing sidebar and queue | Full-screen player |
- Shared app-wide audio engine with queue, repeat, seek, volume, and Media Session controls
- Per-track playback speed and pitch controls with pitch-correction support
- Resilient Subsonic streaming with bounded URL caching and stalled-stream recovery
- Automatic transcoding rules for browser-sensitive formats such as ALAC and M4A
- Internet radio playback for direct streams and HLS playlists
- Web Audio visualizers including Bars, Wave, Circle, Mirror, Spectrum, Particles, Hexagon, Cube, and Grid
- Expandable full-screen player, desktop sidebar player, floating mini-player, and mobile player bar
- Structured and synchronized lyrics with fallback lyric providers
- AutoEq headphone calibration profile search and application
- Configurable keyboard shortcuts and an immersive Zen mode
- Browse artists, albums, songs, playlists, favorites, and genres
- Spotlight-style search across artists, albums, and tracks
- Featured albums, random mixes, recent releases, and most-played statistics
- Persistent sorting and filtering by genre, year, and library metadata
- Demo mode for exploring the interface without connecting a server
- Subsonic API 1.16.1 with fallback negotiation through API 1.14.0
- OpenSubsonic extension discovery and structured lyrics v2 support
- ID3-first album and starred endpoints with legacy server fallbacks
- Password token/salt authentication and optional OpenSubsonic API-key authentication
- Responsive light and dark themes with system-preference detection
- IndexedDB caching for API responses, settings, credentials, and local play statistics
- Docker, Vercel, and static-hosting deployment options
Nebula Music supports servers implementing the Subsonic API or compatible OpenSubsonic extensions, including:
The music server must be reachable from the browser running Nebula. HTTPS and correct CORS configuration are strongly recommended.
- Node.js 20.19+ or 22.12+; Node.js 24 LTS is recommended
- npm
- A reachable Subsonic-compatible server, unless using demo mode
git clone https://github.com/lilremark/Nebula-Music.git
cd Nebula-Music
npm install
npm run devOpen http://localhost:3000. No environment variables are required.
Choose one of the supported authentication methods:
- Password: Enter the server URL, username, and password. Nebula stores the generated token and salt instead of the raw password.
- API key: Enter the server URL and OpenSubsonic API key. Nebula omits the username and legacy token parameters as required by the extension.
npm run typecheck
npm run build
npm run previewThe production bundle is written to dist/.
The published image is available from Docker Hub as
lilremark/nebula-music.
It serves Nebula through an unprivileged NGINX 1.30.3 container. The Compose
setup uses a read-only filesystem, drops Linux capabilities, and includes a
health check.
Pull and run the latest release:
docker pull lilremark/nebula-music:latest
docker run -d \
--name nebula-music \
--restart unless-stopped \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=16m \
--security-opt no-new-privileges \
--cap-drop ALL \
-p 8080:8080 \
lilremark/nebula-music:latestOpen http://localhost:8080.
To stop the container:
docker stop nebula-music
docker rm nebula-musicUsing the included Compose configuration:
docker compose -f docker/docker-compose.yml up -d
docker compose -f docker/docker-compose.yml downCompose uses latest by default. Set NEBULA_VERSION=2.1.3 to pin the current
release. See docker/README.md for local-build commands and
additional deployment details.
Nebula is a client-side application. Server details and preferences are entered in the UI and stored in the browser.
| Storage | Contents |
|---|---|
| IndexedDB | Settings, cached API responses, authentication data, and per-server play statistics |
localStorage |
Lightweight play-history snapshots and the last-seen application version |
To reset the application completely, clear the site data for the Nebula origin in your browser.
| Action | Default |
|---|---|
| Play or pause | Space |
| Previous track | ArrowLeft |
| Next track | ArrowRight |
| Toggle repeat | L |
| Cycle visualizer | V |
| Toggle Zen mode | Z |
Shortcuts can be changed in Settings.
Nebula-Music/
├── components/ Reusable UI, navigation, radio, and player components
├── constants/ Equalizer presets and shared constants
├── context/ Global store and theme state
├── docker/ Docker, Compose, and Nginx configuration
├── hooks/ Adaptive color, artist image, and waveform hooks
├── public/ Static browser assets and audio worklets
├── services/ Subsonic API, AutoEq, and IndexedDB services
├── screenshots/ README product screenshots
├── views/ Home, browse, library, radio, search, and settings views
├── App.tsx Application shell and view routing
├── index.tsx React bootstrap
└── index.css Global styles and theme variables
flowchart LR
UI["React views and components"] --> Store["Context store"]
Store --> API["Subsonic service"]
Store --> Audio["HTMLAudioElement and Web Audio API"]
API --> Server["Subsonic/OpenSubsonic server"]
API <--> Cache["IndexedDB cache"]
Audio --> Session["Media Session API"]
Audio --> Visualizer["AnalyserNode visualizers"]
The global store coordinates library requests, cached responses, playback
state, and UI updates. A shared HTMLAudioElement handles playback while a
lazily created Web Audio graph powers analysis, visualizers, pitch processing,
and equalization.
| Command | Description |
|---|---|
npm run dev |
Start the Vite development server on port 3000 |
npm run typecheck |
Run TypeScript validation without emitting files |
npm run build |
Create the production bundle |
npm run preview |
Preview the production build locally |
- Import this repository into Vercel.
- Select the Vite framework preset.
- Use
npm run buildas the build command. - Use
distas the output directory.
Build the project with npm run build, then deploy the generated dist/
directory to Netlify, Cloudflare Pages, Amazon S3, or another static host.
Because Nebula connects directly from the browser, the deployed origin must be permitted by the music server's CORS policy.
Nebula cannot connect to my server
- Verify that the URL includes
https://orhttp://. - Confirm the server is reachable from the same browser and network.
- Check the server's CORS configuration.
- Avoid mixed content: an HTTPS deployment cannot call an HTTP music server.
- Confirm the selected password or API-key authentication mode is supported by the server.
Audio plays but seeking does not work
- Confirm the server supports byte-range requests and returns appropriate
Content-LengthandAccept-Rangesheaders. - Enable server-side transcoding for formats the browser cannot seek reliably.
Settings or themes do not persist
- Ensure the browser is not blocking IndexedDB or local storage.
- Clear the site's stored data after changing between demo and live-server credentials.
- Updated all npm dependencies, including React 19, Vite 8, Tailwind CSS 4, TypeScript 6, Motion 12, and Lucide React 1.
- Added OpenSubsonic extension discovery and API-key authentication.
- Added structured lyrics v2 and ID3-first album/starred endpoints with legacy fallbacks.
- Added Subsonic protocol fallback negotiation from API 1.16.1 through 1.14.0.
- Centralized Subsonic response and error handling.
- Updated Docker builds to Node.js 24 LTS and unprivileged NGINX 1.30, with a read-only runtime, dropped capabilities, and container health checks.
- Published multi-platform
2.1.3andlatestimages to Docker Hub atlilremark/nebula-music. - Added refreshed product screenshots and updated project documentation.
- Added AutoEq headphone calibration.
- Added production Docker and Nginx deployment files.
- Improved long-session Subsonic playback recovery.
- Refined visualizer controls and Settings layout.
See the commit history for the complete development history.
Issues and pull requests are welcome. Read CONTRIBUTING.md for development requirements, validation commands, and pull-request guidance.
Security vulnerabilities must not be reported publicly. Email remark@remark.rip and follow SECURITY.md.
Distributed under the MIT License.


