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.
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
|
*.ico binary
|
||||||
|
*.webp binary
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
# Abhängigkeiten
|
||||||
|
node_modules/
|
||||||
|
.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# Next.js
|
||||||
|
.next/
|
||||||
|
out/
|
||||||
|
build/
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# Produktion / Laufzeit
|
||||||
|
data/
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Umgebung — niemals committen!
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# Prisma
|
||||||
|
prisma/*.db
|
||||||
|
prisma/*.db-journal
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Editor / OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
.idea/
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# Tests / Screenshots-Rohdaten
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
|
.playwright/
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
## Fortschritt
|
||||||
|
|
||||||
|
- Stand: **Etappe 1 läuft** (Start 2026-09-01 18:09)
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# DEVLOG — Entwicklungszeiterfassung Flimmer
|
||||||
|
|
||||||
|
Alle Zeiten per `date`-Befehl erfasst (Europe/Berlin), nicht geschätzt.
|
||||||
|
Format je Eintrag: `Start – Ende (Dauer) — Beschreibung`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Etappe 1 — Projektgerüst, Branding, Docker, DB-Schema, Auth (v0.1.0)
|
||||||
|
|
||||||
|
| # | Start | Ende | Dauer | Arbeitsschritt |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 1.1 | 2026-09-01 18:09 | | | Rückfragen geklärt, Repo/Toolchain geprüft, Projekt-CLAUDE.md angelegt |
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
|
const nextConfig: NextConfig = {
|
||||||
|
// Schlankes Docker-Image: Next kopiert nur die wirklich benötigten Dateien.
|
||||||
|
output: "standalone",
|
||||||
|
reactStrictMode: true,
|
||||||
|
poweredByHeader: false,
|
||||||
|
serverExternalPackages: ["@prisma/client", "bcryptjs", "nodemailer"],
|
||||||
|
// Poster/Backdrops laufen über unseren eigenen Cache-Endpunkt, nicht über
|
||||||
|
// next/image-Remote-Loader — deshalb hier keine remotePatterns nötig.
|
||||||
|
images: {
|
||||||
|
dangerouslyAllowSVG: true,
|
||||||
|
contentDispositionType: "attachment",
|
||||||
|
},
|
||||||
|
async headers() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: "/sw.js",
|
||||||
|
headers: [
|
||||||
|
{ key: "Cache-Control", value: "no-cache, no-store, must-revalidate" },
|
||||||
|
{ key: "Service-Worker-Allowed", value: "/" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
Generated
+4352
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"name": "flimmer",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "Flimmer — selbst hostbarer Serien- und Film-Tracker",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "prisma generate && next build",
|
||||||
|
"start": "next start",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"db:generate": "prisma generate",
|
||||||
|
"db:migrate": "prisma migrate dev",
|
||||||
|
"db:deploy": "prisma migrate deploy",
|
||||||
|
"db:studio": "prisma studio",
|
||||||
|
"db:seed": "tsx prisma/seed.ts",
|
||||||
|
"icons": "tsx scripts/generate-icons.ts",
|
||||||
|
"screenshots": "tsx scripts/screenshots.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@prisma/client": "7.10.0",
|
||||||
|
"bcryptjs": "3.0.3",
|
||||||
|
"clsx": "2.1.1",
|
||||||
|
"date-fns": "4.4.0",
|
||||||
|
"jose": "6.2.10",
|
||||||
|
"next": "16.3.4",
|
||||||
|
"nodemailer": "9.1.0",
|
||||||
|
"react": "19.2.8",
|
||||||
|
"react-dom": "19.2.8",
|
||||||
|
"zod": "4.5.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tailwindcss/postcss": "4.3.3",
|
||||||
|
"@types/bcryptjs": "3.0.0",
|
||||||
|
"@types/node": "24.10.1",
|
||||||
|
"@types/nodemailer": "8.0.1",
|
||||||
|
"@types/react": "19.2.18",
|
||||||
|
"@types/react-dom": "19.2.5",
|
||||||
|
"playwright": "1.62.1",
|
||||||
|
"prisma": "7.10.0",
|
||||||
|
"sharp": "0.35.4",
|
||||||
|
"tailwindcss": "4.3.3",
|
||||||
|
"tsx": "4.23.13",
|
||||||
|
"typescript": "7.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=22"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
const config = {
|
||||||
|
plugins: {
|
||||||
|
"@tailwindcss/postcss": {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"plugins": [{ "name": "next" }],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user