Gitea baut browser_download_url aus seiner eigenen ROOT_URL (hier
192.168.178.153:3000), die vom Backend-Container nicht erreichbar ist. Der
API-Call gelang, der Asset-Download nicht — der stille Fallback auf die nicht
vorhandene lokale Datei meldete dann "Keine APK hinterlegt". Asset- und
Redirect-URLs werden jetzt auf GITEA_URL umgeschrieben; scheitert der Weg
trotzdem, sagen Log und Fehlermeldung welcher der beiden Wege fehlt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Namen getauscht: das Standard-Compose zieht jetzt die fertigen Registry-Images
(vorher docker-compose.prod.yml), die Build-Variante heisst docker-compose.dev.yml.
Weniger verwirrend, weil der Produktivfall ohne -f auskommt. Kopfkommentare,
README, CLAUDE.md, .env.example und build-push-images.mjs entsprechend angepasst.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Chosen flow: build on the host from backend/scrobble Dockerfiles instead of
pulling from a registry (no registry / no Docker-on-dev needed). Heavy deps are
baked, so restarts are instant and rebuilds after git pull are cache-fast.
Removed the now-obsolete docker-compose.dev.yml (runtime-install variant); the
optional push-to-registry script stays for a future CI flow. Updated README,
CLAUDE.md, .env.example.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Less confusion: docker-compose.yml is now the default (pulls pre-built images)
and the build-on-host variant is docker-compose.dev.yml. Updated all references
(CLAUDE.md, README, .env.example, build-push-images.mjs, compose header).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a pull-based production option so the host no longer builds/installs deps
on every restart:
- backend/Dockerfile + scrobble/Dockerfile bake the heavy deps (ffmpeg, Deno,
yt-dlp, node libs). Backend still refreshes yt-dlp on start (non-fatal).
- docker-compose.prod.yml pulls ${REGISTRY}/novasonic-*:${TAG}.
- scripts/build-push-images.mjs (npm run push-images) builds + pushes all three.
- .env.example documents every var incl. REGISTRY/TAG; .env gitignored.
The build-on-host docker-compose.yml stays as-is.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 1+2 of a self-hosted, multi-user listening archive — the basis for
day/month/year stats and a yearly "Wrapped". Runs IN ADDITION to the existing
Navidrome/Last.fm scrobble; never replaces it.
Service (isolated, own container):
- scrobble/scrobble-server.js — node:sqlite play-log (own volume), routes
POST /scrobble/plays (idempotent by uuid), GET /scrobble/history (archive),
DELETE /scrobble/plays?user= (test cleanup), GET /scrobble/health.
Multi-user auth via Navidrome ping.view (cached) -> user not spoofable.
- docker-compose: novasonic-scrobble service (node:22, port 3710) + volume;
backend bumped node:20->22 (EOL); SCROBBLE_URL plumbing (entrypoint, .env.example).
Capture (both platforms, offline-safe queue, idempotent batch flush):
- Fires at the existing scrobbleMode counted-play moment — consistent with
Last.fm, respects the user's setting (no separate 50%/4min rule).
- Web: src/player/scrobbleLog.js (localStorage queue) + subsonicAuthParams()
in api.js + hooks in player.js + flush init in main.js; S.cfg.scrobbleUrl.
- Android: data/PlayLogClient.kt (filesDir queue, reused Ktor client) +
repo.logPlay/flushPlayLog + PlayerController hook + NovaSonicApp flush +
scrobbleUrl in PrefsStore/SettingsViewModel/SettingsScreen (with test button).
Plan + design decisions documented in docs/scrobble-plan.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deletes backend/lib/squid.js; strips all references from downloader.js,
config.js, novasonic-server.js, docker-compose.yml, .env.example, README,
and CHANGELOG. Default DOWNLOAD_BACKEND is now ytdlp.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Spotify importer resolves links without OAuth credentials — these
variables were never read by any code.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the broken open.spotify.com/get_access_token scrape with
accounts.spotify.com/api/token (Basic auth, client_credentials grant).
Adds SPOTIFY_CLIENT_ID/SECRET to config, docker-compose, and .env.example.
Health endpoint now reports spotify.configured; frontend disables the
importer and shows a setup guide when credentials are missing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- MUSIC_PATH is now used 1:1 inside the container (no /music remapping)
- config.js 404-safe with inline fallback defaults
- Prefill uses .trim() so empty strings don't overwrite fields
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove max-width/gap/padding from bottom nav so buttons fill full screen width
- Add NS_BACKEND_URL to config.js entrypoint and autofill backend-url field on setup screen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Frontend reads window.NS_SERVER_URL from config.js (injected at container start via docker-entrypoint.sh) and pre-fills the setup screen
- Removed triggerNaviScan from frontend and backend (Navidrome auto-scans on file change)
- Removed NAVIDROME_USER/PASS from backend and compose
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>