Zurück zum Blog
Design Engineering · Essay

Tokens sagen einem Modell, was existiert — nicht, was erlaubt ist

Simon Doba·14. August 2026·8 Min. Lesezeit

Dokumentation für Design Systems ist für Menschen geschrieben. „Hier ist ein Button, er hat sechs Varianten." Ein Mensch liest das, schaut sich die Beispiele an und schließt den Rest aus Geschmack und Kontext.

Gib dieselbe Dokumentation einem Modell, und du bekommst plausiblen Schrott. Nicht weil es nicht lesen könnte, sondern weil nirgends steht, wann man wozu greift. Es nimmt die Variante, die zum Satz passt, den man ihm gegeben hat.

Also habe ich die ersten drei Augusttage an der Schicht gebaut, die das beantwortet. Interessant daran ist nicht, was entstanden ist. Interessant ist, dass mein eigenes Eval den ersten echten Fehler darin gefunden hat, und der Fehler war meiner.

Drei Schichten, nicht eine

Das System hat 1.040 Design-Tokens: 250 Primitives, 600 Foundations, 190 semantische. Das klingt nach viel Führung und ist fast keine, weil Tokens nur aufzählen.

  • Tokens sagen, welche Werte existieren. bg.intent.negative.strong ist etwas, das es gibt und das du benutzen darfst.
  • Regeln sagen, welche Kombinationen bedeutungsvoll sind. Ein Generator zieht sich bg.intent.negative.strong allein aus den Tokens. Erst die Regeln sagen ihm, dass fg.base.primary darauf ein Kontrastfehler ist. Davon gibt es 45 — 14 verbotene Paarungen, 7 Flächenregeln, 12 Ebenen-Paarungen, 12 strukturelle Checks.
  • Das Inventory sagt pro Komponente: wofür sie da ist, wofür sie nicht da ist und was man stattdessen nimmt, womit sie sich komponiert und welche A11y-Pflichten daran hängen. Ein Eintrag für jede der 75 Komponenten.

Die zweite Schicht liefert niemand mit. Token-Pipelines sind inzwischen üblich. Eine maschinell prüfbare Aussage, dass zwei erlaubte Werte nicht zusammen auftreten dürfen, ist es nicht, und sie ist die einzige Schicht, die aus „hier sind die Möglichkeiten" ein „hier wäre es falsch" macht.

Dann kann man es bewerten

Regeln, die eine Maschine prüfen kann, sind Regeln, um die man ein Harness bauen kann. Sechs Aufgaben, ein Modell erzeugt zu jeder eine UI-Spec, die Spec wird gegen die eigenen Regeln des Systems geprüft.

Aktuelle Baseline: sechs von sechs bestanden, 98 % im Mittel.

Diese Zahl ist eine Richtung, kein Benchmark. Sie ist ein Mittelwert über sechs Aufgaben gegen eine Modell-Baseline, und das ist dünn genug, dass ich keinen Vergleich darauf aufbauen würde. Wozu sie taugt, ist das Erkennen von Regressionen in den Regeln, und genau das hat sie getan.

Das Eval hat einen Fehler in meinen Regeln gefunden

Zwei der sechs Specs wurden abgelehnt, weil sie einen gleichfarbigen Rahmen auf eine gefüllte Fläche gesetzt hatten.

Ich wollte dem Modell den Fehler nachweisen und stellte fest: Das Modell hatte recht. Die Quelle, aus der ich die Regeln abgeleitet habe, verbietet das nicht. Für starke Füllungen erwähnt sie einen Rahmen schlicht nicht, und ich hatte dieses Schweigen als Verbot transkribiert.

Schweigen ist kein Verbot. Der Satz steht jetzt oben in der Regeldatei, weil er die Fehlerart jedes Menschen beschreibt, der Prosa-Leitlinien in maschinell prüfbare Constraints übersetzt, und ich bin im ersten Anlauf mitten hineingelaufen.

Das hat dieselbe Form wie das, worüber ich letzte Woche geschrieben habe, eine Ebene tiefer. Die Regeln kodieren meine Lesart der Quelle. Nichts im System kann diese Lesart hinterfragen, weil die Regeln der Maßstab sind, an dem alles andere gemessen wird. Es brauchte eine generierte Spec, die mir widerspricht, um das sichtbar zu machen.

Was ein ordentliches Argument dafür ist, überhaupt ein Harness zu haben. Und so herum berichte ich es lieber als über einen Score.

Was abgeleitet wird und was geschrieben

Das durchgehende Arbeitsprinzip: ableiten, nicht schreiben. Was mechanisch herleitbar ist, macht ein Skript.

  • Tokens werden generiert, nie von Hand bearbeitet. Ein Marken-Wechsel fasst genau eine Datei an, weil Komponenten an semantische Namen binden und nie an eine Palettenfarbe, einen Hex-Wert oder eine Arbitrary Utility.
  • Das Inventory-Gerüst wird generiert. Das Urteil — wofür eine Komponente nicht da ist — schreibe ich von Hand, weil dieser Teil sich nicht automatisieren lässt.
  • Die Variantenliste liest die cva-Definitionen der Komponenten selbst statt einer gepflegten Liste. Das ist dieselbe Drift, die mich anderswo regelmäßig erwischt.

Eine Sache gehört deutlich gesagt, weil die Zahlen sonst falsch gelesen werden: 75 Komponenten und rund 26.100 Zeilen über 50 Commits in drei Tagen sind nicht ich beim Tippen. Das ist das Routing-Setup, das ich ohnehin fahre, gerichtet auf eine Domäne, in der die Ausgabe zufällig prüfbar ist. Die Regelschicht ist der Grund, warum das machbar statt leichtsinnig war — eine generierte Komponente, die eine Paarungsregel verletzt, fällt durch, bevor ich sie überhaupt ansehe.

Der CSS-Fallstrick, der alles gekostet hätte

Ein Detail, weil es das Theming beinahe mitgenommen hat und weil es nicht naheliegt.

Eine Custom Property, die var() enthält, wird auf dem deklarierenden Element aufgelöst. --background: var(--color-bg-base-canvas) nur in :root zu deklarieren backt den Hellwert ein und vererbt ihn dann in jeden .dark-Teilbaum. Der Umschalter wäre tot gewesen, während jedes einzelne Token korrekt aussah.

Der Fix ist, in beiden Scopes zu deklarieren. Behalten würde ich die Prüfung, die danach kam: Ein Skript löst jede var()-Kette in hell und in dunkel auf und vergleicht sie. 334 aufgelöste Werte identisch, keine Drift. Das ist die Fassung, der ich traue — angesichts dessen, wie viele grüne Checks in dieser Woche nichts bedeutet haben.

Next

Das Harness braucht mehr als sechs Aufgaben und mehr als eine Modell-Baseline, bevor die Zahl etwas bedeutet. Und ich will, dass es an etwas scheitert, das ich nicht selbst hineingelegt habe.

Danach der Teil, den ich am spannendsten finde: messen, wie ein System benutzt wird, statt welche Teile davon importiert werden. Frühes Ergebnis aus einer echten Anwendung — die primäre Button-Variante kommt fünfmal vor, die Outline-Variante 512-mal. Dazu gibt es einen eigenen Post, mit dem Vorbehalt, dass eine Codebase daraus eine Selbstdiagnose macht und keinen Befund über andere.

Falls du ein Design System pflegst: Ist darin je etwas maschinell geprüft worden, das über Typen und Lint hinausgeht? Mich interessiert, ob die Regelschicht überall fehlt oder nur in den Systemen, die ich gelesen habe.

Next.js 16.3, React 19, Tailwind v4.3.3, Base UI 1.6, pnpm und Turborepo. Zahlen gemessen am 5. August 2026: 75 Komponenten, 111 Demos, 7 Patterns, 1.040 Tokens, 45 maschinenlesbare Regeln.

Artikel teilen

Baust du an etwas Ähnlichem?

Ich schreibe hier über Setups, die ich selbst benutze. Wenn du an etwas Vergleichbarem arbeitest, würde mich interessieren, wie dein Workflow aussieht.

Schreib mir

Cookie-Einstellungen

Wir nutzen Cookies für Analyse und Verbesserung unserer Website. Datenschutzerklärung