Commit Graph
11 Commits
Author SHA1 Message Date
HoneyandClaude Opus 4.8 149443e4f7 feat(docker): image-based prod stack (Dockerfiles + prod compose + push script)
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>
2026-09-02 07:45:17 +02:00
HoneyandClaude Opus 4.8 71190488ca feat(scrobble): own timestamped play-log service (stats/Wrapped foundation)
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>
2026-08-06 22:54:25 +02:00
HoneyandClaude Sonnet 4.6 f1bdd811ca chore: remove squid.wtf (Qobuz) backend — yt-dlp only
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>
2026-06-18 20:59:30 +02:00
HoneyandClaude Sonnet 4.6 def625a622 chore: remove unused SPOTIFY_CLIENT_ID/SECRET from .env.example
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>
2026-06-08 20:47:30 +02:00
HoneyandClaude Sonnet 4.6 972c6b9722 docs: add TICKETMASTER_API_KEY to .env.example
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 20:43:03 +02:00
HoneyandClaude Sonnet 4.6 468827571a feat: switch Spotify auth to official Client Credentials Flow
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>
2026-05-09 22:57:01 +02:00
HoneyandClaude Sonnet 4.6 ac8d26bf9d feat: split backend into lib/ modules + add squid.wtf (Qobuz) download backend
- backend/lib/config.js  — CONFIG from env (adds DOWNLOAD_BACKEND, SQUID_QUALITY)
- backend/lib/jobs.js    — jobs Map, updateJob(), log()
- backend/lib/metadata.js — iTunes, artwork, lyrics, sanitize helpers
- backend/lib/ytdlp.js   — yt-dlp download cascade + shared embedMetadata()
- backend/lib/squid.js   — ALTCHA PoW solver, Qobuz search/download via squid.wtf
- backend/lib/downloader.js — backend selector: ytdlp | squid | auto (squid-first + fallback)
- novasonic-server.js thinned to Express routes only, imports from lib/
- docker-compose: mount full backend/ dir, install deps outside read-only volume
- .env.example: document DOWNLOAD_BACKEND and SQUID_QUALITY

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 20:44:26 +02:00
HoneyandClaude Sonnet 4.6 6e00b78219 Fix MUSIC_PATH direct mount + backend URL prefill
- 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>
2026-04-25 17:37:30 +02:00
HoneyandClaude Sonnet 4.6 a5461ff92c Fix bottom nav full-width layout + add backend URL autofill
- 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>
2026-04-25 17:03:34 +02:00
HoneyandClaude Sonnet 4.6 b6edfcf14b Add NAVIDROME_URL autofill, remove Navidrome scan trigger
- 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>
2026-04-25 16:44:38 +02:00
HoneyandClaude Sonnet 4.6 df69990625 Add Docker setup: nginx frontend + backend compose
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 14:55:28 +02:00