CI / pruefen (pull_request) Canceled after 0s
Errungenschaften und die Auswahlliste fuer unbekannte Jellyfin-Titel. Changelog, Release-Notiz, DEVLOG und Projektgedaechtnis nachgezogen. Die Anleitung hat ihre beiden Abschnitte schon mit den jeweiligen Issues bekommen — Errungenschaften mit Screenshot, „Titel, die Flimmer noch nicht kennt" im Jellyfin-Kapitel.
165 lines
10 KiB
Markdown
165 lines
10 KiB
Markdown
# Flimmer — Arbeitsauftrag & Projektgedächtnis
|
|
|
|
> Diese Datei ist mein (Claude) Gedächtnis für dieses Projekt. Sie hält fest,
|
|
> **was gebaut werden soll**, **wie gearbeitet wird** und **wo ich gerade stehe**.
|
|
> Nach jeder Etappe wird der Abschnitt „Fortschritt" aktualisiert.
|
|
|
|
## Was ist Flimmer?
|
|
|
|
Selbst hostbarer Serien- & Film-Tracker (angelehnt an „Flimmerkiste"). Multi-User,
|
|
TMDB-Metadaten, Episodenfortschritt, eigene Universen mit mehreren Reihenfolgen,
|
|
Statistiken, Benachrichtigungen, REST-API, PWA. Oberflächensprache **Deutsch**.
|
|
|
|
## Verbindliche Entscheidungen (nicht ohne Rückfrage ändern)
|
|
|
|
| Bereich | Entscheidung | Begründung |
|
|
|---|---|---|
|
|
| Framework | **Next.js 15, App Router, TypeScript** | UI + REST-API + Cron in einem Deployment; Server Components halten Prisma serverseitig; `output: "standalone"` ergibt ein schlankes Docker-Image |
|
|
| DB | **PostgreSQL + Prisma** (Schema + Migrationen) | vorgegeben |
|
|
| Styling | **Tailwind CSS v4** (`@theme`, CSS-Variablen) | Design-Tokens sind in v4 nativ CSS-Variablen → Dark/Light/Themes bauen sauber darauf auf |
|
|
| Auth | **eigene Session-Schicht**: bcryptjs + opake Tokens in DB-Tabelle `Session`, httpOnly-Cookie; OIDC optional über `jose` + Discovery | DB-Sessions erlauben Sperren/Abmelden durch Admin; kein Beta-API-Risiko von next-auth v5; Credentials + OIDC parallel möglich |
|
|
| Passwort-Hash | **bcryptjs** (pure JS) | keine nativen Build-Abhängigkeiten im Docker-Image |
|
|
| Scheduler | in-process über `instrumentation.ts` (`ENABLE_SCHEDULER`) **plus** `/api/cron/*` mit `CRON_SECRET` | kein zweiter Container nötig, externe Scheduler trotzdem möglich |
|
|
| Bild-Cache | Dateien unter `DATA_DIR/images`, ausgeliefert über `/api/image` | kein TMDB-Abruf pro Seitenaufruf |
|
|
| Charts | handgeschriebene SVG-Komponenten | volle Kontrolle über Design-Tokens, keine Chart-Lib-Abhängigkeit |
|
|
| PWA | eigenes `sw.js` + `manifest.webmanifest` | keine zusätzliche Abhängigkeit |
|
|
| i18n | Dictionary `src/i18n/de.ts` + `t()`-Helper mit Punkt-Keys | weitere Sprachen ergänzbar |
|
|
| API | `/api/v1/**`, Bearer-API-Keys pro Nutzer, OpenAPI unter `/api/v1/openapi.json` | für spätere Mobile-App/Skripte |
|
|
|
|
## Branding (fix)
|
|
|
|
- Name **Flimmer**, Motiv: warmes Flimmern des Bildschirms
|
|
- Logo als **SVG**: abgerundetes Bildschirm-Rechteck, weiches warmes Glühen (Gradient),
|
|
dezentes Play-Dreieck; Wortmarke in moderner, leicht gerundeter Sans
|
|
- Drei Varianten: **Icon**, **Icon + Wortmarke horizontal**, **monochrom**
|
|
- Favicon + PWA-Icons (inkl. **maskable**) aus dem Icon generiert
|
|
- Farbwelt: sehr dunkles Blauviolett/Anthrazit als Grund, Signatur = **Glow-Gradient
|
|
Bernstein → Magenta**; Light Mode = dieselben Akzente auf warmgrauem Grund
|
|
- **Alle Kombinationen müssen WCAG AA erfüllen**
|
|
- UI: posterlastig, großzügige Karten mit sanftem Hover-Glow, runde Ecken, weiche
|
|
Verläufe, ruhige Mikro-Animationen (Aufglimmen beim Abhaken)
|
|
- Logo + Name konsistent in Header, Login, E-Mail-/Notification-Templates, README
|
|
|
|
## Arbeitsregeln
|
|
|
|
- **Git-Repo** mit Remote `origin` → `https://git.wilde-server.de/florian.wilde/flimmer.git`, Branch `main`
|
|
- **Conventional Commits** (`feat:`, `fix:`, `chore:`, `docs:` …), Nachrichten deutsch
|
|
- **Kleine Commits** nach jedem abgeschlossenen Schritt — kein Riesen-Commit
|
|
- `.env` **niemals** committen (nur `.env.example`)
|
|
- **CHANGELOG.md** im Keep-a-Changelog-Format, SemVer ab 0.1.0; jede Etappe = neue Minor-Version
|
|
- Pro Version: **Git-Tag** `vX.Y.Z` + **Gitea-Release** (via Gitea-MCP, `gh`/`tea` sind nicht installiert),
|
|
Titel = Version, Notes = Changelog-Abschnitt; zusätzlich `releases/vX.Y.Z.md` ablegen
|
|
- **DEVLOG.md**: pro Arbeitsphase Start-/Endzeit per `date`-Befehl (nicht schätzen) + Kurzbeschreibung;
|
|
je Etappe Summe, am Ende Gesamtübersicht
|
|
- Versionsnummer aus `package.json` im UI anzeigen (Footer/Einstellungen)
|
|
- Umgebung: **Windows + PowerShell/Git-Bash**, VS Code. `curl` → `curl.exe`. Keine Desktop-Benachrichtigungen.
|
|
|
|
## Etappen
|
|
|
|
1. **Projektgerüst, Branding, Docker-Compose, DB-Schema, Auth** → v0.1.0
|
|
2. **TMDB-Anbindung**: Suche, Detailimport, Episodendaten, Bild-Cache → v0.2.0
|
|
3. **Kern-Tracking**: Bibliothek, Status, Episodenfortschritt, Watchlist → v0.3.0
|
|
4. **Universen** mit Reihenfolgen und Fortschritt → v0.4.0
|
|
5. **Dashboard, Kalender, Statistiken** → v0.5.0
|
|
6. **Benachrichtigungen, Sync-Job, Import/Export, REST-API, PWA-Feinschliff** → v0.6.0
|
|
|
|
## Ausdrücklich gewünscht (nicht vergessen!)
|
|
|
|
- [ ] **Bebilderte Anleitung** `docs/ANLEITUNG.md` mit **Screenshots** der laufenden App
|
|
(Playwright gegen die geseedete Instanz, Bilder nach `docs/screenshots/`)
|
|
- [ ] Papierkorb (30 Tage) statt hartem Löschen + **Undo** für „als gesehen markiert"
|
|
- [ ] Seed-Skript mit Beispieldaten
|
|
- [ ] Backup-Hinweise (DB-Dump) in der README
|
|
- [ ] Healthcheck `/api/health`
|
|
- [ ] Öffentliche Profilseite (abschaltbar)
|
|
- [ ] Rewatch-Tracking (Durchläufe, bei Serien pro Durchlauf)
|
|
- [ ] Streaming-Verfügbarkeit (TMDB Watch Providers), Region konfigurierbar, Standard DE
|
|
- [ ] Import: Trakt.tv-Export + CSV; Export: CSV/JSON
|
|
- [ ] Benachrichtigungen: SMTP, ntfy, Gotify, generischer Webhook — pro Nutzer
|
|
- [ ] Streamingdienste mit konsistenten Akzentfarben/Badges im ganzen UI
|
|
- [ ] Optional per ENV: OIDC/SSO (Authelia, Keycloak)
|
|
- [ ] Registrierung durch Admin abschaltbar; erster Nutzer wird Admin
|
|
|
|
## Wichtige technische Merkposten
|
|
|
|
- **Next 16**: Request-APIs sind async (`cookies()`, `headers()`, `params`,
|
|
`searchParams`). `middleware.ts` heißt jetzt `proxy.ts`. Turbopack ist Standard.
|
|
Breaking Changes stehen in `node_modules/next/dist/docs/01-app/02-guides/upgrading/version-16.md`.
|
|
- **Prisma 7**: keine `url` im Schema — Treiber-Adapter (`@prisma/adapter-pg`)
|
|
im Client, URL in `prisma.config.mjs`. Generator ist `prisma-client`
|
|
(TypeScript-Ausgabe nach `src/generated/prisma`, gitignored).
|
|
Config bewusst `.mjs`, damit die CLI im Produktionsimage ohne TS-Loader läuft.
|
|
- **Tailwind v4**: `@theme inline` reicht die `--fl-*`-Variablen durch,
|
|
`@custom-variant dark` hängt an `[data-theme="dark"]`.
|
|
- **Zwei Verläufe**: `--fl-gradient` für Flächen, `--fl-gradient-ink` für Text
|
|
(im Light Mode abgedunkelt, sonst kein AA). Logo-Stops `--fl-brand-1/2/3`.
|
|
- **Dev-Umgebung**: Postgres auf `localhost:5439` (`docker-compose.dev.yml`),
|
|
Dev-Server auf **Port 3011** (3000 und 3010 sind von anderen Projekten belegt).
|
|
- **Screenshots**: `node scripts/shot.mjs <url> <ziel.png> [w] [h] [theme]`.
|
|
Achtung: das Skript meldet sich **nicht** an — bei geschützten Seiten entsteht
|
|
kommentarlos ein Bild der Anmeldemaske. Für angemeldete Ansichten den
|
|
Login-Weg aus `scripts/screenshots.mjs` nachbauen.
|
|
- Next hängt selbst einen Block an diese Datei an — der bleibt drin.
|
|
|
|
## Fortschritt
|
|
|
|
- ✅ **Etappe 1** (v0.1.0) — Gerüst, Branding, Docker, Schema, Auth. 38 min.
|
|
- ✅ **Etappe 2** (v0.2.0) — TMDB: Suche, Import, Episoden, Bild-Cache. 14 min.
|
|
- ✅ **Etappe 3** (v0.3.0) — Bibliothek, Status, Episodenfortschritt, Papierkorb. 24 min.
|
|
- ✅ **Etappe 4** (v0.4.0) — Universen mit Reihenfolgen, Freigaben. 14 min.
|
|
- ✅ **Etappe 5** (v0.5.0) — Übersicht, Kalender, Statistik. 15 min.
|
|
- ✅ **Etappe 6** (v0.6.0) — Benachrichtigungen, Abgleich, Import/Export, REST-API, PWA, Anleitung. 31 min.
|
|
|
|
**Alle sechs Etappen abgeschlossen. Gesamtzeit: 2 h 16 min.**
|
|
|
|
- ✅ **Nacharbeiten** (v0.7.0/0.7.1) — Docker verifiziert, „hab ich", `update.sh`. 51 min.
|
|
- ✅ **Issue-Runde** (v0.8.0) — Passkeys, Jellyfin-Anbindung, Standardreihenfolge,
|
|
Rückmeldung beim Tippen, Titelraster, Filmsichtung zurücknehmen. 77 min.
|
|
- ✅ **Zweite Runde** (v0.9.0) — Errungenschaften, Auswahlliste für unbekannte
|
|
Jellyfin-Titel. 37 min.
|
|
|
|
Ab v0.8.0 wird **issue-getrieben** gearbeitet: eigener Branch je Issue,
|
|
Zeiterfassung in Gitea, Freigabe durch Florian. Details im DEVLOG.
|
|
|
|
### Nützliches für spätere Arbeiten
|
|
- Suche ohne TMDB-Schlüssel ausprobieren:
|
|
`npm run tmdb:stub` und dann
|
|
`TMDB_API_KEY=stub TMDB_BASE_URL=http://127.0.0.1:3099/3 PORT=3011 npm run dev`
|
|
- Screenshots neu aufnehmen: `npm run screenshots` (nimmt auf und verkleinert)
|
|
- `npm test` läuft seriell gegen die Dev-Datenbank, braucht keinen TMDB-Schlüssel
|
|
- Deutsche Anführungszeichen (`„…"`) niemals in JS-**String-Literalen** —
|
|
das ASCII-Schlusszeichen beendet den String. In JSX-Text und Kommentaren ok.
|
|
- Heredocs im Bash-Tool sind bei langen TSX-Dateien unzuverlässig — dann das
|
|
Write-Werkzeug benutzen.
|
|
- **Wenn Klicks unter Playwright wirkungslos bleiben, liegt es meist nicht am
|
|
eigenen Code.** Beobachtet: gegen `npm run dev` reagierte unter headless
|
|
Chromium **keine** Seite — kein Knopf, nicht einmal der Theme-Umschalter,
|
|
ohne Seitenfehler und ohne fehlgeschlagene Anfrage. Begleitet vom
|
|
scheiternden HMR-Socket (`ERR_INVALID_HTTP_RESPONSE`).
|
|
**Der Zustand ist aber nicht dauerhaft:** in einem späteren Lauf gegen
|
|
denselben Dev-Server funktionierten dieselben Klicks. Der HMR-Fehler tritt
|
|
in beiden Fällen auf, taugt also nicht als Erklärung.
|
|
Vorgehen: erst mit `Object.keys(el).some(k => k.startsWith("__react"))`
|
|
prüfen, ob überhaupt hydratisiert wurde. Bleibt es dabei, gegen einen
|
|
Produktionsbau prüfen (`npm run build`, `PORT=3012 npm start`) — dort trat
|
|
es nie auf. Formulare täuschen zusätzlich: die Anmeldung funktioniert auch
|
|
ohne JavaScript und wirkt deshalb intakt.
|
|
- Vor `npm start` prüfen, ob der Port noch von einem früheren Lauf belegt ist —
|
|
sonst startet der neue Server gar nicht und man testet den alten Bau.
|
|
- **`APP_URL` muss zum tatsächlich aufgerufenen Port passen.** In der `.env`
|
|
steht `http://localhost:3010`; wer gegen 3011 oder 3012 testet, muss
|
|
`APP_URL` mitgeben. Passkeys scheitern sonst am Ursprungsabgleich (500),
|
|
und der OIDC-Rücksprung zeigt auf die falsche Adresse.
|
|
- Testdaten nach Klickproben wieder herstellen: die Proben schreiben in die
|
|
geseedete Entwicklungsdatenbank.
|
|
|
|
<!-- BEGIN:nextjs-agent-rules -->
|
|
|
|
# This is NOT the Next.js you know
|
|
|
|
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.
|
|
|
|
This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.
|
|
|
|
<!-- END:nextjs-agent-rules -->
|