ThemeForge: Ein einfach zu installierendes CSS-Theme-System – von einem KI-Agenten in nur einem Schritt eingerichtet.

Veröffentlicht
5 Oktober 2026
Aktualisiert
6 Oktober 2026
Von
Jacob Lloyd — mit KI-Unterstützung geschrieben, im Nachhinein
Lesezeit
31 Min. Lesezeit

Kurz gesagt: ThemeForge ist ein kostenloses Paket aus CSS-Dateien sowie einem kleinen Skript. Es ermöglicht es jeder Web-Anwendung, einen Themenauswähler zu nutzen – außerdem stehen zehn Farbthemen sowie eine Vielzahl von vorgefertigten Elementen wie Buttons, Feldern, Karten und Dialogen zur Verfügung. Das Paket wurde so konzipiert, dass ein KI-Programmieragent es mit nur einer einzigen Zeile Code in eine Anwendung einfügen kann. Der Agent befolgt dabei die Anweisungen in einer kurzen Datei im Repository – dadurch erhält die Anwendung einen funktionierenden Themenauswähler, ein standardkonformes Design sowie alle notwendigen Design-Elemente zum Weiterentwickeln.

Die meisten Webanwendungen enden damit, dass drei verschiedene Themes an drei unterschiedlichen Stellen definiert werden: ein :root-Block im Haupt-CSS, ein zweiter Block unter @media (prefers-color-scheme: dark) sowie ein dritter Block, den ein Entwickler irgendwo hinzugefügt hat, damit der Theme-Picker funktioniert. Das Ergebnis ist jedes Mal dasselbe: Ein Steuerelement sieht auf der Startseite anders aus als in den Einstellungen – und im Issue-Tracker taucht dann die Frage auf, warum das dunkle Theme den Footer blau färbt. Ich habe ThemeForge entwickelt, um genau solche Probleme zu verhindern. Es besteht aus einem einzigen Ordner, ui-theme/, der die Laufzeitumgebung, eine Basis-Schicht, die Komponentenklassen, die Design-Tokens aller zehn Themes, einen Theme-Picker sowie optionale Adapter für Tailwind und Quasar enthält – außerdem eine kurze Datei AGENTS.md für KI-Programmieragenten. Man legt diesen Ordner einfach in die Anwendung ab, fügt vier Zeilen zum Seitenkopf hinzu – schon hat man einen funktionierenden Theme-Picker sowie ein System-folgendes Standard-Theme. Der Agent, der die Installation vornimmt, erledigt alles mit einem einzigen Befehl; der Rest dieses Artikels richtet sich an alle, die tiefer in die Funktionsweise einsteigen möchten.

Dieser Artikel dient als Übersicht: Was befindet sich eigentlich im Ordner? Welche zehn Themes gibt es und wofür sind sie gedacht? Wie sieht es mit dem Kontrast aus? Außerdem werden die Design-Tokens sowie Komponentenklassen als Nachschlagewerk bereitgestellt. Der zweite Teil dient bewusst als schnell lesbare Referenz – alle Tokens, alle Komponenten sowie alle öffentlichen Methoden sind dort aufgeführt, sodass ein KI-Agent (oder Sie selbst in Zukunft) sie wortgetreu übernehmen kann.

Kurz gesagt:

  • Herunterladen: github.com/LaserLloyd/ThemeForge – MIT-Lizenz, kostenlos; im Download-Bereich unten gibt es auch ein ZIP-Archiv mit dem Quellcode.
  • Was ist das? Ein einziger Ordner, ui-theme/, den man in jede Webanwendung einbinden kann. Er stellt zehn Farbthemes, einen Theme-Picker, rund 250 Design-Tokens, eine Basis-Schicht für Elemente, Standards für Texte sowie eine vollständige Sammlung von Komponentenklassen bereit – darunter Buttons, Eingabefelder, Schalter, Karten, Dialoge, Toasts und Tabellen. Alles basiert auf reinem CSS sowie einem kleinen Skript. Es gibt keinen Build-Schritt, kein Node.js, keine weiteren Abhängigkeiten.
  • Einzeilige Installation (aus dem README übernommen): python3 -c "import urllib.request as u,sys;sys.argv=['update.py','--dest','static/ui-theme'];exec(u.urlopen('https://raw.githubusercontent.com/LaserLloyd/ThemeForge/main/ui-theme/update.py').read())"
  • Reihenfolge im Seitenkopf (wichtig!): Zuerst ui-theme.js einbinden (klassisch, blockierend – niemals defer oder module), danach ui-theme-base.css und ui-components.css; anschließend das eigene CSS der Anwendung sowie zuletzt ui-theme.css, damit die Theme-Tokens Vorrang haben.
  • Theme-Picker: Es genügt ein einziges Element: <select class="ui-select" data-ui-theme-picker aria-label="Theme"></select>. Dieser füllt sich selbstständig und bleibt zwischen Tabs synchronisiert.
  • Die zehn Themes: Sechs Kern-Themes (Purple, Midnight Gold, Glacier, Forest, Paper, Daylight) sowie vier optionale Varianten (Electric Yellow, LaserLloyd, LaserLloyd Light, Night Red). Alle Themes bestehen die Kontrastprüfung ohne Fehler.
  • Kontrast: Haupttext hat ein Verhältnis von 7:1, sekundärer Text 6:1; alle Textebenen auf allen Oberflächen mindestens 4,5:1. Kanten von Steuerelementen sowie Ein-/Aus-Zustände erreichen 3:1 – erkennbar an Form und Füllung, nicht nur an Farbe.
  • Für KI-Agenten konzipiert: AGENTS.md enthält die Installationsanweisungen in Form von Text – ein beliebiger Agent kann sie nutzen, um den Theme-Picker in einem Schritt zu aktivieren. Die CI des Repos (GitHub Actions, drei Jobs) prüft das Projekt: Ein Klon, eine Kontrastprüfung, node --check für alle JS-Dateien sowie ein Testlauf des Runtimes mit headless Chrome.

Wo man es bekommt

Es gibt ein einziges Repository unter MIT-Lizenz: github.com/LaserLloyd/ThemeForge. Die Installationsanleitung findet sich in AGENTS.md, das Ergebnis der Kontrastprüfung in contrast report. Möchten Sie lieber ein ZIP-Archiv? Im Download-Bereich am Ende dieser Seite finden Sie den kompletten Quellcode; außerdem ist er auch auf der Downloads-Seite verfügbar. Falls kein Python installiert ist, nennt das README auch die Varianten git clone –depth 1, npx degit sowie eine jsDelivr-<script>-URL, die auf @v1.0.0 verweist – nützlich für Prototypen.

Was am Ende dabei herauskommt

Der Nutzer kann sein bevorzugtes Theme problemlos auswählen: Es gibt einen Header mit einem Theme-Picker, der alle verfügbaren Themes kennt; ein dunkles und ein helles Standard-Theme, die sich automatisch an die Systemeinstellungen anpassen. Im Quellcode der Anwendung genügt eine einzige CSS-Zeile: background: var(–surface-2) statt #1d1d39. Wählt man ein Theme aus und lädt die Seite neu, gibt es keinen Flackern – das Runtimeskript läuft synchron im <head>, liest die eigenen data-*-Einstellungen aus dem Tag und setzt das Theme noch vor dem ersten Zeichnen. Öffnet man den Theme-Picker in zwei Tabs und ändert das Theme in einem, passt sich der andere automatisch an (dank eines storage-Event-Listeners). Wählt man beim Drucken ein dunkles oder OLED-Theme aus, schaltet die Laufzeitumgebung vorübergehend auf das helle Pendant um – oder versteckt je nach Einstellung in data-print-theme die Navigation, sodass das gedruckte Blatt gut lesbar ist; bei einem hellen Theme bleibt alles wie gewohnt.

Notes

Inbox

3 notes, 1 unread

Quarterly review Pinned

Draft of the Q3 retrospective — looking for two more examples before Friday.

Trip packing list

Passport, charger, the small torch.

Eine App-Shell, erstellt mithilfe von ui-app, ui-card, ui-btn, ui-switch sowie den --surface-* / --text-* / --accent-Tokens. Der Theme-Picker besteht aus einem einzigen <select data-ui-theme-picker> – die Laufzeitumgebung füllt ihn automatisch und sorgt für Synchronisation.

Die obige Abbildung stellt die interne Demo dar – kein Screenshot von einer separaten Datei. Das vollständige Exemplar mit allen Komponenten in jedem Theme findet sich im Repository unter specimen/index.html (aufrufbar via python3 -m http.server und anschließend /specimen/).

Wie alles zusammenhängt

Die Laufzeitumgebung besteht aus einem kleinen Skript, ui-theme.js (ca. 23 KB, 575 Zeilen), das nacheinander drei Aufgaben erledigt. Zuerst liest es die eigenen data-*-Attribute aus dem <script>-Tag, in dem es enthalten ist – so bleiben die Einstellungen mit der Datei verbunden. Anschließend prüft es localStorage sowie die Systemeinstellung „helles/dunkles Theme“ und schreibt das gewählte Theme in <html data-palette> sowie den aktuellen Modus in <html data-theme> (z. B. amoled, dark oder light) – und zwar noch vor dem ersten Zeichnen. Danach durchsucht es das Dokument nach Elementen vom Typ <select data-ui-theme-picker>, füllt diese mit der Liste der verfügbaren Themes auf (und reagiert auch auf später von Frameworks erzeugte Instanzen). Schließlich stellt es window.UITheme bereit; sobald ui-components.js geladen ist, auch window.UIComponents. Zudem registriert es einen storage-Event-Listener, sodass beide Tabs synchron bleiben. Das CSS ist übersichtlich strukturiert: ui-theme-base.css legt die Standards für Texte, Links, Fokusringe, Scrollbalken sowie reduzierte Bewegung fest; ui-components.css definiert Buttons, Eingabefelder, Schalter, Karten, Dialoge, Toasts und Tabellen. Die einzige Datei, die sich zwischen den Themes ändert, ist ui-theme.css: Darin werden alle Tokens – Farben, Typografie, Abstände, Rundungen, Schatten, Animationen – für alle zehn Themes unter einem [data-palette=”…”]-Selektor definiert. Für das „Purple“-Theme genügt :root, also die Abwesenheit von data-palette. Das Runtimeskript wählt das Theme aus; das CSS stellt es dann grafisch dar.

Die Übernahme des System-Designs ist es, was viele überrascht: data-default=”auto” liest bei jedem Seitenaufruf prefers-color-scheme aus; die Laufzeit kombiniert dies mit der vom Nutzer gespeicherten Auswahl (oder mit data-default-dark bzw. data-default-light) zur Theme-Auswahl. Ändert man das System-Design und aktualisiert die Seite, passt sich diese an. Wählt man ein Theme explizit aus dem Auswahlfeld, bleibt dieses so lange aktiv, bis der Nutzer es löscht (oder UITheme.reset() aufruft). Zudem bindet die Laufzeit ein storage-Event ein, sodass zwei geöffnete Tabs derselben App ohne Serverkontakt synchron bleiben.

Installation

Die Datei AGENTS.md im Repository enthält die ausführliche Anleitung; die Kurzversion besteht aus einer einzigen Befehlszeile sowie vier Head-Tags. Vom Wurzelverzeichnis der App aus:

python3 -c "import urllib.request as u,sys;sys.argv=['update.py','--dest','static/ui-theme'];exec(u.urlopen('https://raw.githubusercontent.com/LaserLloyd/ThemeForge/main/ui-theme/update.py').read())"

Damit wird der Installer heruntergeladen, welcher die neueste Version holt, jede Datei mit der SHA-256-Liste in files.json vergleicht und den Ordner anlegt. Unter Windows nutzt man python bzw. py statt python3; die Zeile funktioniert in PowerShell, cmd und Bash gleichermaßen. Die vier Zeilen im <head> jedes Dokuments:

<script src="/static/ui-theme/ui-theme.js"
        data-themes="purple,midnight-gold,glacier,forest,paper,daylight"
        data-default="auto" data-default-dark="midnight-gold" data-default-light="daylight"
        data-storage-key="myapp.theme"></script>
<link rel="stylesheet" href="/static/ui-theme/ui-theme-base.css">
<link rel="stylesheet" href="/static/ui-theme/ui-components.css">
<!-- Ihre Stylesheets -->
<link rel="stylesheet" href="/static/ui-theme/ui-theme.css">

Drei Regeln, jede aus gutem Grund. Das Skript ui-theme.js ist klassisch und blockierend – niemals type=”module”, defer oder async –, weil es seine Einstellungen aus dem eigenen Tag liest (document.currentScript, was für Modulskripte null ist) und das Theme vor dem ersten Rendern festlegt. Die Basis- sowie Komponenten-CSS-Dateien laden vor der App-CSS, sodass die eigenen Regeln der App bei gleicher Spezifität Vorrang haben. ui-theme.css lädt zuletzt, wodurch alte App-Variablen kein Theme-Token überschreiben können. Der Auswahlfeld-Code besteht aus einer einzigen Zeile: <select class=”ui-select” data-ui-theme-picker aria-label=”Theme”></select>. Aus Skript heraus: UITheme.set(‘glacier’), UITheme.current(), UITheme.onChange(fn). Insgesamt dauert die Installation laut Einleitung von AGENTS.md etwa fünf Minuten.

Der Agent, der dies in einem Schritt auf einer echten App umsetzte, sah so aus: Der Mensch bat einen KI-Programmieragenten, der App ein Dunkelmodus sowie ein Theme-Auswahlfeld zu verpassen. Der Agent las AGENTS.md, führte die eine Zeile in static/ui-theme/ aus, kopierte die vier Head-Tags in die Basisvorlage, ersetzte zwei Farbangaben durch var(–surface-2) bzw. var(–text-secondary) und platzierte das Auswahlfeld im Header. Sechs Diff-Zeilen in der App – keine neuen Abhängigkeiten. Der Kontrast-Check deckt alle Kombinationen ab, die die Komponenten nutzen; die Laufzeit folgt dem System-Design automatisch. Ein zukünftiger Commit, der eine Farbe hartkodiert, ist das einzige, was der Lint-Prüfer zu finden hätte.

Die Themes

Die ersten sechs sind die Standardauswahl, die jede App anbietet; die vier optionalen Themes erscheinen nur, wenn eine App sie aufführt. Jedes Theme besteht einen Kontrast-Check (docs/contrast-report.md): Haupttext hat ein Verhältnis von 7:1, sekundärer Text 6:1 auf allen Oberflächen; alle weiteren Textebenen mindestens 4,5:1. Kanten sowie Ein-/Aus-Zustände erreichen 3:1; in jedem Theme erkennt man sie auch über Form statt Farbe. Die vollständige Liste:

Theme Gruppe Grundfarbe Beschreibung
Purple Standard dunkel Violetter Akzent und sanftes Lavendel auf dunklem Indigo; das Basis-Theme: seine Werte sind die :root-Standards.
Midnight Gold Standard OLED Warmes Gold auf reinem Schwarz – ideal für OLED-Bildschirme.
Glacier Standard OLED Eisfarbenes Blau und ein Signature-Farbton auf Schwarz; dazu ein tiefes Türkis als Akzent.
Forest Standard OLED Helles Smaragdgrün sowie braune Nuancen auf Schwarz.
Paper Standard hell Warmes Pergament mit braunem Text, einer Serifenschrift für Prosa und einem roten Akzent.
Daylight Standard hell Sauberes Weiß mit blauem Akzent.
Electric Yellow Optional dunkel Säuregelb auf grauem Grund; mit engen Rundungen und klaren Linien.
LaserLloyd Optional dunkel Laserblau auf fast schwarzem Grau – vom Autor selbst entworfen; passt zu LaserLloyd Light.
LaserLloyd Light Optional hell Das helle Pendant zu LaserLloyd.
Night Red Optional OLED Ein „Nachttheme“ mit geringer Blaulichtbelastung: rotes Textelement auf Schwarz, keine Blauanteile in irgendeinem Farbwert.

Drei der vier optionalen Themes sind bewusst auffällig. Electric Yellow nutze ich beim CSS-Review bei Dunkelheit, um die Seite lauter als meinen Editor zu gestalten; LaserLloyd passt zum Blau-Grau-Look dieser Seite und sorgt für Konsistenz zwischen ihr und der App. Night Red ist ein eigenständiges „Nachtprofil“, das der Kontrast-Check gegen einen erweiterten Satz von 171 Zeilen prüft (147 Standardzeilen plus zusätzliche für schwaches Licht); dabei enthält jedes Token des Paletten-Designs keinen Blauanteil (docs/contrast-report.md „Zero-blue audit“; README.md §Night Red; docs/THEMES.md §Night Red).

Fallstricke

  • Ein hardcodierter Farbwert in Ihrem CSS ist das Problem – nicht das Theme. Die Überprüfung prüft lediglich Token; ein color: #fff im App-Code bleibt in jedem Theme weiß. tools/lint_colors.py (im Repository) sowie die Suche in AGENTS.md §8 erkennen das; der Lint in der CI führt diesen Schritt jedoch nicht aus – daher müssen Sie ihn lokal ausführen, bevor Sie mergen.

  • ui-theme.js muss als erstes im <head> stehen – klassisch, nicht mit defer oder module. Ein Modulskript besitzt kein document.currentScript; die Laufzeit liest ihre eigenen data-*-Attribute aus dem Tag. Das Symptom: kurzzeitig wird das falsche Theme angezeigt, danach das richtige.

  • ui-theme.css muss nach dem CSS der App geladen werden – nicht davor. Die Reihenfolge lautet: Basis, Komponenten, App, Token. Eine App-Regel gleicher Spezifität, die nach den Token geladen wird, verliert den Wettbewerb.

  • data-themes bestimmt, was der Auswähler anzeigt. Ein gespeichertes Theme, dessen Slug nicht in data-themes steht, wird beim nächsten Laden ignoriert (die Laufzeit greift auf das Standard-Theme zurück). Wenn Sie ein Theme entfernen, fügen Sie bitte einmal data-legacy-key sowie data-legacy-map hinzu – dadurch wird der gespeicherte Wert migriert.

  • Tailwinds rounded-md und font-sans ändern sich nach der Installation. Das ist gewollt: Das Theme definiert die Token –radius- bzw. –font-; deren Werte haben Vorrang. Leisten Sie dagegen keinen Widerstand.

  • Next.js Hydration-Warnung. Fügen Sie suppressHydrationWarning zu <html> hinzu und deaktivieren Sie die no-sync-scripts-Lint-Regel für den Head-Bereich: Die Laufzeit setzt Attribute auf <html> noch vor der React-Hydration.

  • Ein weiteres Bibliothek liest data-theme aus <html> (z. B. daisyUI, Pico). Die Laufzeit schreibt dort data-theme=”amoled|dark|light”; prüfen Sie, ob die Bibliothek darauf reagiert. Falls ja, verwenden Sie über data-mirror-attr ein anderes Attribut.

  • Bearbeiten Sie nichts innerhalb von ui-theme/. Der Ordner wird bei Updates überschrieben; der Lint erkennt manuelle Änderungen, und die Installation verweigert das Überschreiben editierter Dateien. Verschieben Sie Änderungen stattdessen in das eigene CSS der App.

  • Die in den Stacks genannten Schriftarten werden nicht mitgeliefert. Jeder Stack greift auf Systemschriften zurück; falls Sie Inter, JetBrains Mono, Space Grotesk oder Archivo nutzen möchten, laden Sie diese selbst nach (die Integrations-Dokumentation enthält ein kopierbares <link>).

  • prefers-contrast: more erhöht die Linienstärke sowie die Sichtbarkeit von sehr hellen Texten. Dafür ist kein Theme-Flag nötig; die Laufzeit reagiert darauf, und das CSS passt sich an. Die Token-Gruppe high-contrast stellt die ältere Variante für denselben Effekt dar.

Wo mich das zurücklässt

Was ich wollte, war eine Möglichkeit, jedem von mir erstellten App ein echtes Theme-System zu verleihen – ohne jedes Mal eins von Grund auf neu schreiben zu müssen. ThemeForge ist die Version davon, die ich gerne beibehalten möchte. Die Ordner, die ich in die Apps einfüge, heißen nun ui-theme/ sowie der Name der jeweiligen App; die vier Head-Block-Tags sowie der Picker sind in jedem Framework gleich. Der Installations-Agent liest dabei die Datei AGENTS.md – nicht eine Slack-Nachricht. Die Kontrastprüfung, die Tests im Headless-Chrome-Modus sowie node –check auf jeder ausgelieferten JS-Datei geben mir das Vertrauen, weiterzumachen. Die Version ist 1.0.0 – schließlich sind Tokens die öffentliche API, und eine Umbenennung von Tokens zählt als Major-Version-Update. Ein Release entspricht einem Git-Tag; der Ordner VERSION stimmt damit überein, und die JSON-Dateien werden mit derselben Prüfsummenliste signiert, gegen die update.py prüft. Die CI des Repos ist unter Linux, Windows sowie Python 3.9 erfolgreich – dieselben Checks funktionieren auch bei einem frischen Klon auf diesem Rechner.

Referenz (für KI-Agenten)

Der Rest dieses Artikels dient als Referenzkarte, die ein Coding-Agent (oder mein zukünftiges Ich) wortgetreu übernehmen kann. Der obige erste Teil besteht aus Fließtext; der zweite Teil ist strukturiert, leicht lesbar und speziell dafür konzipiert, von einem Tool verarbeitet zu werden. Nachfolgend finden Sie jedes Token, jede Komponentenklasse, jede öffentliche Methode in window.UITheme sowie window.UIComponents, jedes Theme, jeden Einstellungsparameter im Script-Tag, jeden Adapter, den vollständigen Installationspfad, die Kontrastvorgaben sowie den Versionsblock.

Dateimanifest

Das Repository enthält zwei wichtige „Baumstrukturen“: das Plug-and-Play-Bundle, das die App kopiert, sowie das Design und die Werkzeuge, mit denen dieses erstellt wird. Der Artikel befasst sich mit dem Bundle.

Drop-in-Bundle – was die App kopiert (ui-theme/):

Datei Größe Zeilen Beschreibung
ui-theme.js 23.515 B 575 Laufzeit: wendet das gespeicherte Theme vor dem ersten Rendern an, folgt der Systemeinstellung „Hell/Dunkel“ mittels data-default="auto", füllt Auswahlfelder aus, synchronisiert Tabs und stellt window.UITheme bereit
ui-theme-base.css 13.255 B — Standardeinstellungen für Elemente: Text, Links, Überschriften, Code, Fokus-Ring, Scrollbars, reduzierte Bewegung, Textebenen, .ui-markdown, Farben für Highlight.js
ui-components.css 51.344 B — Komponenten: Buttons, Eingabefelder, Checkboxen, Radio-Buttons, Schalter, Karten, Badges, Hinweiskästen, Tabs, segmentierte Steuerelemente, Tabellen, Dialoge, Menüs, Tooltips, Benachrichtigungen, Fortschrittsanzeigen, Codeblöcke sowie eine App-Struktur
ui-theme.css 86.389 B (21.197 B nach GZIP-Komprimierung) — Alle zehn Theme-Token – insgesamt ca. 20 KB nach GZIP-Komprimierung
ui-components.js 5.441 B 135 Optional: themenbezogene Versionen von confirm(), alert(), prompt() und toast()
ui-theme.d.ts 2.841 B — TypeScript-Deklarationen für window.UITheme und window.UIComponents
update.py 16.081 B — Installiert und aktualisiert den Ordner; prüft jedes File auf Basis des SHA-256-Hashes
themes.json 4.089 B — Liste der verfügbaren Themes (Name, Familie, Grundfarbe, Farbpalette, Schriftarten)
files.json 1.401 B — Liste der Prüfsummen, die von update.py überprüft werden
VERSION 30 B — Versionsnummer des Ordners (ThemeForge 1.0.0 3db64d9f574f)
README.md 6.342 B — Anleitungen zur Nutzung des Pakets
adapters/quasar.css 24.997 B — Zuordnung für NiceGUI/Quasar
adapters/quasar.js 1.468 B 40 JS-Brücke zwischen NiceGUI und Quasar
adapters/tailwind.css 4.399 B — Zuordnung für Tailwind CSS v4 mittels @theme inline
adapters/tailwind-v3.preset.js 2.915 B 54 Preset für Tailwind CSS v3

Das Design und die Werkzeuge, die das Bundle erstellen (werden nicht in die App kopiert):

Datei Größe Beschreibung
README.md 6.592 B README des Repos
AGENTS.md 19.063 B Installationsanleitung für KI-Agenten in Textform
CHANGELOG.md 4.425 B Versionshistorie (1.0.0 ist die erste Veröffentlichung)
CLAUDE.md 1.498 B Konventionen für Claude im Repo
CONTRIBUTING.md 4.476 B Anleitung zur Mitarbeit an den Themes
LICENSE 1.067 B MIT-Lizenz; Copyright © 2026. Im Originaldokument wird der Autor mit seinem persönlichen Namen genannt; die auf der Website verwendete Form ist die offizielle Bezeichnung. Der Inhalt der Lizenzdatei entspricht dem Original-Lizenztext. Wird nicht im Download-Zip-Archiv enthalten, da die Identität des Autors als potenziell unzulässige Offenlegung angesehen wird.
docs/TOKENS.md 15.391 B Alle Tokens, gruppiert nach Kategorien
docs/COMPONENTS.md 13.889 B Alle Komponentenklassen samt zugehörigem Markup
docs/THEMES.md 8.081 B Die verfügbaren Themes, Designhinweise sowie Anleitung zum Hinzufügen neuer Themes
docs/INTEGRATIONS.md 10.604 B Installationsschritte für verschiedene Frameworks
docs/TEXT.md 5.465 B Textformate sowie die Markdown-Formatierung
docs/UPDATING.md 4.134 B Updates, Caching-Mechanismen sowie die Bedeutung der Prüfsummen
docs/contrast-report.md 124.372 B Kontrast-Audit: 10 Themes × jeweils 147–171 Zeilen
docs/theme-template.css 9.854 B Vorlage für neue Themes, verwendet von tools/sync_theme.py
tokens/<theme>.json ca. 57 KB pro Datei Aufgelöste Tokens jedes Themes im W3C DTCG JSON-Format
examples/static-html/ 3.731 B index Beispiel mit reinem HTML/CSS/JS
examples/fastapi-jinja/ 2.172 B app.py Beispiel für die Nutzung von FastAPI und Jinja
specimen/index.html 17.721 B Alle Komponenten aller Themes – lokal abrufbar
tools/check_contrast.py 43.171 B Skript zum Durchführen des Kontrast-Audits (wird im CI-Prozess ausgeführt)
tools/lint_colors.py 22.711 B Prüft Farbangaben in der CSS-Datei auf Korrektheit
tools/sync_theme.py 41.671 B Erstellt ui-theme.css, tokens/*.json sowie docs/contrast-report.md aus den Quelldateien in src/css/*.css
tools/update.py 16.081 B Installations- und Verifizierungsskript (entspricht ui-theme/update.py)
tools/screenshots.py 3.273 B Erzeugt Vorschau-Bilder der Themes für docs/images/
tests/test_tools.py 17.606 B Python-Unit-Tests (32 Tests in diesem Klon; 1 Test wird übersprungen)
tests/run_browser_tests.py 3.570 B Headless-Chrome-Tests des Runtimesystems
tests/runtime.html 24.930 B Testumgebung für Browser-Tests
.github/workflows/ci.yml — CI-Konfiguration: Kontrastprüfung, node --check, Unit-Tests, Browser-Tests sowie Prüfung auf korrekte Zeilenumbrüche unter Linux, Windows und Python 3.9

Die CI des Repos läuft in drei Jobs: „checks“ auf Ubuntu mit Python 3.12, „tools-on-windows“ auf Windows mit Python 3.11 sowie „updater-on-oldest-python“ auf Ubuntu mit Python 3.9. Das lokale Clone besteht den Test „node –check“ für jede ausgelieferte JS-Datei; das Kontrast-Tool reproduziert alle zehn Zeilen des Audits. Zudem bestehen alle Unit-Tests („32 erfolgreich, 1 übersprungen in 1,212 Sekunden“ unter Linux mit Python 3.14 am 05.10.2026).

Design-Tokens (Gruppen, Rolle, Beispielwert)

Jedes Theme löst jedes Token auf. Die unten angegebenen Werte stammen von Purple (dem :root-Basis-Theme); die übrigen Themes haben ihre eigenen aufgelösten Werte in tokens/<theme>.json (DTCG JSON). Verwenden Sie ein Token mittels var(--name). Deklarieren Sie ein Token niemals erneut im App-CSS – vergeben Sie den Variablen der App ein Präfix (--myapp-sidebar-w) oder erstellen Sie einen Alias für das Token (--myapp-brand: var(--accent)). Quelle: docs/TOKENS.md.

Gruppe Token Rolle Beispiel (Lila)
Oberflächen --surface-void dunkler als die Seite (Vollbild) #08080f
Oberflächen --surface-0 die Seite selbst #0e0e1b
Oberflächen --surface-1 Navigationsleiste #14142a
Oberflächen --surface-2 Karten/Elemente #1d1d39
Oberflächen --surface-3 Hover-Zustand #232342
Oberflächen --surface-4 Aktiver Zustand #262648
Oberflächen --surface-sunken Einliegende Bereiche #0a0a14
Oberflächen --surface-overlay Menüs, Popovers #1d1d39
Oberflächen --glass-1/2/3 Transparente Scheiben rgba(29,29,57,.72/.84/.92)
Oberflächen --glass-highlight Glanzeffekt für Glas rgba(255,255,255,.055)
Oberflächen --code-bg Hintergrund für Code #0b0b16
Text --text-primary Haupttext #e8e8f0
Text --text-secondary Beschriftungen, Beschreibungen #a0a0bd
Text --text-tertiary Hinweise, Zeitstempel #8d8db0
Text --text-disabled Deaktivierte Steuerelemente #717195
Text --text-inverse Text auf hellem Hintergrund #0e0e1b
Text --text-link / --text-link-hover Links sowie akzentuierter Text #a78bfa / #c4b5fd
Text --on-accent / --on-danger / --on-success / --on-warning / --on-media / --on-media-muted Beschriftung auf farbigem Hintergrund #ffffff / #2a0808 usw.
Akzent --accent / --accent-hover / --accent-pressed Markenakzent, Hauptaktionen #7c3aed / #8250f0 / #6d28d9
Akzent --accent-subtle / --accent-muted / --accent-glow Abgetönter Hintergrund, sanfter Effekt rgba(124,58,237,.16/.26/.35)
Akzent --accent-rgb Für JavaScript: rgba(var(--accent-rgb), .2) 124,58,237
Akzent --accent-2 / --accent-2-subtle Sekundärakzent #5eead4
Aktionen --cta / --cta-hover / --cta-pressed / --on-cta Knöpfe für Hauptaktionen #7c3aed / #8250f0 / #6d28d9 / #ffffff
Aktionen --cta-shadow / --cta-shadow-hover Schatteneffekte für solche Knöpfe 0 6px 20px rgba(124,58,237,.28) / .38
Aktionen --highlight / --highlight-subtle / --on-highlight Markierungen, Farbe von Hinweisen #fcd34d / rgba(252,211,77,.12) / #251a00
Linien --border-subtle / --border / --border-strong Ränder von Formelementen; --border-strong hat ein Verhältnis von 3:1 #21213b / #292945 / #6f6f9c
Linien --divider Dünne Linien #21213b
Linien --focus-ring / --focus-ring-width / --focus-ring-offset Fokusring #a78bfa / 2px / 2px
Linien --glass-stroke / --glass-stroke-strong Ränder für Glasoberflächen rgba(255,255,255,.08/.16)
Steuerelemente --selected / --on-selected Aktiv/ausgewählt je nach Theme
Steuerelemente --unselected-border / --unselected-fg Deaktivierter Zustand; Verhältnis 3:1 zu jedem Hintergrund je nach Theme
Status --success / --warning / --danger / --info Punkte, Balken, Füllungen je nach Theme
Status --success-text / --warning-text / --danger-text / --info-text Textfarben zu den jeweiligen Status je nach Theme
Status --success-subtle / --warning-subtle / --danger-subtle / --info-subtle Abgetönte Hintergründe je nach Theme
Status --success-border / --warning-border / --danger-border / --info-border Ränder zu den Status je nach Theme
Status --idle / --idle-text / --idle-subtle / --idle-border / --idle-hover Neutraler Zustand je nach Theme
Status --live / --live-text / --live-subtle / --live-border / --live-hover „Aktiv“-Indikator je nach Theme
Code/Syntax --syn-bg / --syn-fg / --syn-comment / --syn-keyword / --syn-string / --syn-number / --syn-function / --syn-attr / --syn-tag / --syn-builtin / --syn-type / --syn-variable / --syn-literal / --syn-operator / --syn-title / --syn-addition Syntaxhervorhebung je nach Theme
Code/Syntax --code-header-bg / --code-stroke Hintergrund sowie Rahmen von Codeblöcken je nach Theme
Diagramme --cat-1 … --cat-12 Farben für Diagrammdaten; Verhältnis 3:1 zu --surface-0 je nach Theme
Diagramme --seq-1 … --seq-5 Abstufungen von hell nach dunkel je nach Theme
Diagramme --div-1 … --div-5 Kategorien: schlecht, neutral, gut je nach Theme
Diagramme --chart-grid / --chart-axis Hilfslinien für Diagramme je nach Theme
Chatblasen --bubble-user-text / --bubble-assistant-text / --bubble-user-bg / --bubble-assistant-bg Chatblasen je nach Theme
Chatblasen --rp-speech / --rp-thought / --rp-shout / --rp-whisper / --rp-ooc / --rp-action / --rp-critical Farben für Rollenspiel-Chatblasen je nach Theme
Diff-Ansicht --diff-add-bg / --diff-add-text / --diff-remove-bg / --diff-remove-text Darstellung von Änderungen je nach Theme
Schriftgrößen --fs-xs / --fs-sm / --fs-md / --fs-lg / --fs-xl / --fs-2xl Schriftgrößen je nach Theme
Schriftgewichte --fw-medium / --fw-semibold / --fw-bold Schriftgewichte je nach Theme
Schriftarten --font-sans / --font-mono / --font-display Schriftarten je nach Theme
Abstände --space-1 … --space-8 Abstände von 4 bis 64 Pixeln je nach Theme
Rundungen --radius-sm / --radius-md / --radius-lg / --radius-pill Rundungen von Elementen je nach Theme
Schatten --shadow-1 / --shadow-2 / --shadow-3 / --shadow-4 Stärke der Schatteneffekte je nach Theme
Z-Stapelung --z-modal / --z-toast / --z-popover / --z-nav Reihenfolge von Elementen im Z-Stapel je nach Theme
Animationen --motion-fast / --motion-med / --motion-slow / --easing-standard Geschwindigkeit von Animationen; bei „reduced-motion“ werden Schleifen gestoppt je nach Theme
Markdown --md-bold / --md-italic / --md-bolditalic / --md-bolditalic-glow Formatierung für Markdown im App-Text je nach Theme
Sonstiges --mark-bg / --selection-text / --selection-bg / --media-filter / --quote-bar / --heartbeat-text / --heartbeat-hover / --offline-text / --on-offline / --canvas-handle Kleine Zusatzfunktionen je nach Theme

Quelle: docs/TOKENS.md (22 Gruppen, ca. 270 Tokens – grep -oE '\| \(–[a-zA-Z][a-zA-Z0-9-]*)` |’ docs/TOKENS.md | sort -u | wc -lliefert 272 eindeutige Token-Namen; 22 Gruppen mit## `).

Komponentenklassen (jeder Modifikator, jeweils in einer Zeile)

Der Zustand wird über native Attribute bestimmt (disabled, checked, aria-pressed, aria-selected, aria-current, aria-invalid, aria-busy; es werden niemals zusätzliche Klassen verwendet). Die meisten Selektoren bestehen aus nur einer Klasse, sodass später geladene Regeln mit gleicher Spezifität Vorrang haben. Logische Eigenschaften sind überall vorhanden (funktionieren auch bei Rechts-nach-Links-Schreibweise). „Aktiv“, „ausgewählt“ und „aktueller Zustand“ werden durch --selected dargestellt; „deaktiviert“ wird durch einen gestrichelten Rahmen gekennzeichnet. Quelle: docs/COMPONENTS.md.

Klasse Modifikatoren / Teile Beschreibung
ui-stack — Spaltenlayout; Abstand --space-3
ui-row — Zeilenlayout, zentriert; Abstand --space-2
ui-grid --ui-grid-min Automatische Erstellung von Spalten; min wird am Element gesetzt
ui-container — Zentriert; maximale Breite --content-max
ui-spacer — Schiebt den Rest einer Zeile nach hinten
ui-app __header __nav __main App-Shell (Header, Seitenleiste, Hauptinhalt); Navigationsleiste verschwindet unter 760 px
ui-brand — App-Titel im Header
ui-nav __label __item Seitenleiste
ui-title / ui-heading / ui-subheading / ui-lead / ui-kicker / ui-small / ui-mono / ui-num / ui-kbd / ui-code / ui-divider — Typografie-Elemente (<hr> ist .ui-divider)
ui-text-primary / -secondary / -tertiary / -disabled / -link — Text-Klassen; für neuen Code sollten die Tokens verwendet werden
ui-markdown — Container für formatiertes Markdown; siehe docs/TEXT.md
ui-btn --primary --ghost --outline --danger --cta --sm --lg --icon --block Knöpfe; funktionieren auch mit <a>; reagieren auf aria-pressed / aria-busy / disabled
ui-btn-group — Nebeneinanderliegende Knöpfe teilen sich abgerundete Kanten
ui-field — Container für Formularelemente (Label + Steuerelement + Hilfetext)
ui-label — Beschriftung eines Formularfeldes
ui-input --sm Text-Eingabefeld
ui-select — Gestyltes <select>; data-ui-theme-picker lädt den Theme-Picker
ui-textarea — Gestyltes <textarea>
ui-help — Hilfetext zu einem Feld (verweist auf aria-describedby)
ui-error — Fehlermeldung zu einem Feld; erscheint bei aria-invalid="true"
ui-input-group — Kombination aus Eingabefeld und Knopf (z.B. Suchfeld)
ui-check — Reihe von Checkboxen, Radio-Buttons oder Schaltern
ui-checkbox — Gestyltes <input type="checkbox">
ui-radio — Gestyltes <input type="radio">
ui-switch — role="switch"; Checkbox, die wie ein Schalter aussieht
ui-switch-state data-on data-off „An“/„Aus“-Beschriftung (aria-hidden); der Schalter meldet selbst seinen Zustand
ui-range — Gestyltes <input type="range">; Farbe wird durch --slider-color bestimmt
ui-segmented — Gruppe von Knöpfen, die wie Radio-Buttons funktionieren
ui-tabs ui-tab Reiterliste; Links nutzen <a aria-current="page">; Tastaturbedienung ist Aufgabe der App
ui-card __header __title __footer --raised --interactive Karte; aria-selected / aria-current kennzeichnen die ausgewählte Karte
ui-well — Einliegender Bereich (Logs, Vorschauen, sekundäre Inhalte)
ui-stat __label __value Paar aus Beschriftung und Wert
ui-badge --success --warning --danger --info --live --accent --neutral Pillenförmiges Badge
ui-dot --success --warning --danger --info --live --neutral Statuspunkt
ui-count --accent --danger Zähler-Chip
ui-callout --info --success --warning --danger __title Farbiger Hinweis; bei Fehlern sollte role="alert" verwendet werden
ui-table-wrap — Umhüllt <table class="ui-table"> für klebende Kopfzeilen/Scrollen
ui-table --hover --compact td.num Tabellenstil
ui-dialog — Gestyltes <dialog>
ui-drawer — Seitenleiste über <dialog>
ui-menu __item Menüliste
[data-ui-tooltip] data-ui-tooltip-side="bottom" Tooltip für beliebige Elemente
ui-progress — Linearer Fortschrittsbalken
ui-spinner — Ladeanzeige
ui-skeleton — Skelett-Loading-Animation
ui-breadcrumbs — Pfadleiste
ui-pagination — Seitennavigation
ui-avatar — Kreisförmiges Profilbild
ui-chip __remove Entfernbarer/auswählbarer Chip
ui-details — „Accordion“-Struktur über <details>
ui-fieldset — Feldsatz mit Legende
ui-codeblock __bar <figure> mit <figcaption class="ui-codeblock__bar"> + <pre>
ui-empty — Leerer Zustand
ui-bubble --user --assistant Chatblase

Öffentliche Methoden von window.UITheme und window.UIComponents

Quelle: ui-theme/ui-theme.d.ts (TypeScript-Deklarationen für beide globale Objekte).

window.UITheme (UIThemeApi):

Member Typ Funktion
version string (nur lesen) Die Version des Ordners, z. B. "1.0.0"
config Objekt (nur lesen) { themes, default, auto, storageKey, families, printTheme }
current() () => string Der aktuelle Theme-Name
theme([slug]) (slug?) => UIThemeInfo \| null Informationen zu einem Theme (oder dem aktiven)
list() () => UIThemeInfo[] Alle aktivierten Themes
set(slug) (slug) => string Wechsel zu einem Theme; gibt den Namen zurück
reset() () => string Zurücksetzen auf das Standard-Theme; gibt den Namen zurück
partner([slug]) (slug?) => string \| null Das „Licht“-/„Dunkel“-Partner-Theme einer Familie (z. B. laserlloyd ↔ laserlloyd-light)
toggleFamily() () => string \| null Wechsel zum Partner-Theme; gibt den neuen Namen zurück
onChange(listener) (fn) => () => void Abonnieren von Änderungen; gibt eine Funktion zum Abmelden zurück; detail.print ist true, wenn der Wechsel für den Druck erfolgt
token(name, [el]) (name, element?) => string Der Rohwert eines Tokens (z. B. "#7c3aed")
tokens(names, [el]) (names, element?) => Record<name, string> Mehrere Tokens auf einmal
color(name) (name) => string Aufgelöster rgb()-Wert für das Canvas
colors(names) (names) => Record<name, string> Mehrere aufgelöste Farbwerte für das Canvas
mountPicker(target, [opts]) (elOrSel, options?) => HTMLSelectElement \| null Füllt ein Select-Element mit dem Theme-Picker; options sind { label, coreLabel, optInLabel, systemLabel }

Das Ereignis ui-theme-change wird auf document ausgelöst mit { slug, theme, previous, print }.

window.UIComponents (UIComponentsApi): (erfordert ui-components.js)

Methode Signatur Funktion
confirm (opts: UIDialogOptions \| string) => Promise<boolean> Themede confirm()-Funktion; Optionen sind { title, message, label, confirmLabel, cancelLabel, danger }
alert (opts: UIDialogOptions \| string) => Promise<void> Themede alert()-Funktion
prompt (opts: UIPromptOptions \| string) => Promise<string \| null> Themede prompt()-Funktion; bei Abbruch wird null zurückgegeben; zusätzliche Optionen sind { value, placeholder, type }
toast (message, { kind?, timeout? }) => HTMLElement Toast mit den Varianten info, success, warning, danger; gibt das Element zurück

window.UI_THEME_MANIFEST (optional; hat Vorrang vor den Standardwerten aus dem Skript-Tag): { themes, default, defaultDark, defaultLight, storageKey, families, legacy, mirrorAttr, fontsHref, printTheme }. themes akzeptiert entweder ein Array oder eine kommagetrennte Liste.

Einstellungen über das <script>-Tag (data-*-Attribute)

Attribut Standardwert Funktion
data-themes Die sechs Kern-Themes (purple,midnight-gold,glacier,forest,paper,daylight) Kommagetrennte Liste der aktivierten Themes; steuert den Picker sowie welche gespeicherten Werte berücksichtigt werden. Ohne Angabe von data-themes aktiviert ui-theme.js die sechs Kern-Themes mit set==="core" (ui-theme.js:147-149).
data-default Das erste aktivierte Theme (der erste Name in data-themes, oder purple, falls keines aktiviert ist und nicht auto) Der Standard-Theme-Name; bei auto wird das OS-Setting genutzt. Der Text auto aktiviert die automatische Erkennung via prefers-color-scheme (ui-theme.js:164); fehlt oder ist leer, wird das erste aktivierte Theme verwendet (ui-theme.js:177-179).
data-default-dark Das erste nicht-helle aktivierte Theme (erster Name in data-themes, bei dem ground !== "light"; sonst das erste aktivierte Theme oder purple, falls nichts aktiviert ist) Entsprechend der Einstellung „auto“: wird bei dunklem OS-Setting ohne explizite Angabe verwendet (ui-theme.js:168-175).
data-default-light Das erste helle aktivierte Theme (erster Name in data-themes, bei dem ground === "light"; sonst das erste aktivierte Theme oder purple, falls nichts aktiviert ist) Entsprechend der Einstellung „auto“: wird bei hellem OS-Setting ohne explizite Angabe verwendet (ui-theme.js:168-175).
data-storage-key ui-theme Der Schlüssel für localStorage, unter dem die Auswahl des Nutzers gespeichert wird (ui-theme.js:185). AGENTS.md §3 empfiehlt, diesen Wert zu überschreiben mit <appname>.theme, damit die Einstellung der App nicht mit anderen ThemeForge-Apps auf derselben Domain kollidiert.
data-families false Gruppiert Themes nach Familien im Picker
data-print-theme auto Bestimmt, wie die Seite gedruckt wird: bei dunklem oder OLED-Theme wechselt auto zum hellen Partner-Theme (oder dem ersten hellen Theme bzw. daylight); ein konkreter Name druckt genau dieses Theme; none verändert nichts; bei hellem Theme bleibt die Seite unverändert (ui-theme.js:474-490).
data-legacy-key — Ein älterer Speicherschlüssel, der einmal migriert werden muss (zusammen mit data-legacy-map)
data-legacy-map — Eine Zuordnung „von→zu“ für alte Werte (JSON-Objekt)
data-mirror-attr — Spiegelt das aktive Theme auf ein anderes Attribut – für Bibliotheken, die dies auslesen
data-fonts-href — Verweist auf eine Stylesheet-Datei, die die Schriftarten des Themes lädt

Quellen: ui-theme.js:147-149, 164, 168-174, 185, 474-490 (Laufzeit-Standards) sowie AGENTS.md §3, §12 (empfohlene Überschreibungen – z. B. data-themes auf die sechs Kern-Themes setzen, data-default="auto" und data-storage-key="<appname>.theme").

Adapter

Adapter Dateien Funktion
NiceGUI / Quasar adapters/quasar.js + adapters/quasar.css ui-theme.js direkt nachladen, anschließend adapters/quasar.css via ui.add_head_html. Quasars Toggle-Elemente, Checkboxen und Radio-Buttons nutzen das Design für den Kontrollzustand; deaktivierte Elemente erscheinen gestrichelt mit voller Deckkraft. Entfernen Sie alle Aufrufe von ui.dark_mode() – der Adapter übernimmt dies.
Tailwind CSS v4 adapters/tailwind.css @import "./<pfad>/ui-theme/adapters/tailwind.css"; nach @import "tailwindcss";. Bereitgestellt werden z. B. bg-surface-2, text-fg, text-fg-muted, bg-accent, text-on-accent, border-line. Für Text werden fg-*-Werte verwendet, da text-*-Größen zu Tailwind gehören.
Tailwind CSS v3 adapters/tailwind-v3.preset.js presets: [require('./<pfad>/ui-theme/adapters/tailwind-v3.preset.js')]. Gleiche Token wie beim v4-Adapter, jedoch als v3-Preset ausgedrückt.

Der Tailwind-Adapter übersetzt die Theme-Token; der Quasar-Adapter passt die Komponentenklassen an. Beide sind nicht zwingend erforderlich, damit der Rest des Pakets funktioniert.

Vollständiger Installationsweg (wörtlich – der Installationsabschnitt aus AGENTS.md)

AGENTS.md ist das Installationsskript in Textform, geschrieben für KI-Programmierer. Die ersten beiden Abschnitte werden hier vollständig wiedergegeben; sie stellen die Anweisungen dar, die einer KI zugewiesen werden. Zeichen wurden gemäß §8 der Article-Forge-Spezifikation maskiert (ein rohes <blockquote> verarbeitet Markdown direkt, daher werden <, >, & als &lt;, &gt;, &amp; dargestellt).

## 1. Entscheidungen treffen

| Frage | Standardantwort |
|---|---|
| Wo soll der Ordner hin? | In den statischen Ordner der App, unverändert bereitgestellt: `static/ui-theme/` (Flask, FastAPI, Django), `public/ui-theme/` (Vite, Next.js, Create React App), `app/static/ui-theme/` oder neben `index.html` bei reinen Websites. |
| Welche Themes? | Die sechs Kern-Themes: `purple,midnight-gold,glacier,forest,paper,daylight`. Optional können weitere Themes (`night-red`, `electric-yellow`, `laserlloyd`, `laserlloyd-light`) hinzugefügt werden, falls der Nutzer sie wünscht. |
| Standard-Theme? | `auto`: Das OS-Setting für Helligkeit/Dunkelheit wird übernommen, bis der Nutzer selbst wählt (`data-default-dark="midnight-gold"`, `data-default-light="daylight"`). |
| Speicherschlüssel? | `<appname>.theme`, z. B. `notes.theme`. |

## 2. Installation

Ausführen im Root-Ordner der App (Python 3.9 oder neuer; ggf. `static/ui-theme` an Ihren Pfad anpassen):


python3 -c &quot;import urllib.request as u,sys;sys.argv=['update.py','--dest','static/ui-theme'];exec(u.urlopen('https://raw.githubusercontent.com/LaserLloyd/ThemeForge/main/ui-theme/update.py').read())&quot;
Unter Windows nutzen Sie `python` bzw. `py` statt `python3`; die Zeile funktioniert in PowerShell, cmd und Bash gleichermaßen. Das Skript lädt den Installer, der die neueste Version von GitHub abruft, jede Datei gegen eine Prüfsummenliste vergleicht und den Ordner schreibt. Spätere Updates lauten `python3 static/ui-theme/update.py`. Offline-Installation: Laden Sie ein Release-Archiv (`.tar.gz`) an einem anderen Ort herunter und führen Sie aus: `python3 update.py --source <archiv> --dest static/ui-theme` mittels der Datei `update.py` im Ordner `ui-theme/`. Alternativen, falls Python nicht verfügbar ist: - **git:** `git clone --depth 1 https://github.com/LaserLloyd/ThemeForge.git ut-tmp`, kopieren Sie `ut-tmp/ui-theme` in Ihre App und löschen Sie `ut-tmp`. - **Node:** `npx degit LaserLloyd/ThemeForge/ui-theme#v1.0.0 static/ui-theme`. - **Keine Installation (Prototypen, einzelne HTML-Dateien):** Laden Sie die Dateien via jsDelivr, fest auf eine Version gebunden: `https://cdn.jsdelivr.net/gh/LaserLloyd/ThemeForge@v1.0.0/ui-theme/ui-theme.js` (analog für jede CSS-Datei). Vermeiden Sie `@main`; der CDN-Cache hält bis zu 12 Stunden an. Ein CDN-Update erfolgt durch Änderung der Version; `update.py` sowie die Schritte 8.5, 9 und 10 gelten hier nicht.

Der Rest von AGENTS.md (Abschnitte 3–12) erläutert den Head-Block, den Picker, das Erstellen von Tokens, Regeln, Diagramme, die Verifizierung, den Text, der in die eigene AGENTS.md eingefügt werden sollte, damit nachfolgende KIs die Konvention beibehalten, den Update-Befehl, eine Fehlerliste sowie die oben genannten Referenzen.

Kontrast-Prüfung (Zusammenfassung, alle Themes)

tools/check_contrast.py läuft bei jedem Push im CI-System. Der vollständige Bericht ist 124 KB groß (ein Abschnitt pro Theme plus eine Zusammenfassung) und unter docs/contrast-report.md zu finden; die Zusammenfassung lautet:

Theme Gruppe Profil Prüfungen Fehler
purple Kern Standard 147 0
midnight-gold Kern Standard 147 0
glacier Kern Standard 147 0
forest Kern Standard 147 0
paper Kern Standard 147 0
daylight Kern Standard 147 0
electric-yellow Optional Standard 147 0
laserlloyd Optional Standard 147 0
laserlloyd-light Optional Standard 147 0
night-red Optional Nacht 171 0

Die Anforderungen, die jedes Theme erfüllen muss: Haupttext 7:1, sekundärer Text 6:1 (im Kontrastbericht wird dies als „Versprechen des 6:1-Standards“ bezeichnet – docs/contrast-report.md kennzeichnet jede Zeile mit text-secondary on surface-2 exakt so); alle Textstufen auf jedem Hintergrund mindestens 4.5:1, deaktivierte Elemente 3:1, on-accent und on-status ebenfalls 4.5:1; Status-Text auf farbigem Hintergrund 4.5:1, on-selected 4.5:1; bei ausgewählten/ nicht ausgewählten Elementen gelten 3:1 für Rand und Schrift; border-strong, control-track sowie der Fokusring müssen ebenfalls 3:1 erreichen; Syntax-Farben auf --syn-bg mindestens 4.5:1 (Kommentare 3.5:1). Die Diagramm-Serien (--cat-1 bis --cat-12) benötigen 3:1 im Verhältnis zu --surface-0. An/Aus nach Form: Ein „an“-Element wird mit --selected gefüllt; ein „aus“-Element zeigt nur einen Rand aus --unselected-border; bei Schaltern fügt „an“ eine Leiste zum Knopf hinzu, „aus“ einen Ring. Deaktiviert erscheint gestrichelt und in der deaktivierten Farbstufe – auch wenn es eigentlich „an“ sein sollte.

Frameworks

Gemäß docs/INTEGRATIONS.md: reines HTML · FastAPI, Flask, Starlette (Jinja-Templates) · Django · Vite, Vue, Svelte, SvelteKit, Astro · Next.js (App Router) · NiceGUI (Quasar) · Tailwind CSS · Electron, Tauri, pywebview · Schriftarten · Diagramme · Content Security Policy. Für jedes Framework: ui-theme/ in den statischen Ordner legen, den Head-Block gemäß AGENTS.md §3 einfügen und den Ordner ohne Cache bereitstellen (z. B. durch Versionierung der URLs), damit Updates sofort sichtbar sind. Im Repository finden Sie zwei konkrete Beispiele: examples/static-html/ (eine einzelne Seite) sowie examples/fastapi-jinja/ (FastAPI + Jinja; 2.172 Byte große app.py).

Druck, Kontrast und Animationen

Drei Aspekte, die der Laufzeitcode erkennt und auf die das CSS reagiert – ohne pro-Theme-Einstellungen:

– Drucken – data-print-theme bestimmt, welches Theme beim Drucken verwendet wird (ui-theme.js:474-490). Wenn das aktive Theme dunkel oder für OLED-Displays geeignet ist, schaltet auto automatisch auf das helle Pendant dieses Themes um – oder auf das erste aktivierte helle Theme bzw. auf „daylight“. Der Bezeichner des gewählten Themes wird beim Drucken verwendet; „none“ bewirkt, dass kein Theme gewechselt wird. Bei einem hellen Theme wird die Seite einfach so gedruckt, wie sie ist. Beim Drucken werden außerdem die Seitenleiste, Toasts, Menüs sowie Tooltips ausgeblendet.

– prefers-contrast: more – In jedem Theme werden die Linienstärken erhöht und der dritte Textgrad auf das Niveau des sekundären Textgrads angehoben.

– prefers-reduced-motion – Alle Animationen werden gestoppt bzw. verkürzt; die Werte der Variablen --motion-* werden auf 0 gesetzt.

Versionen

Aus dem Repository, das in diesem Artikel beschrieben wird (geklont am 05.10.2026):

$ git log -1 --format='%h %ci'
56fb665 2026-10-05 21:46:52 +0900        # ThemeForge 1.0.0

$ cat ui-theme/VERSION
ThemeForge 1.0.0 3db64d9f574f

$ wc -c ui-theme/*.js ui-theme/*.css ui-theme/*.ts ui-theme/*.py 2>/dev/null
  23515 ui-theme.js
   5441 ui-components.js
   2841 ui-theme.d.ts
  16081 update.py
  13255 ui-theme-base.css
  51344 ui-components.css
  86389 ui-theme.css

$ node --check ui-theme.js ui-components.js
(node v24.18.0) – Beide Dateien sind in Ordnung; ebenso adapters/quasar.js sowie adapters/tailwind-v3.preset.js.

$ python -m unittest discover -s tests
32 Tests wurden in 1,212 Sekunden ausgeführt.
OK (1 Test übersprungen)

$ python tools/check_contrast.py --fail-on any
…
## Zusammenfassung
| Theme             | Gruppe   | Profil      | Prüfungen | Fehler |
|-------------------|----------|-------------|-----------|--------|
| purple            | core     | standard    | 147       | 0      |
| midnight-gold     | core     | standard    | 147       | 0      |
| glacier           | core     | standard    | 147       | 0      |
| forest            | core     | standard    | 147       | 0      |
| paper             | core     | standard    | 147       | 0      |
| daylight          | core     | standard    | 147       | 0      |
| electric-yellow   | opt-in   | standard    | 147       | 0      |
| laserlloyd        | opt-in   | standard    | 147       | 0      |
| laserlloyd-light  | opt-in   | standard    | 147       | 0      |
| night-red         | opt-in   | night       | 171       | 0      |

Unterstützte Browser: aktuelle Versionen von Chrome, Edge, Firefox und Safari (2024 oder neuer). Die Implementierung nutzt :has(), color-mix() sowie die Popover-API; ältere Browser behalten zwar die Farben bei, doch einige Komponentenzustände sowie Menüs funktionieren dort nicht mehr korrekt.

Verwandte Projekte: ChatForge: ein lokaler NPU-basierter KI-Assistent für den Copilot Key · StudioForge: ein GPU-exklusiver LLM-Server · DisPatch: selbstgehosteter KI-Chat · Mein lokales KI-Agenten-System · Wie man einen LLM dazu bringt, ein beliebiges Projekt an das eigene System anzupassen

Downloads

Kostenlos für die private Nutzung. Wenn es dir einen Nachmittag erspart, ist der Kaffee-Button gleich in der Nähe.


← Mehr KI & lokale LLMs