HoneyandClaude Sonnet 4.6 2dd3d7c7e5 fix: refresh edit form fields when getSong returns after edit mode opened
When the user opens the edit modal before the getSong async call returns,
the form fields are populated from the initial song object (from the song
list) which may omit albumArtist and other fields that only getSong
returns. Now, when getSong resolves and edit mode is already visible, all
form fields are updated to the authoritative Navidrome data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:28:28 +02:00

NovaSonic

A self-hosted music streaming PWA for Navidrome / Subsonic-compatible servers.
Built with Vite + vanilla ES modules, served via nginx in Docker.


Features

Home

  • Hero card — large banner featuring a random pick from your most-played and recently played albums, labelled "Meistgespielt" or "Zuletzt gehört" accordingly
  • Genre browser — top 15 genres (by song count) as a colored card grid; click to browse songs, hover-play to instantly shuffle the genre

Music Library

  • Stream music from your Navidrome / Subsonic library
  • Browse artists, albums, playlists, starred tracks, and random picks
  • Sort and filter views (albums, favorites) with chip filters
  • Search/filter bar inside playlist detail and favorites (instant, client-side)
  • Synced and plain lyrics via LRCLIB (auto-fetched per track)
  • Play count display — optional toggle in Settings; always shown on artist pages
  • Star and context-menu on every song row (artist top songs, all-songs view, playlists, albums)

Playback

  • Queue management with shuffle, repeat (all / once), and radio mode (endless random)
  • Now Playing overlay with swipe-to-dismiss; queue tab stays active when selecting a song from the queue
  • Lock screen media controls (Android / iOS via Media Session API)
  • Gapless-style queue with prev/next, skip forward/back
  • Scrobbling — plays are reported to Navidrome after 15 seconds of continuous playback

Discovery

  • iTunes / Last.fm integration — charts, global search, 30-second previews, similar artists, recommendations
  • Spotify playlist importer — paste a Spotify playlist URL to preview and download all tracks, enriched with iTunes metadata and cover art

Downloads (yt-dlp backend)

  • Download individual tracks, full albums, or entire artists from YouTube / SoundCloud
  • Spotify playlist importer downloads with iTunes-enriched metadata (album, year, track number, genre, cover art)
  • Duplicate detection — skips tracks already present on the server
  • Lyrics embedded into downloaded files (LRCLIB)

Playlists

  • Create, edit, and delete playlists
  • Edit playlist name, description, cover art, and public/private toggle
  • Add / remove tracks; reorder via drag and drop

Audiobookshelf Integration

  • Connect to your Audiobookshelf server (URL + API key)
  • Browse and stream audiobooks from your ABS library
  • Full player: chapters list, playback speed, sleep timer (preset or custom minutes), progress sync

App

  • PWA — installable on Android / iOS / desktop, offline-capable via service worker
  • Android APK (WebView wrapper with native Media3/ExoPlayer backend)
  • Robust Android queue sync — song identity verified via media ID on every resume to prevent stale-state mismatches
  • Multiple color themes
  • Dark theme, mobile-first responsive layout
  • German UI

Project Structure

Music_App/
├── src/                       # ES modules (Vite entry)
│   ├── state.js               # Shared mutable state (S object)
│   ├── utils.js               # md5, esc, formatDur, toast
│   ├── api.js                 # Subsonic API, Navidrome REST, iTunes API
│   ├── player.js              # Playback, transport, queue, media session, preview
│   ├── views.js               # Navigation, page loaders, card makers, search
│   ├── ui.js                  # Modals, overlays, sidebar, settings, context menu
│   ├── nowplaying.js          # Now Playing overlay
│   ├── abs.js                 # Audiobookshelf integration
│   ├── spotify.js             # Spotify playlist importer
│   ├── components.js          # Shared UI components
│   ├── themes.js              # Theme switching
│   ├── pwa.js                 # Service worker registration + update banner
│   └── main.js                # App init, audio wiring, window globals
├── backend/
│   ├── novasonic-server.js    # Node.js download backend (yt-dlp + ffmpeg)
│   └── lib/
│       └── metadata.js        # iTunes lookup, lyrics fetch, artwork download
├── public/                    # Static assets (copied as-is to dist/)
│   ├── sw.js                  # Service worker
│   ├── manifest.json          # PWA manifest
│   ├── icon.svg               # App icon
│   └── config.js              # Runtime config placeholder (generated by Docker)
├── android/                   # Android WebView APK wrapper
├── index.html                 # App shell + Vite entry point
├── styles.css                 # All styles
├── vite.config.js
├── Dockerfile                 # Multi-stage: Node build → nginx serve
├── docker-compose.yml
├── nginx.conf
└── docker-entrypoint.sh       # Injects NS_SERVER_URL / NS_BACKEND_URL at startup

Docker Setup

Frontend only

docker compose up -d

Environment variables (set in docker-compose.yml or via -e):

Variable Description
NS_SERVER_URL Pre-fills the Navidrome server URL on the login screen
NS_BACKEND_URL Pre-fills the download backend URL

With download backend

The backend requires yt-dlp and ffmpeg. A separate docker-compose.yml lives in backend/.

cd backend
docker compose up -d

Environment variables for the backend:

Variable Default Description
PORT 3700 Port the backend listens on
MUSIC_PATH /music Path to your Navidrome music folder (mount as volume)
AUDIO_FMT mp3 Output format (mp3, flac, opus, …)
AUDIO_QUALITY 0 yt-dlp audio quality (0 = best)
MAX_PARALLEL 2 Maximum concurrent downloads

Development

npm install
npm run dev      # Vite dev server with HMR
npm run build    # Production build → dist/
npm run preview  # Preview the production build locally

First Launch

  1. Open the app in a browser
  2. Enter your Navidrome server URL, username and password
  3. Optionally add a Last.fm API key (Settings) for recommendations and similar artists
  4. Optionally add the backend URL (Settings) to enable yt-dlp downloads
  5. Optionally connect Audiobookshelf (Settings) to stream audiobooks
S
Description
No description provided
Readme
5 MiB
0 Stars 0 Watchers 0 Forks
2026-09-02 09:26:49 +02:00
Languages
Kotlin 47.4%
JavaScript 40.1%
CSS 5.5%
HTML 5.4%
Python 0.8%
Other 0.8%