Commit Graph
19 Commits
Author SHA1 Message Date
Florian Wilde f9ce2f7021 feat: Bibliotheksseite, Papierkorb und manuelles Anlegen
Die Detailseite hängt jetzt an der internen Titel-ID statt an der TMDB-ID —
nur so bekommen manuell angelegte Titel dieselbe Seite. Treffer aus der Suche
laufen über /tmdb/<art>/<id>, das den Titel holt und weiterleitet.

Der Fortschritt einer ganzen Liste wird in einer Abfrage gezählt statt je
Eintrag; bei 300 Titeln wären das sonst 300 Rundreisen zur Datenbank.

Entfernte Titel wandern für 30 Tage in den Papierkorb und behalten ihren
Fortschritt.
2026-09-01 19:24:51 +02:00
Florian Wilde f613136e8a feat: Bedienelemente für Bibliothek und Episodenfortschritt
Server-Aktionen prüfen die Sitzung jeweils selbst — auf Angaben aus dem
Formular ist beim Zugriffsschutz kein Verlass.

Häkchen reagieren sofort und werden zurückgedreht, wenn der Server
widerspricht: Abhaken soll sich anfühlen wie ein Schalter, nicht wie ein
Formular. Jede Sichtungsaktion meldet sich unten kurz zurück und lässt sich
von dort zurücknehmen — die Wirkung passiert weit weg vom Klick.
2026-09-01 19:24:51 +02:00
Florian Wilde 4c3c878980 test: Kern-Tracking absichern
14 Tests für Aufnehmen, Abhaken, Fortschritt ohne Specials, Rewatch,
Papierkorb, Rückgängig und den Zugriffsschutz zwischen Nutzern.

Die Testdateien laufen jetzt seriell: parallel räumten sie sich gegenseitig
die gemeinsamen Katalog-Fixtures weg.
2026-09-01 19:24:50 +02:00
Florian Wilde bb6ce4ab35 feat: Kern-Tracking mit Sichtungen, Fortschritt und Rewatches
Grundgedanke: Eine Sichtung ist die einzige Wahrheit darüber, was jemand
gesehen hat. Fortschritt, „nächste Episode" und später die Statistik werden
daraus berechnet, nichts davon wird doppelt gespeichert.

Rewatches zählen über einen Durchlaufzähler am Eintrag. Ein neuer Durchlauf
setzt den Fortschritt zurück, die alten Sichtungen bleiben stehen — sonst
verlöre die Schauzeit-Statistik jedes Mal ihre Geschichte.

Der Status ergibt sich aus den Sichtungen: die erste Episode startet, die
letzte schließt ab. Pausiert und Abgebrochen bleiben unangetastet — wer
bewusst pausiert hat, will das nicht durch ein Häkchen aufgehoben bekommen.
2026-09-01 19:24:49 +02:00
Florian Wilde 9ecaaf03a9 docs: Changelog, Release-Notes und DEVLOG für 0.2.0 v0.2.0 2026-09-01 19:00:14 +02:00
Florian Wilde 75128d1bf2 test: Importpfad gegen nachgebildete TMDB-Antworten prüfen
npm test läuft ohne TMDB-Schlüssel gegen die Entwicklungsdatenbank und deckt
Kopfdaten, Staffeln, Episoden, Streamingdienste je Region, wiederholten
Import und die Auffrischlogik ab.

Dabei aufgefallen: importSeries gab den Titel zurück, bevor die Staffel- und
Episodenzähler geschrieben waren — die Zähler standen auf 0.
2026-09-01 19:00:13 +02:00
Florian Wilde e11cb6abef feat: Suchseite und Titel-Detailseite
Die Suchanfrage steht in der URL: Treffer sind teilbar, der Zurück-Knopf
funktioniert, und die Suche selbst bleibt eine Server-Komponente.

Posterkacheln zeigen bei fehlendem Bild die Bildmarke über dem
Signaturverlauf. Die Rückfalldarstellung liegt dauerhaft unter dem Bild —
ein onError-Handler hilft nicht, wenn das Bild schon vor der Hydration
scheitert, und der Browser zeigt dann sein kaputtes Bildsymbol.
2026-09-01 19:00:13 +02:00
Florian Wilde cc0e498fe6 feat: Katalogschicht und lokaler Bild-Cache
Der Katalog ist bewusst gemeinsam für alle Nutzer und über (Typ, TMDB-ID)
dedupliziert: zehn Leute mit derselben Serie brauchen die Episodenliste nur
einmal. Persönliches steckt ausschließlich in LibraryEntry und Watch.

Poster laufen über /api/image statt direkt zu TMDB — einmal holen, danach
vom eigenen Server ausliefern. Größe und Pfad werden streng geprüft, damit
daraus kein offener Proxy wird.

Staffel 0 (Specials) wird importiert, zählt aber nicht zum Fortschritt;
Episoden ohne eigene Laufzeit fallen auf die durchschnittliche Episodenlänge
der Serie zurück.
2026-09-01 19:00:12 +02:00
Florian Wilde 4feb84c060 feat: TMDB-Client für Suche, Details und Episodendaten
Nur die Endpunkte, die Flimmer wirklich braucht, samt der Felder, die uns
interessieren. Antworten werden zehn Minuten zwischengespeichert, damit
Tippen im Suchfeld nicht jedes Zeichen einzeln nach draußen trägt.

Zugang wahlweise über den klassischen API-Schlüssel oder das Bearer-Token —
TMDB gibt beides aus, und Selbsthoster haben mal das eine, mal das andere.
2026-09-01 19:00:11 +02:00
Florian Wilde d1303d10f5 docs: Zeiten der Etappe 1 im DEVLOG festhalten v0.1.0 2026-09-01 18:47:06 +02:00
Florian Wilde b05dd1b01e feat: Healthcheck-Endpunkt für Reverse-Proxy und Monitoring
/api/health prüft die Datenbankverbindung mit und antwortet bei Ausfall mit
503 — eine App ohne Datenbank ist nicht gesund, auch wenn der Prozess läuft.
2026-09-01 18:46:55 +02:00
Florian Wilde 2e8e4df6cf docs: README, Design-Dokumentation, Changelog und Seed
README mit Installation, Update-Weg und Backup-Anleitung; docs/DESIGN.md
hält Marke, Farbwerte samt gemessener Kontraste und die Bausteine fest.
Changelog nach Keep a Changelog, Release-Notes zusätzlich unter releases/.
2026-09-01 18:46:49 +02:00
Florian Wilde 63d47b4ead feat: Docker-Compose-Setup zum Selbsthosten
Dreistufiges Image: Abhängigkeiten, Build, Laufzeit. Im Endbild landen nur
der standalone-Server, die statischen Dateien und die Prisma-CLI — letztere,
damit der Container ausstehende Migrationen beim Start selbst einspielt.

Der Entrypoint wartet per TCP-Verbindung auf die Datenbank, statt dafür ein
zusätzliches Paket ins Laufzeitimage zu ziehen.
2026-09-01 18:46:48 +02:00
Florian Wilde 7f8ad716b6 feat: optionale SSO-Anmeldung über OIDC
Authorization Code mit PKCE, ID-Token gegen die JWKS des Anbieters geprüft.
Ohne Client-Bibliothek: Flimmer braucht genau einen Ablauf, dafür lohnt
keine weitere Abhängigkeit mit eigenem Versionsrhythmus.

Bekannte SSO-Kennungen werden verknüpft, sonst über die E-Mail-Adresse
einem vorhandenen Konto zugeordnet; das Anlegen neuer Konten lässt sich
per OIDC_AUTO_REGISTER unterbinden.
2026-09-01 18:46:47 +02:00
Florian Wilde b001e62695 feat: App-Hülle mit Header, Theme-Umschalter und Übersicht
Layout mit Inline-Skript, das data-theme setzt, bevor der erste Pixel
gemalt wird — sonst blitzt beim Laden das falsche Farbschema auf. Logo als
React-Komponente statt als Bilddatei: nimmt Theme-Farben an, spart einen
Netzwerkabruf und die Verläufe liegen einmalig im Root-Layout.

Im hellen Modus greifen eigene Tokens für Verlaufstext und Wortmarke; der
vollfarbige Signaturverlauf fällt auf warmem Weiß sonst unter WCAG AA.
2026-09-01 18:46:47 +02:00
Florian Wilde 01c0f9bc9f feat: Registrierung, Anmeldung und Sitzungen
Passwörter mit bcrypt, Sitzungen als opake Token in der Datenbank — im
Cookie steht das Klartext-Token, in der Tabelle nur dessen SHA-256. Damit
lassen sich einzelne Geräte gezielt abmelden, was reine JWT-Sitzungen nicht
hergeben.

Der erste registrierte Zugang wird automatisch Administrator, sonst käme
man nach dem Aufsetzen nicht in die Verwaltung. Die Registrierung ist
instanzweit abschaltbar; solange es keinen Nutzer gibt, bleibt sie offen.

Enthält außerdem API-Schlüssel je Nutzer als Grundlage für die spätere
REST-API und die Instanz-Einstellungen in der Tabelle AppSetting.
2026-09-01 18:46:27 +02:00
Florian Wilde 3e11e4ffb1 feat: Datenmodell für Katalog, Tracking und Universen
Prisma-Schema in vier Schichten: Konten und Zugang, gemeinsamer Katalog
(über die TMDB-ID dedupliziert), persönliches Tracking je Nutzer sowie
Universen mit mehreren Reihenfolgen. Dazu Benachrichtigungskanäle und
Protokoll der Hintergrundläufe.

Prisma 7 verlangt einen Treiber-Adapter statt der URL im Schema; die
Konfiguration liegt deshalb in prisma.config.mjs — bewusst als .mjs, damit
die CLI auch im schlanken Produktionsimage ohne TypeScript-Loader läuft.
2026-09-01 18:46:27 +02:00
Florian Wilde 488b99f7a1 feat: Flimmer-Branding mit Logo, Icons und Design-Tokens
Logo als SVG in drei Varianten (Icon, Icon+Wortmarke horizontal, monochrom);
die Wortmarke ist als Pfad konstruiert und braucht daher keine installierte
Schrift. Daraus generiert scripts/generate-icons.ts Favicon (SVG + ICO),
PWA-Icons, Maskable-Icons, Apple-Touch-Icon und OG-Bild.

Die Farbwelt liegt als CSS-Variablen in globals.css und wird ueber
@theme inline an Tailwind durchgereicht — Dark/Light und spaetere Themes
bauen darauf auf. Alle Kombinationen erfuellen WCAG AA.
2026-09-01 18:26:21 +02:00
Florian Wilde 0bdfd66c93 chore: Projektgeruest mit Next.js 16, TypeScript und Tailwind v4
Konfiguration fuer Next (standalone-Build), TypeScript, PostCSS/Tailwind,
.gitignore und .gitattributes. CLAUDE.md haelt die Projektentscheidungen
und den Arbeitsauftrag fest, DEVLOG.md die Zeiterfassung.
2026-09-01 18:26:21 +02:00