HoneyandClaude Sonnet 4.6 3855207530 feat: artist cards with image in search + fix action bar overflow
Search: replace SmallArtistChip (text pill) with ArtistCard showing
circular profile image (72dp) + name below; works for both Navidrome
artists (uses coverArt) and iTunes artists (uses artworkUrl100 if present)

ArtistDetailScreen: convert action bar Row → LazyRow so Play / Shuffle /
Konzerte pills sit comfortably with horizontal scroll instead of cramming

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:24:18 +02:00

NovaSonic

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


Features

Music Library

  • Stream music from your Navidrome / Subsonic library
  • Browse artists, albums, playlists, starred tracks, and random picks
  • Sort and filter views 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
  • Star and context menu on every song row

Artist Pages

  • Full-bleed hero card — artist photo as portrait + blurred background (desktop); full-bleed image with name overlay (mobile)
  • Bio, similar artists, top songs pulled from Last.fm via Navidrome
  • Concert events via Ticketmaster (upcoming shows with venue, date, ticket link)
  • Albums cross-referenced against iTunes catalog — shows what's downloaded, partially downloaded, or missing
  • Quick actions: play top songs, shuffle all, open concerts

Playback

  • Queue management with shuffle, repeat (all / one), and radio mode (endless random)
  • Spotify-style shuffle — pre-shuffles the full queue so every song plays exactly once
  • Now Playing overlay with swipe-to-dismiss
  • Gapless-style playback — next track pre-buffered 60 seconds before current track ends
  • Lock screen / notification media controls (Android / iOS / desktop)
  • Scrobbling — reported to Navidrome (configurable: 15 s / 30 s / ⅓ / ⅔ / end)

Discovery

  • iTunes / Last.fm integration — charts, global search, 30-second previews, similar artists, recommendations
  • Song Importer — paste a Spotify, YouTube, YouTube Music, or SoundCloud link to preview and download tracks

Downloads (yt-dlp backend)

  • Download individual tracks, full albums, or entire artists
  • Sources: YouTube Music (primary), YouTube, SoundCloud, Spotify (via importer)
  • iTunes enrichment — album, year, track number, genre, 1000×1000 cover art
  • Duplicate detection — skips tracks already present on the server
  • Standard filename: 01 - Artist - Title.ext, organised into AlbumArtist/Album/ folders

Metadata Editor

  • Edit title, artist, album artist, album, genre, year, track number, disc number
  • Update embedded cover art via URL or file upload
  • File renamed and moved automatically on save
  • Navidrome rescan triggered after every save

Playlists

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

Audiobookshelf Integration

  • Browse and stream audiobooks from your Audiobookshelf server
  • Chapters list, playback speed, sleep timer, progress sync

App

  • PWA — installable on Android / iOS / desktop
  • Android APK — native WebView wrapper with Media3 / ExoPlayer backend
    • Native OS notification with skip buttons
    • Pre-buffers last played track on cold start for instant resume
    • Artwork pre-warming so notification never shows blank cover
  • Multiple color themes, dark mode, mobile-first responsive layout
  • German UI

Project Structure

NovaSonic/
├── src/
│   ├── player/
│   │   ├── player.js          # Playback, queue, transport, media session, preload
│   │   └── nowplaying.js      # Now Playing overlay
│   ├── views/
│   │   ├── detail.js          # Artist / album detail pages
│   │   ├── views.js           # Navigation, page loaders, search
│   │   ├── events.js          # Ticketmaster concert events
│   │   ├── home.js            # Home page, artist image cache
│   │   ├── search.js          # Search, artist/album navigation
│   │   ├── playlists.js       # Playlist management
│   │   ├── spotify.js         # Spotify importer
│   │   ├── youtube.js         # YouTube importer
│   │   ├── soundcloud.js      # SoundCloud importer
│   │   ├── navigation.js      # Client-side router
│   │   └── abs.js             # Audiobookshelf integration
│   ├── ui/
│   │   ├── ui.js              # Modals, sidebar, settings, context menu
│   │   ├── components.js      # Song rows, cards, shared UI
│   │   ├── downloads.js       # Download modal + job tracker
│   │   ├── metadata.js        # Metadata editor
│   │   ├── modals.js          # Song info, events modals
│   │   ├── notify.js          # Toast notifications
│   │   └── settings.js        # Settings page
│   ├── state.js               # Shared mutable state (S object)
│   ├── utils.js               # md5, esc, formatDur, toast
│   ├── api.js                 # Subsonic API, iTunes API, cover art
│   └── main.js                # App init, audio wiring, window globals
├── backend/
│   ├── novasonic-server.js    # Express API: downloads, metadata, events proxy
│   └── lib/
│       ├── config.js          # Env var → config object
│       ├── jobs.js            # In-memory download job store
│       ├── metadata.js        # iTunes lookup, artwork, lyrics, filename helpers
│       ├── ytdlp.js           # yt-dlp download + ffmpeg metadata embedding
│       ├── squid.js           # Qobuz (squid.wtf) download backend
│       ├── downloader.js      # Unified downloadTrack / downloadAlbumTracks
│       └── romaji.js          # Japanese → romaji search index
├── android/                   # Android APK (WebView + Media3/ExoPlayer)
├── public/
│   ├── sw.js                  # Service worker
│   ├── manifest.json          # PWA manifest
│   └── config.js              # Runtime config (generated by Docker entrypoint)
├── index.html
├── styles.css
├── vite.config.js
├── Dockerfile
├── docker-compose.yml
├── nginx.conf
└── docker-entrypoint.sh       # Injects NAVIDROME_URL / BACKEND_URL at runtime

Setup

1. Clone and configure

git clone <repo>
cd NovaSonic
cp .env.example .env

Edit .env:

NAVIDROME_URL=https://music.yourdomain.com
BACKEND_URL=https://novasonic-api.yourdomain.com

MUSIC_PATH=/srv/navidrome/music   # absolute path to your music folder on the host

AUDIO_FMT=mp3          # mp3 | flac | opus | best
AUDIO_QUALITY=0        # 0 = best (yt-dlp)
MAX_PARALLEL=2

DOWNLOAD_BACKEND=auto  # ytdlp | squid | auto
SQUID_QUALITY=mp3      # mp3 | flac | hi-res

TICKETMASTER_API_KEY=  # optional — free key from developer.ticketmaster.com

2. Start

docker compose up -d

This starts both the frontend (nginx on port 8080) and the backend (Node.js on port 3700). Route both ports through your reverse proxy.

3. First launch

  1. Open the app and enter your Navidrome server URL, username and password
  2. Optionally add a Last.fm API key in Settings for recommendations and artist bios
  3. Optionally connect Audiobookshelf in Settings to stream audiobooks

Environment Variables

Frontend container

Variable Description
NAVIDROME_URL Pre-fills the Navidrome server URL on the login screen
BACKEND_URL Pre-fills the download backend URL on the login screen

Backend container

Variable Default Description
PORT 3700 Port the backend listens on
MUSIC_PATH /music Absolute path to your Navidrome music folder (mounted as volume)
AUDIO_FMT mp3 Download output format (mp3, flac, opus, best)
AUDIO_QUALITY 0 yt-dlp audio quality (0 = best)
MAX_PARALLEL 2 Max concurrent download jobs
DOWNLOAD_BACKEND auto ytdlp / squid / auto (tries Qobuz first, falls back to yt-dlp)
SQUID_QUALITY mp3 Qobuz quality: mp3, flac, hi-res
TICKETMASTER_API_KEY — Free API key from developer.ticketmaster.com — enables concert events on artist pages

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
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%