Zum Inhalt springen
OmniRoute source

OmniRoute — Design System & Visual Identity (Deutsch)

Die Marketing-Website (viral.omniroute.online, why.omniroute.online, omniroute.online) und das Produkt-Dashboard sollen wie ein Produkt aussehen. Die Website hat ihre Farbpalette bereits vom Dashboard übernommen — in ihrer Datei css/tokens.css steht sogar „Die Palette entspricht dem OmniRoute-Dashboard (src/app/globals.css)“. Daher stimmen beide auf Farbebene bereits zu etwa 80 % überein. Was dem Dashboard noch fehlt:

  1. Der Millimeterpapier-Rasterhintergrund, den die Website auf jeder Seite verwendet.
  2. Einige gemeinsame Design-Tokens, die auf der Website vorhanden sind, dem Dashboard jedoch fehlen (Radius-Skala, Markenverlauf, surface-2, Monospace-Schriftart).
  3. Konsistenz auf Komponentenebene — eine Reihe von Dashboard-Komponenten umgeht die Theme-Tokens durch hartcodierte Hex-/rgba-Werte.

Dieses Dokument enthält die Analyse und den Plan.


  • Single Source of Truth = src/app/globals.css. Die Website spiegelt das Dashboard wider, niemals umgekehrt. Neue Tokens werden zuerst in globals.css aufgenommen.
  • Tokens statt Literalen. Komponenten verwenden semantische Tokens (bg-surface, text-primary, border-border), niemals rohe #hex-Werte.
  • Dezent statt aufdringlich. Das Raster ist ein unauffälliger Hintergrund hinter den Inhalten — es darf niemals den Textkontrast verringern oder mit der Benutzeroberfläche konkurrieren.
  • Theme-fähig. Alles funktioniert sowohl in .dark (dem charakteristischen Erscheinungsbild des Produkts) als auch im hellen Theme.
  • Gezielte Einführung. Zuerst Raster und Tokens ausliefern (geringes Risiko, hohe Sichtbarkeit), anschließend die Komponenten schrittweise bereinigen.

3. Aktueller Stand — was bereits übereinstimmt und was nicht

Abschnitt betitelt „3. Aktueller Stand — was bereits übereinstimmt und was nicht“

Jede Marken- und Oberflächenfarbe stimmt bereits wertmäßig mit der Website überein (lediglich die Namen unterscheiden sich — das Dashboard verwendet das Präfix --color-). Verifiziert in src/app/globals.css:30-128:

Konzept Website-Token (tokens.css) Dashboard-Token (globals.css) Übereinstimmung
Primärfarbe --primary #e54d5e --color-primary #e54d5e ✅
Primärfarbe bei Hover --primary-hover #c93d4e --color-primary-hover #c93d4e ✅
Akzent --accent #6366f1 --color-accent #6366f1 ✅
Akzent 2 --accent-2 #8b5cf6 --color-accent-hover #8b5cf6 ✅ (umbenannt)
Akzent 3 --accent-3 #a855f7 --color-accent-light #a855f7 ✅ (umbenannt)
Erfolg / Warnung / Fehler #22c55e / #f59e0b / #ef4444 identisch ✅
Ampelfarben #ff5f56 / #ffbd2e / #27c93f identisch ✅
Dunkler Hintergrund / Oberfläche / Rahmen #0b0e14 / #161b22 / rgba(255,255,255,.08) identisch ✅
Heller Hintergrund / Oberfläche / Text #f9f9fb / #fff / #1a1a2e identisch ✅

Fazit: Es ist keine Farbmigration erforderlich. Die visuelle Identität wird bereits geteilt; wir vervollständigen sie, statt sie neu aufzubauen.

Lücke Website verfügt über Dashboard Maßnahme
Raster-Hintergrund body::before-Millimeterpapier, --grid-line, --grid-size 32px, --section-alt ✅ hinzugefügt (Phase 1) Teil A
Radius-Skala --radius 14px, --radius-sm 9px --radius 14px hinzugefügt; -sm + Komponentenumstellung ausstehend Teil B / Phase 2
Markenverlauf --grad-brand 135deg primary→accent-3 ✅ Token hinzugefügt (Phase 1); Verwendung in Phase 2 Teil B
Verschachtelte Oberfläche --surface-2 #1c2230 ✅ hinzugefügt (Phase 1) Teil B
Monospace-Schriftart --font-mono (ui-monospace-Stack) ausstehend (Phase 4, zusammen mit den Verbrauchern) Teil B
text-muted (dunkel) #8b8b9e #a1a1aa (zinc-400) abgleichen — Teil B

3.3 Theming-Mechanismen (damit nichts beschädigt wird)

Abschnitt betitelt „3.3 Theming-Mechanismen (damit nichts beschädigt wird)“
  • Tailwind v4, CSS-first (keine tailwind.config.*). Tokens werden in :root/.dark definiert und über @theme inline für Utilities verfügbar gemacht (globals.css:130-179).
  • Dunkelmodus über die Klasse .dark auf <html> (@custom-variant dark in globals.css:22), umgeschaltet durch einen benutzerdefinierten Zustand-Store (src/store/themeStore.ts), Standard-Theme = system (src/shared/constants/appConfig.ts:11). Die Website verwendet stattdessen html[data-theme="light"] — die Mechanismen unterscheiden sich, treffen aber nie aufeinander (separate Origins), daher besteht kein Konflikt. Wir behalten den .dark-Mechanismus des Dashboards bei.
  • Eine Laufzeitüberschreibung für die Primärfarbe ist vorhanden (themeStore.ts:85-97, Voreinstellungen in COLOR_THEMES) — Benutzer können --color-primary austauschen. Jedes neue Token (Verlauf usw.), das auf --color-primary verweist, übernimmt diese Überschreibungen automatisch. ✅
  • Reservierte Radiusnamen in Tailwind v4: --radius-sm/md/lg/... bilden die Grundlage der rounded-*-Utilities. Eine Neudefinition verändert rückwirkend jedes vorhandene rounded-* (z. B. wird rounded-sm in 12 Dateien verwendet). Daher werden der Wert für den kleinen Radius und die Umstellung der Komponenten bewusst auf Phase 2 verschoben, in der die Verbraucher gemeinsam geändert werden.

4. Teil A — Der Millimeterpapier-Rasterhintergrund (Hauptanforderung) — IMPLEMENTIERT (Phase 1)

Abschnitt betitelt „4. Teil A — Der Millimeterpapier-Rasterhintergrund (Hauptanforderung) — IMPLEMENTIERT (Phase 1)“

Das exakte Rezept von der Website (_mono_repo/omnirouteSite/css/base.css): ein fixiertes, den gesamten Viewport ausfüllendes Pseudoelement, das zwei 1px-Linienverläufe zeichnet und mit z-index:-1 hinter allen Inhalten liegt.

body::before {
content: "";
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
background-size: var(--grid-size) var(--grid-size);
}

Warum dies funktioniert, obwohl body eine deckende background-color hat: Ein ::before mit z-index:-1 wird über dem eigenen Hintergrund des Elements, aber unter dessen Inhalt im normalen Dokumentfluss gezeichnet. Somit ist --color-bg die Grundfüllung, das Raster wird darübergelegt und die App wird oberhalb des Rasters dargestellt.

src/app/landing/page.tsx:16-26 implementiert dieses Raster bereits seitenbezogen — allerdings mit roten Linien (#E54D5E, Deckkraft 0.06) im Abstand von 50px sowie animierten Lichtkugeln. Das Muster hat sich im Produkt somit bewährt; durch diese Arbeit wird es zu einem globalen, Theme-fähigen Hintergrundbild.

:root {
/* hell — Rasterdeckkraft gegenüber den 0.045 der Website erhöht, damit das Hintergrundbild
auf dem dicht gefüllten Dashboard tatsächlich sichtbar ist (Karten/Chrome verdecken den Großteil des Viewports) */
--grid-line: rgba(0, 0, 0, 0.07);
--grid-size: 32px;
--section-alt: rgba(0, 0, 0, 0.022);
}
.dark {
/* dunkel — aus demselben Grund gegenüber 0.035 erhöht */
--grid-line: rgba(255, 255, 255, 0.06);
--section-alt: rgba(255, 255, 255, 0.018);
}

Das Raster ist konstruktionsbedingt global (es deckt das Panel, auth/login, Fehlerseiten — alle Routen — gleichzeitig ab). Genau ein Element verdeckte es innerhalb des Panels:

  • src/shared/components/layouts/DashboardLayout.tsx — der äußere Wrapper zeichnete ein deckendes bg-bg. Alles darunter ist bereits transparent (<main>, der Scroll-Container und das innere max-w-7xl), sodass durch das Entfernen von bg-bg das Body-Raster im Inhaltsbereich sichtbar wird (das --color-bg des Bodys bleibt die Grundfüllung).

    <div className="flex h-dvh min-h-0 w-full overflow-hidden bg-bg">
    <div className="flex h-dvh min-h-0 w-full overflow-hidden">

4.5 Zusammenspiel mit dem Chrome (Seitenleiste / Header)

Abschnitt betitelt „4.5 Zusammenspiel mit dem Chrome (Seitenleiste / Header)“
  • Header (Header.tsx:207, bg-bg) und Sidebar (Sidebar.tsx:430, bg-sidebar) bleiben deckend → das Raster erscheint nur im Inhaltsbereich, eingerahmt von einem einfarbigen Chrome. Eine ruhige Standardeinstellung, die der Trennung von Chrome und Arbeitsfläche auf der Website entspricht (Entscheidung D3 = einfarbig).

Diese werden direkt unter &lt;body&gt; gerendert (ohne Panel-Chrome), daher sollte das globale Raster automatisch hinter ihnen erscheinen. Phase 5 — ABGESCHLOSSEN: Die eigenständigen Vollbild-Wrapper waren tatsächlich deckend (min-h-screen … bg-bg, wobei bg-bg dieselbe einfarbige Füllung wie &lt;body&gt; ist), wodurch das Raster auf allen Bildschirmen außerhalb des Dashboards verdeckt wurde — nicht nur bei der Anmeldung. Sie sind jetzt alle transparent, sodass das gemeinsame Hintergrundbild durchscheint: login, forgot-password, callback, maintenance, offline, status, terms, privacy, onboarding und ErrorPageScaffold (deckt 400/401 ab). Damit ist D4 abgeschlossen (von nur der Anmeldung auf alle eigenständigen Bildschirme erweitert). Abgesichert durch tests/unit/design-grid-background.test.ts.

landing/page.tsx behält seinen aufwendigeren animierten Hintergrund (Lichtkugeln + Vignette) — seinen eigenen Marketing-Aufmacher (Entscheidung D5 = unverändert belassen).


Phase 1 fügt die inerten, kollisionsfreien Identitäts-Token (--surface-2/--color-surface-2, --grad-brand, --radius) hinzu. Phase 2 bindet die Radius-Skala in Tailwind ein und stellt die Komponenten darauf um; Phase 4 ergänzt --font-mono sowie dessen Nutzer.

Token Warum Phase
--radius / --radius-sm Eine Radius-Skala (14/9) statt uneinheitlicher 6/8/12-Werte 1 (Wert) / 2 (Einbindung + Umstellung)
--grad-brand Markenverlauf für primäre CTAs (Rot→Violett), passend zur Website 1 (Token) / 2 (Button)
--surface-2 Verschachtelte Panels / Tabellenüberschriften / eingerückte Zeilen 1
--font-mono Codeblöcke, Terminal, IDs, Endpunkte 4
--text-muted abgleichen Einen Wert für Website↔Panel wählen (#a1a1aa empfohlen) 2

D2 (text-muted): Website #8b8b9e vs. Dashboard #a1a1aa. Es wird empfohlen, #a1a1aa des Dashboards beizubehalten und die Website entsprechend zu aktualisieren. Kosmetische Änderung.


6. Teil C — Komponentenstandardisierung (Phasen 2–4)

Abschnitt betitelt „6. Teil C — Komponentenstandardisierung (Phasen 2–4)“

Benutzerdefinierte Komponenten (kein shadcn/Radix), Tailwind v4, semantische Token größtenteils übernommen (195 Dateien importieren das gemeinsame Barrel). Die Aufgabe besteht darin, die Umgehungen zu entfernen. Basisverzeichnis: src/shared/components/.

# Element Datei(en) Problem → Ziel Phase
C1 Radius-Ausrichtung Button.tsx:14-18, Card.tsx:39, Modal.tsx, Input.tsx, Select.tsx gemischte 6/8/12px → --radius/--radius-sm (14/9) 2
C2 Button-Verlauf + Variante accent Button.tsx:5-12 Primärvariante ist einfarbig Rot→Rot; an --grad-brand angleichen; fehlende Variante accent ergänzen. ~195 Importeure — höchste Sichtbarkeit 2
C3 Tabellen DataTable.tsx:122-176, logTableStyles.ts, globals.css:405-414 100 % fest codierte Inline-rgba-Werte + nicht vorhandene Variablen; zu Token migrieren, abweichende Stile entfernen 3
C4 Statusfarben zentralisieren flow/edgeStyles.ts, TokenHealthBadge.tsx, DegradationBadge.tsx, ProviderCascadeNode.tsx, Badge.tsx + 5 Hilfsdateien 6+ Kopien derselben Hex-Werte → ein Modul auf Basis von --color-success/warning/error 3
C5 Kartenrahmen Card.tsx:39 border-white/5 → Marke /8 2
C6 Fokusring abgleichen ✅ ERLEDIGT globals.css --focus-ring (Akzent) vs. ring-primary/30 der Formularsteuerelemente auf Akzent (Violett) vereinheitlicht, passend zum globalen Ring und zur Abgrenzung vom roten Fehlerring; Fehler bleibt rot 4
C7 Checkbox + Textarea ergänzen rohe &lt;input&gt;-/&lt;textarea&gt;-Elemente mit inline gesetztem accentColor:#6366f1 Token-gesteuerte Primitive 4
C8 Suche nach fest codierten Hex-Werten ConsoleLogViewer.tsx:240, ComboLiveStudio.tsx:306, Modal-Punkte, ~14 Diagrammdateien Literale → Token 4
C9 cn() → clsx + tailwind-merge src/shared/utils/cn.ts widersprüchliche Klassen werden gestapelt; für C1-Überschreibungen erforderlich 2

Bereits markenkonform (Token-gesteuert, benötigen nur eine Radius-Anpassung): Badge, Toggle, SegmentedControl, Input, Select.


  • Phase 1 — Raster + Identitäts-Tokens (DIESER PR). globals.css-Raster + --surface-2-/--grad-brand-/--radius-Tokens; body::before-Hintergrund; den bg-bg-Blocker entfernen; statischer Guard-Test. Geringes Risiko, mit einem Commit rückgängig zu machen.
  • Phase 2 — Primitive (C1, C2, C5) — IN DIESEM PR ERLEDIGT. Semantische Radius-Utilities rounded-card (14px) / rounded-control (9px) über @theme hinzugefügt (benutzerdefinierte Namen, daher bleiben die standardmäßigen rounded-sm/md/lg/xl unverändert — keine Auswirkungen auf 400 Dateien); Card/Modal → 14px, Button/Input/Select → 9px; primärer Button → --grad-brand (Rot→Violett) + neue accent-Variante; Card-Rahmen → das border-border-Token (0.08). Zurückgestellt: cn()→tailwind-merge (C9) benötigt neue Abhängigkeiten; die Bereinigung der ad hoc verwendeten rounded-lg-Klassen (326 Dateien) bleibt unverändert, da die Primitive den Großteil der Oberflächen abdecken.
  • Phase 3 — Statusfarben + Tabellen (C3, C4) — IN DIESEM PR ERLEDIGT. ✅ C4 (src/shared/constants/statusColors.ts — STATUS_HEX als Single Source of Truth; flow/edgeStyles.ts + TokenHealthBadge darauf umgestellt, originalgetreu/gleiche Hex-Werte). ✅ --font-mono-Token. ✅ C3 (DataTable) — sämtliche Inline-rgba-Werte sowie die wirkungslosen var(--bg-table-header)- / var(--text-secondary)-Fallbacks durch einen --table-*-Token-Satz (--table-header-bg/-row-zebra/-row-hover/-cell-border/-row-selected) ersetzt, dessen Dark-Werte exakt den alten hartcodierten rgba-Werten entsprechen (im Dark-Modus Byte für Byte identisch) und dessen Light-Werte das zuvor immer dunkle Light-Theme korrigieren. Header-Rahmen → --color-border, sekundärer Text → --color-text-muted. Vor dem Merge ist eine visuelle Prüfung erwünscht. (Nicht geändert: logTableStyles.ts und die alten Ant-Regeln für .ant-table — separat, niedrigere Priorität.)
  • Phase 4 — Bereinigung (C6, C7, C9 erledigt; C8 ausstehend). ✅ C9 cn() → twMerge(clsx(...)) (clsx + tailwind-merge als Abhängigkeiten hinzugefügt) — das className eines Aufrufers ersetzt jetzt korrekt eine kollidierende Klasse eines Primitivs, statt beide zu stapeln. ✅ C7 neue Checkbox- + Textarea-Primitive (Token-gesteuert, aus der Barrel-Datei exportiert; additive Änderung — die Übernahme der 32 rohen Checkboxen / 41 rohen Textareas kann schrittweise erfolgen). ✅ C6 Fokus-Ring-Abgleich — die Formular-Steuerelemente (Input/Select/Textarea/Toggle/Checkbox) verwenden beim Fokus jetzt den Accent-Ring (Violett), passend zum globalen --focus-ring und ohne Kollision mit dem roten Fehler-Ring; der rote Fehlerzustand bleibt unverändert. ⏳ Der C8-Hex-Sweep ist KEIN blindes Suchen/Ersetzen — bestätigte Fundstellen, die beabsichtigt sind und erhalten bleiben müssen: ConsoleLogViewer.tsx:240 (stets dunkles Terminal), TokenHealthBadge-Popover, ReactFlow-SVG-Konturen. Nur Hex-Werte migrieren, die tatsächlich Theme-abhängig sein sollen.

Jede Phase: npm run lint + npm run typecheck:core + eine visuelle Prüfung.


  • D1 — Primärer Button: Rot→Rot beibehalten oder zu Rot→Violett --grad-brand wechseln? Empfehlung: Rot→Violett (Phase 2).
  • D2 — Farbe der Rasterlinien: neutral (Website-Stil) — gewählt — statt Markenrot. Größe 32px (nach Feedback des Owners gegenüber den ursprünglichen 46px um ca. 30 % verkleinert — 46px große Zellen wirkten im Dashboard-Layout zu groß).
  • D3 — Lebendigkeit des Chromes: Seitenleiste/Header deckend — gewählt.
  • D4 — Auth-/Login-Raster: ✅ ERLEDIGT (Phase 5) — das deckende bg-bg wurde aus jedem eigenständigen Vollbild-Wrapper entfernt (nicht nur aus dem Login), sodass das Raster auf allen Bildschirmen sichtbar ist. Siehe §4.6.
  • D5 — Landingpage: Animierten Splash unverändert lassen. Gewählt.
  • D6 — Radius 14/9 im gesamten Produkt: Empfehlung: ja (Phase 2).
  • D7 — Phase 1 wird zuerst ausgeliefert: Gewählt.
  • D8 — Layout-Breite (Phase 5): Der Inhalts-Container des Dashboards war auf max-w-7xl (1280px) begrenzt, wodurch auf großen Monitoren eine Zentrierung mit breiten leeren Seitenrändern entstand. ✅ ERLEDIGT — auf ein fluides max-w-[3840px] (echtes 4K) erhöht: Der Inhalt folgt jetzt bis etwa 4K dem Viewport und wird erst darüber hinaus zentriert (DashboardLayout.tsx). Bewusst schmale Seiten bleiben absichtlich schmal (ProviderOnboardingWizard max-w-5xl, Rtk/CavemanContextPageClient max-w-6xl).
  • D9 — Deckende Datentabellen (Phase 6): Da der Inhaltsbereich des Dashboards nun transparent ist (damit der Raster-Hintergrund durchscheint, Phase 5), ließen Datentabellen, deren Container keine deckende Oberfläche darstellten, das Raster durch ihre transparenten geraden Zeilen / Zebra-Zeilen mit geringer Alpha-Deckkraft durchscheinen. ✅ ERLEDIGT — jede Tabelle ohne Card zeichnet nun bg-surface (oder, beim <DataTable>-Primitiv, background: var(--color-surface) auf ihrem Scroll-Container). Korrigiert: DataTable (Primitiv), ProxyLogger/RequestLoggerV2 (deren <Card>-Tönung bg-black/5 dark:bg-black/20 setzte sich über tailwind-merge gegen das bg-surface der Card durch → ca. 95 % transparent), BatchListTab/FilesListTab/CacheEntriesTab/ReasoningCacheTab/cache page/FreePoolTab/ModelMappingTable/HeaderTable sowie die beiden CSS-Grid-„Tabellen“ in den Cache-Ansichten (bg-surface/35 → bg-surface). Tabellen, die sich bereits innerhalb einer <Card>/eines Modals befinden, wurden als deckend verifiziert und bewusst unverändert belassen (bg-surface wäre dort ein redundanter No-op). Das Raster selbst musste nicht geändert werden — body::before des Dashboards ist Byte für Byte identisch mit dem der Website (--grid-size: 32px); jedes „größere Raster“, das auf einer laufenden Instanz zu sehen ist, stammt aus einem veralteten Build vor #4143, nicht aus dem Code. Abgesichert durch tests/unit/design-grid-background.test.ts (Phase-6-Block).

  • Keine Änderung der Farbpalette — die Farben stimmen bereits überein; wir ergänzen lediglich fehlende Tokens. Kein Risiko, das Produkt farblich zu verändern.
  • Keine Änderung der Theme-Engine — .dark + Zustand-Store beibehalten.
  • Die Änderung der Radien (Phase 2) ist umfassend — sie betrifft sämtliche Karten, Buttons und Eingabefelder; stark ausgelastete Ansichten (Tabellen, Modals) vor dem Merge visuell prüfen.
  • Tabellen (C3) weisen die meisten hartcodierten Stile und die größte potenzielle Regressionsfläche auf — in einem eigenen PR isolieren.

Bereich Pfad
Dashboard-Tokens src/app/globals.css (:root, .dark, @theme inline, body, body::before)
Theme-Store src/store/themeStore.ts, src/shared/components/ThemeProvider.tsx, src/shared/constants/appConfig.ts:9-11
Panel-Shell (Grid hier entsperrt) src/shared/components/layouts/DashboardLayout.tsx
Chrome src/shared/components/Header.tsx:207, src/shared/components/Sidebar.tsx:430
Grid-Vorlage src/app/landing/page.tsx:16-26
Primitive src/shared/components/{Button,Card,Input,Select,Badge,Modal,Toggle,SegmentedControl,Loading,Tooltip,DataTable}.tsx
Quellen für Statusfarben flow/edgeStyles.ts, TokenHealthBadge.tsx, DegradationBadge.tsx, logTableStyles.ts
cn-Hilfsfunktion src/shared/utils/cn.ts
Schutztest für Phase 1 tests/unit/design-grid-background.test.ts
Website-Referenz _mono_repo/omnirouteSite/css/tokens.css, css/base.css

OmniRoute-Quellcode (a58000c7685f)

HagiCode

HagiCode ist ein agentischer Coding-Arbeitsplatz mit strukturierten Workflows, Multi-Agent-Ausführung und Hero-Dungeon-Ansichten.

Mit einem intelligenteren, schnelleren und unterhaltsameren agentischen Workflow wird aus Ideen nutzbare Software.

HagiCode-Hauptoberfläche im hellen Design
  • SmartStrukturierte Workflows machen aus Absichten einen umsetzbaren Weg von der Idee bis zur Auslieferung.
  • EfficientMulti-Agent-Workflows führen Recherche, Umsetzung und Prüfung parallel aus.
  • FunHero Dungeon macht lange Coding-Sitzungen anschaulich und gemeinschaftlich.
HagiCode besuchen