Commander-Entscheid 24.07.: nur noch EIN Branch. Der stable-Zwischenbranch war vestigial — die VM deployt ohnehin aus main (git pull), das Gruen-Gate hat den Live-Deploy nie real gegated. - ci.yml: Beförderungs-Schritt (push -> stable) entfernt; die Ampel prueft nur noch (Ruff/pytest/Vite-Build), Rot heisst weiterhin: nicht deployen. - deploy.sh: klont/resettet auf main statt stable. - AGENTS §C, README (Entwicklung), DESIGN-2.0-Briefing: auf main-only umgeschrieben. Design-2.0-Briefing als ERLEDIGT markiert. - SAVEPOINT v3.6. Branches stable / design-2.0 / kernumbau-2026-07-23 werden nach diesem Push geloescht (Inhalte vollstaendig in main). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
14 KiB
Design 2.0 — Briefing (Übergabe an Gemini)
✅ ERLEDIGT (24.07.2026). Design 2.0 wurde umgesetzt und ist in
main. Der Arbeitsbranchdesign-2.0wurde nach dem Merge gelöscht (es gibt nur nochmain). Dieses Dokument bleibt als historische Auftragsbeschreibung.Dieses Dokument ist die vollständige Auftragsbeschreibung für den UI-Umbau „Design 2.0". Es ist so geschrieben, dass ein zweites KI-Modell (Gemini) eigenständig loslegen kann. Stand: 24.07.2026, vorbereitet von Claude.
0. Auftrag in einem Satz
Das Rippy-Web-UI von 428 handgeschriebenen theme === 'dark' ? … : …-
Ternaries auf ein sauberes, token-basiertes Tailwind-dark:-System
umstellen und dabei die Optik auf ein modernes, konsistentes „Design 2.0"
heben — ohne Funktion, API-Aufrufe, deutsche Texte oder die
Deploy-Kette anzufassen.
1. Was Rippy ist (Kontext in 30 Sekunden)
Rippy ist eine self-hosted Disc-Ripping-Maschine (CD/DVD/Blu-ray/4K-UHD): Disc rein → automatisch erkannt → verlustfrei gerippt (MakeMKV) → komprimiert (HandBrake) → Media-Server-fertig abgelegt. Alles Docker, alles im Heimnetz. Das UI ist die einzige Bedienoberfläche.
Tech-Stack UI (docker/ui/):
- React 18 + TypeScript + Vite
- TailwindCSS (
darkMode: 'class') - lucide-react (Icons)
- Kein Router (Seitenwechsel über
useStateinApp.tsx) - State: lokale Hooks + Polling gegen die REST-API (
src/lib/api.ts, axios,baseURL: '/api')
Sprach-Konvention (AGENTS.md Regel 4): Variablen-/Funktionsnamen auf Englisch, alle Kommentare, UI-Texte und Docs auf Deutsch. Der Betreiber („Commander") ist Nicht-Entwickler und liest alles.
2. Der Kern des Problems
Jede Komponente entscheidet Farben zur Laufzeit per Ternary:
// SO sieht es HEUTE ~428× aus:
<div className={`rounded-xl border ${theme === 'dark'
? 'bg-slate-800 border-slate-700'
: 'bg-white border-slate-200'}`}>
Das ist der größte technische Schuldenberg des UI:
- 428 Ternaries in 18 Dateien (Inventar unten) — jede Farbe doppelt gepflegt, Copy-Paste-Fehler vorprogrammiert.
- Jede Komponente zieht dafür
const { theme } = useDarkMode()— Rendering hängt an einem Context-Wert, den es fast nie bräuchte. - Wiederkehrende Farb-Mappings sind mehrfach dupliziert statt zentral:
StatusBadge(Dashboard),getLevelColor(Logs),getTypeColor(DeviceDiscovery) definieren jeweils eigene Status→Farbe-Tabellen.
Warum das JETZT ein leichter Umbau ist
Die Infrastruktur für den sauberen Weg steht bereits vollständig:
tailwind.config.js:darkMode: 'class'✅ThemeContext.tsxsetzt beim Umschaltendocument.documentElement. classList.add('dark')— also.darkauf<html>✅- Damit funktionieren Tailwinds
dark:-Varianten sofort überall.
Konkret heißt Migration also fast immer nur:
// NACHHER — kein Ternary, kein useDarkMode nötig:
<div className="rounded-xl border bg-white border-slate-200
dark:bg-slate-800 dark:border-slate-700">
Drei Altlasten, die mit aufgeräumt werden sollten
- Tote CSS-Variablen (
src/index.css): Es gibt:root { --bg-color … }und[data-theme="dark"] { … }. Der Dark-Block ist toter Code — nichts setzt jemalsdata-theme(der Theme-Umschalter nutzt die.dark-Klasse). Entweder die Variablen korrekt an.darkbinden ODER (empfohlen) ganz auf Tailwind-dark:setzen und die Variablen entfernen. - Globale Transition (
src/index.css):* { transition: background-color .3s, color .3s, border-color .3s; }lässt bei jedem Theme-Wechsel die GESAMTE Seite animieren (Jank-Risiko) und macht die überall verstreutentransition-colors duration-300-Klassen doppelt. Auf einen bewussten, schmalen Transition-Ansatz reduzieren. - Icon-Inkonsistenz: Fast alles nutzt
lucide-react, aberConfirmDialog.tsxnutzt Emoji (⚠️✅🤔) als „Icons". Vereinheitlichen.
3. Empfohlener Weg (technisch)
Nicht blind 428 Ternaries per Hand ersetzen — das ist fehleranfällig. Stattdessen in zwei Schichten:
Schicht A — Wiederverwendbare Primitives (src/components/ui/)
Ein kleines Set typisierter Bausteine, die das Design kapseln. Heute wird jedes davon in jeder Datei neu zusammengeklöppelt:
Card/CardHeader— dierounded-xl border bg-white dark:bg-slate-800- Kachel (kommt ~30× vor)Button(Varianten: primary / secondary / ghost / danger)Badge(Status/Typ-Pill mit zentraler Farbtabelle — löst die 3 Duplikate)Input/Select/Toggle(Formularfelder, heute inline-dupliziert)Modal(derfixed inset-0 … backdrop-blur-Rahmen — 4× dupliziert: RipTargetModal, JobDetailModal, MetadataKorrektur, ConfirmDialog)Section/PageHeader(Seiten-Titel + Untertitel, überall gleich)
Farbwelt/Status einmal zentral definieren (z. B.
src/lib/design.ts), damit Status→Farbe nur an EINER Stelle lebt:
export const STATUS_STYLES = {
pending: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',
processing: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',
transcoding: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400',
completed: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400',
failed: 'bg-rose-100 text-rose-700 dark:bg-rose-900/30 dark:text-rose-400',
// Disc-Typen: cd=blue, dvd=purple, bluray=pink, uhd=amber
} as const
Schicht B — Seiten/Komponenten auf die Primitives umstellen
Datei für Datei die Ternaries durch dark:-Klassen bzw. die neuen
Primitives ersetzen. const { theme } = useDarkMode() fällt dabei in
fast allen Dateien weg (nur App.tsx braucht toggleTheme noch).
Optional als echtes „2.0": Tailwind-Theme-Tokens
Statt roher slate-*/indigo-*-Klassen semantische Tokens in
tailwind.config.js (theme.extend.colors) definieren
(surface, surface-muted, border-subtle, accent, text-primary,
text-muted …) und diese nutzen. Das macht spätere Farb-Anpassungen zu
einer Ein-Zeilen-Änderung. Kür, kein Muss — die dark:-Umstellung
ist der Pflichtteil.
4. Design-Richtung (Leitplanken, nicht Korsett)
Die bestehende Farbwelt ist bereits kohärent — bitte systematisieren und verfeinern, nicht wild neu erfinden. Referenz aus dem Ist-Zustand:
- Akzent/Primär: Indigo (
indigo-600), Verlaufindigo-500 → purple-600(Logo, Buttons, aktive Nav) - Flächen: hell
slate-50(Seite) /white(Karten); dunkelslate-950/slate-900(Seite) /slate-800(Karten) - Ränder:
slate-200hell /slate-700dunkel - Status: amber=wartend/Warnung, blue=Bearbeitung/Info, purple=Komprimieren, emerald=fertig/Erfolg, rose=Fehler; Disc-Typen: cd=blue, dvd=purple, bluray=pink, uhd=amber (bewusst abgesetzt)
- Typo: system-sans (siehe
index.css), Überschriftenfont-bold
Spielraum für 2.0 (gern, solange konsistent + zugänglich):
Abstände/Rhythmus vereinheitlichen, Karten-Schatten/Radien harmonisieren,
Empty-States aufwerten, Fokus-/Hover-Zustände konsistent, bessere
Dichte in den Tabellen, der neue Anleitung-Tab (pages/Anleitung.tsx)
darf visuell aufgewertet werden. Barrierefreiheit im Blick behalten
(Kontrast, Fokus-Ringe, aria-* wo sinnvoll).
Es gibt eine Skill/Guideline „Web Interface Guidelines" — an modernen
Best-Practices orientieren.
5. HARTE Regeln (nicht verhandelbar)
- Nur UI, nur
docker/ui/src/(+ ggf.tailwind.config.js,index.css,index.html). Kein Backend (docker/api,docker/worker), keine API-Verträge, keinedocker-compose.yml. - Funktion bleibt 1:1. Alle bestehenden Features, Flows, API-Calls, Polling-Intervalle, Feldnamen im POST-Body bleiben exakt erhalten. Das ist ein Re-Skin + Refactor, kein Feature-Umbau. Im Zweifel: Verhalten unverändert lassen.
- Deutsch bleibt Deutsch. Kein UI-Text wird übersetzt oder umformuliert (außer offensichtliche Tippfehler). Kommentare Deutsch.
- Die CI-Ampel MUSS grün bleiben (
.gitea/workflows/ci.yml): bei jedem Push laufen Ruff, pytest UNDnpm run build(Vite). Ein TypeScript-/Build-Fehler = rot = nicht fertig. Nach JEDER umgestellten Komponente lokalnpm run buildgrün halten. package-lock.jsoncommitten, falls neue Abhängigkeiten dazukommen (die Ampel prüft Reproduzierbarkeit). Neue Runtime-Deps sparsam — das Ziel ist weniger Code, nicht mehr.- AGENTS.md gelesen halten (Repo-Wurzel) — die dortigen Regeln gelten.
6. Datei-Inventar (Fahrplan, Stand 24.07.2026)
Sortiert nach Aufwand. Zahlen = theme === 'dark'-Ternaries in der Datei.
| Datei | Zeilen | Ternaries | Hinweis |
|---|---|---|---|
pages/Settings.tsx |
860 | 128 | Größter Brocken; viele Tabs — evtl. in Unterkomponenten pro Tab zerlegen |
pages/Dashboard.tsx |
504 | 44 | Enthält StatusBadge/TypeBadge/ProgressBar/StatCard → in Primitives heben |
components/DeviceDiscovery.tsx |
381 | 43 | Disc-Karte + Laufwerks-Liste; getTypeColor/getStatusColor zentralisieren |
components/RipTargetModal.tsx |
401 | 37 | Modal + Track-Tabelle + Serien-Felder |
pages/Logs.tsx |
246 | 34 | getLevelColor/getLevelIcon/getLevelLabel → zentral |
components/StorageMounts.tsx |
361 | 33 | Mounts + Ordner-Browser |
components/JobDetailModal.tsx |
239 | 28 | Modal, Download-Liste |
components/FirstRunWizard.tsx |
192 | 22 | Onboarding |
components/WorkerVerwaltung.tsx |
214 | 18 | Worker-Liste + Anbinde-Befehle |
components/LiveLogSection.tsx |
147 | 15 | Live-Log-Kachel |
components/MetadataKorrektur.tsx |
145 | 10 | Korrektur-Popup |
pages/Anleitung.tsx |
180 | 7 | Neu; darf visuell aufgewertet werden |
components/ConfirmDialog.tsx |
83 | 6 | Emoji-Icons → lucide |
App.tsx |
101 | 2 | Sidebar/Nav/Footer; behält toggleTheme |
context/ThemeContext.tsx |
52 | 1 | Bleibt im Kern; ggf. data-theme synchron setzen, falls CSS-Variablen genutzt werden |
context/ToastContext.tsx |
62 | 0 | Nutzt schon dark: teils — als Vorbild ansehen |
Gesamt: 428 Ternaries. Bereits dark:-Klassen im Code: nur 7 —
d. h. ToastContext und Reste zeigen das Zielbild.
Empfohlene Reihenfolge: erst Schicht A (Primitives + design.ts),
dann die kleinen Dateien (ConfirmDialog, App, LiveLogSection) als
Kalibrierung, dann die großen. Settings.tsx zuletzt (größter Nutzen aus
den dann fertigen Primitives).
7. Arbeitsweise & Branch
- Auf einem eigenen Branch arbeiten (war:
design-2.0). Ein Feature-Branch lässt die Ampel laufen (Feedback grün/rot), deployt aber nicht — ideal für einen großen Umbau; nach Abnahme nachmaingemerged. (Hinweis: Seit 24.07.2026 istmainder einzige Branch — deployt wird direkt daraus, die Ampel prüft nur noch.) - Klein committen, eine sinnvolle Einheit pro Commit (z. B. „Primitives: Card + Button", dann „Dashboard auf Primitives umgestellt"). Commit-Text Deutsch, WAS + WARUM.
- Nach jeder Komponente:
npm run buildmuss grün sein. Nie einen roten Zwischenstand pushen. - Visuell gegenprüfen: hell UND dunkel testen (Theme-Umschalter oben in der Sidebar).
8. Verifikation (die exakten Befehle)
cd docker/ui
npm ci # einmalig
npm run build # MUSS grün sein — das prüft auch die Ampel
Lokal ansehen (Dev-Server):
cd docker/ui && npm run dev
Das UI erwartet die API unter /api (nginx-Proxy). Für reine Design-
Arbeit reicht der Dev-Server; leere Listen/Fehlerzustände sind normal ohne
laufendes Backend. Wer gegen echte Daten testen will: Das Live-System läuft
im Heimnetz (Zugang beim Commander erfragen).
Die komplette Ampel (wie in CI) prüft zusätzlich Backend-Tests — die sind von reiner UI-Arbeit nicht betroffen, müssen aber grün bleiben (nicht anfassen).
9. Definition of Done
src/components/ui/-Primitives existieren und werden genutzt- Status/Typ/Level-Farben zentral (
src/lib/design.ts), keine duplizierten Farb-Mappings mehr grep -rn "theme === 'dark'" src/ergibt ~0 Treffer (idealerweise nur noch inThemeContext/Appdas Nötigste)- Tote CSS-Variablen (
[data-theme="dark"]) und globale* { transition }bereinigt ConfirmDialognutzt lucide statt Emoji- Hell- UND Dunkelmodus überall konsistent, keine „weiße Karte im Darkmode"-Ausrutscher
npm run buildgrün; keine neuen TS-Fehler/Warnungen- Keine funktionale Änderung (alle API-Calls/Flows identisch)
- Alle deutschen Texte unverändert
- Auf Branch
design-2.0, sauber committet, bereit für Review/Merge
10. Copy-Paste-Startprompt für Gemini
Du übernimmst „Design 2.0" für das Rippy-Web-UI (React + TypeScript + Vite + TailwindCSS,
darkMode: 'class'). Lies zuerstdocs/DESIGN-2.0-BRIEFING.mdKOMPLETT — dort stehen Auftrag, harte Regeln, Datei-Inventar, empfohlener Weg und die Definition of Done. Arbeite ausschließlich indocker/ui/, auf dem Branchdesign-2.0. Kernauftrag: 428theme === 'dark' ? …-Ternaries durch Tailwind-dark:- Klassen + wiederverwendbare UI-Primitives ersetzen und die Optik modernisieren — OHNE Funktion, API-Aufrufe oder deutsche Texte zu ändern. Halte nach jeder umgestellten Komponentenpm run buildgrün. Beginne mit den UI-Primitives (src/components/ui/) undsrc/lib/design.ts, dann die kleinen Dateien, dann die großen (Settings.tsxzuletzt). Kommentare und Commit-Texte auf Deutsch.