Files
lyssnarr/doc/plan.md
claude 4e0a8aae13
All checks were successful
build-and-push / build (push) Successful in 32s
Milstolpe 1: skelett — Fastify-backend med login, Vue-frontend (mörkt Jellyseerr-tema), Dockerfile
- backend: /api/health, /api/login|logout|session, sessionscookie,
  timingSafeEqual-lösenordskoll, allt annat under /api kräver inloggning,
  serverar byggd frontend med SPA-fallback; 4 tester (node:test)
- frontend: Vue 3 + Vite, login-sida, Upptäck-skal, sökfält (stub),
  mörkt tema enligt Jellyseerr-förlagan
- docker: multi-stage arm64-image; config-plumbing för Lidarr/Jellyfin/
  Gemini via env (Jellyfin-historik prioriterad som signal per Björn)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01824ZrvG2mDYYrmwqypLNup
2026-07-31 23:18:25 +02:00

3.8 KiB
Raw Permalink Blame History

lyssnarr — plan

Goal

Self-hosted music-discovery web app on the Pi5. A Jellyseerr-style UI where Björn can (a) search for new artists, albums and tracks, and (b) get scheduled AI-generated suggestions based on two taste signals: recent listening in the local library (Jellyfin) and tracks recently added to his YouTube Music playlists (via Youtubarr's data). Every result can be added to Lidarr with one click, opened in YouTube Music, or played inline in the app.

Stack

  • Backend: Node ≥ 20, Fastify, better-sqlite3 (suggestion history + feedback), node-cron (scheduled generation)
  • Frontend: Vue 3 + Vite; dark, poster/card-based UI modelled on Jellyseerr (top search bar, discover grid, action buttons per card); built to static files served by the backend
  • Container: single arm64 image, multi-stage Dockerfile (frontend build → backend deps → slim runtime), mirrors Archivum

Deploy target

Pattern B (container on Pi5): Gitea Actions on the Pi5 runner → localhost:5000/lyssnarr:latest → Dockge stack /srv/dockge-staks/lyssnarr/ → NPM vhost https://lyssnarr.brasse-pc.eu (public from day one → the app ships with login from day one: single user, bcrypt-hashed password from the stack .env, signed session cookie).

Integrations

What How
Lidarr REST API (http://lidarr:8686): add/monitor artists & albums, check what's already in the library
MusicBrainz search + canonical MBIDs (Lidarr adds are MBID-based)
YouTube Music unofficial YT Music search from Node → browse/video IDs for "open in YT Music" deep links, thumbnails for the cards, inline playback via YouTube IFrame embed
Gemini API suggestion generation; GEMINI_API_KEY + model via env
Youtubarr read-only mount of its SQLite (/srv/docker/youtubarr/data/db.sqlite3) → "recently added to playlists" signal
Jellyfin play-history signal (prioritised by Björn 2026-07-31) — infra prerequisite: mount /srv/storage1/Music into the jellyfin container + create a music library (container recreate, needs Björn's OK)

UI sketch (Jellyseerr-like)

  • Top: search bar with artist/album/track scope
  • Landing "Upptäck": latest suggestion batch as poster cards, each with Gemini's one-line motivation
  • Card actions: Lidarr · ▶ Spela (inline YouTube embed) · ↗ YT Music (deep link)
  • Badge on cards already in the Lidarr library
  • History page with earlier batches

Milestones

  1. Skeleton end-to-end — repo, CI, Dockerfile, dockge stack, NPM vhost, login; an empty authenticated shell reachable on lyssnarr.brasse-pc.eu
  2. Lidarr integration — library state + add/monitor actions
  3. Search page — MusicBrainz search enriched with YT Music thumbnails/links, add/play/open actions
  4. On-demand suggestions — "generera nu": Gemini prompt built from Lidarr library + Youtubarr playlist adds + Jellyfin play history (used as soon as it's configured)
  5. Scheduler + history — cron-generated batches, history page
  6. Jellyfin music library — infra step on the Pi5 (mount + library) so the play-history signal has data

Roadmap / expansions (proposed — Björn confirms/strikes)

  • 👍/👎 feedback per suggestion, fed into the next Gemini prompt
  • Auto-add top suggestions to Lidarr as monitored (configurable)
  • Track-level batches exported as M3U playlists into Jellyfin
  • Library profile page (genre/decade distribution)
  • Webhook/notification when a new batch lands
  • Liked Music as a direct signal (ytmusicapi sidecar or Node port)

Open questions

  • Gemini model: default gemini-2.5-flash, configurable via env — ok?
  • Auth: built-in single-user login vs Authentik forward-auth later
  • Artwork order: YT Music thumbnails first, Cover Art Archive fallback