Kante: ein Designsystem, das eine KI lesen kann
Was muss in einem Designsystem stehen, damit eine KI daraus genau die Komponenten baut, die ich will, und nicht die, die sie für wahrscheinlich hält? Ich habe ein System gebaut und es an echten Durchläufen gemessen.

- Art
- Designsystem mit gemessenen KI-Durchläufen
- Rolle
- Konzept, Tokens, Spezifikationen, Prüfskripte, Referenz und Auswertung
- Zeitraum
- November 2026
- Technik
- Tokens im W3C-Format, Style Dictionary, Tailwind v4, Radix, Claude Code (Opus und Haiku)
Kurzfassung
Eine KI baut eine Oberfläche in Minuten. Ohne Vorgaben baut sie aber den Durchschnitt dessen, was sie kennt, und erfindet jeden Wert neu. Bei einer Marke mit eigener Sprache ist das kein Zeitgewinn, sondern Nacharbeit.
Ich habe Kante gebaut, ein bewusst kantiges System, und dieselbe Aufgabe dreimal von einer frischen KI-Sitzung lösen lassen: ohne System, mit System auf einem großen Modell und mit System auf einem kleinen. Ohne System fand die Prüfung 263 Werte, die an keinem Token hängen. Mit System waren es nach 2 Runden 0, auch auf dem kleinen Modell.
In Zahlen
Das Problem
Ohne System rät die KI, und sie rät ziemlich gut
Der Durchlauf ohne System bekam nur zwei Screenshots der Referenz. Das Ergebnis sieht auf den ersten Blick richtig aus. Das ist die eigentliche Gefahr: Niemand würde es im Review zurückweisen.
Darunter stehen 116 Farbwerte direkt im Code, 28 verschiedene. Kante hat 15. Die Tinte hat das Modell aus dem Bild geschätzt, als #141414 statt #111111, und für fast dieselbe graue Fläche gibt es zwei Werte, die sich um eine Stufe unterscheiden. Ändere ich im System eine Farbe, kommt davon nichts an.
runs/2026-11-11-baseline-r1/components/button.tsx
primary: {
rest: "border-[#8fb31a] bg-[#c8f031] text-[#141414]",
hover: "enabled:hover:bg-[#b6dd22]",
active: "enabled:active:bg-[#a3c81c] enabled:active:border-[#141414]",
hoverStatic: "bg-[#b6dd22]",
activeStatic: "bg-[#a3c81c] border-[#141414]",
},
secondary: {
rest: "border-[#141414] bg-white text-[#141414]",
hover: "enabled:hover:bg-[#ebebe6]",
active: "enabled:active:bg-[#dcdcd5] enabled:active:shadow-[inset_0_0_0_1px_#141414]",
hoverStatic: "bg-[#ebebe6]",
activeStatic: "bg-[#dcdcd5] shadow-[inset_0_0_0_1px_#141414]",
},
danger: {
rest: "border-[#141414] bg-white text-[#c0261c]",
hover: "enabled:hover:bg-[#fbe7e4]",
active: "enabled:active:bg-[#f5d3ce] enabled:active:shadow-[inset_0_0_0_1px_#c0261c]",
hoverStatic: "bg-[#fbe7e4]",
activeStatic: "bg-[#f5d3ce] shadow-[inset_0_0_0_1px_#c0261c]",
},
};Aufbau
Drei Ebenen, und die KI darf nur die mittlere benutzen
Alle Werte stehen als JSON im W3C-Format für Design-Tokens. Daraus erzeugt Style Dictionary CSS-Variablen, Tailwind-Klassen und eine lesbare Doku. Es gibt genau eine Quelle.
Die Basis-Ebene enthält rohe Werte wie ink.900. Die Bedeutungs-Ebene sagt, wofür ein Wert da ist: color.text.default. Die Komponenten-Ebene gibt es nur dort, wo eine Komponente wirklich abweicht. Die KI darf ausschließlich Bedeutungs- und Komponenten-Tokens verwenden. So sucht sie nach Zweck und nicht nach Aussehen.
Ein Token durch alle Ebenen
- Basisbase.color.ink.900#111111
- Bedeutungcolor.text.default#111111Body text, headings and labels on page, raised and sunken surfaces. Also text on status backgrounds.
- Bedeutungcolor.action.secondary.text#111111Label of secondary actions. Destructive secondary actions use text.danger instead.
- Codetext-ds-action-secondary-textreference/components/button.tsx
Token mit Zweck und Grenze
tokens/semantic/color.json
"muted": {
"$value": "{base.color.ink.500}",
"$description": "Secondary text: hints, help text, metadata. Only on page and raised surfaces. Never on sunken surfaces or status backgrounds, the contrast is too low there.",
"$extensions": {
"de.axkl.pairs": [
{
"surface": "color.surface.page",
"min": 4.5
},
{
"surface": "color.surface.raised",
"min": 4.5
}
]
}
},
"inverse": {Spezifikation als Daten
specs/button.json
"states": [
{ "name": "default", "tokens": { "primary.bg": "color.action.primary.bg", "primary.text": "color.action.primary.text", "secondary.bg": "color.action.secondary.bg", "secondary.text": "color.action.secondary.text", "secondary.border": "color.action.secondary.border", "danger.text": "color.text.danger", "radius": "radius.control" } },
{ "name": "hover", "tokens": { "primary.bg": "color.action.primary.bg-hover", "secondary.bg": "color.action.secondary.bg-hover", "duration": "motion.quick" } },
{ "name": "focus", "tokens": { "outline": "color.border.focus" } },
{ "name": "active", "tokens": { "primary.bg": "color.action.primary.bg-hover", "secondary.bg": "color.action.secondary.bg-hover" } },
{ "name": "disabled", "tokens": { "bg": "color.surface.sunken", "text": "color.text.default", "border": "color.border.default" } }
],
"a11y": {
"role": "button",
"keyboard": ["Enter and Space activate", "Tab moves focus"],
"mustMatch": ["button[type]"]
},
"rules": [
"At most one primary button per view.",
"Danger is a secondary button with a text.danger label and the same outline; it never has a red background.",
"An icon-only button needs aria-label.",
"Disabled buttons use the disabled attribute, the disabled tokens and 50% opacity on the whole button.",
"Focus ring: 2px outline in border.focus with 2px offset."
]Harte Regeln in AGENTS.md
AGENTS.md
## Hard rules
1. No colour literals: no hex, rgb(), hsl(), oklch().
2. No px, rem or em values, neither in arbitrary Tailwind values (`h-[13px]`) nor in `style`.
3. No Tailwind palette colours (`bg-gray-100`, `text-blue-600`, `bg-white`, `text-black`).
4. Spacing only with `*-ds-*` utilities; never `p-4`, `gap-3`, `mt-6`.
5. Corners only `rounded-none`. No `rounded`, `rounded-md`, `rounded-full`.
6. No shadows. Elevation comes from borders.
7. Text only with `type-*` utilities; no `text-sm`, `font-bold`, `leading-*`, `tracking-*`.
8. Never reference `--ds-base-*` or `ds-base-*`.
9. Implement exactly the states each spec lists, with the tokens it names.
10. A spec's `rules` override your own taste.
11. No numeric size utilities (`size-5`, `w-10`, `h-6`, `size-4`). Control and icon sizes come from component tokens: `size-ds-checkbox-size`, `w-ds-switch-width`, `h-ds-switch-height`, `size-ds-switch-thumb`, `size-ds-icon-s`. `w-full`, `w-1/2` and `min-h-screen` are fine.
Entscheidungen
Was das System lesbar macht
- Eine Quelle, viele Ausgaben. Tokens stehen einmal als JSON. CSS, Tailwind-Klassen, Typen und Doku werden daraus erzeugt. Eine KI kann nichts lesen, was an zwei Stellen unterschiedlich steht.
- Namen nach Zweck, nicht nach Aussehen. color.text.muted statt grey-500. Wer nach dem Zweck sucht, findet den richtigen Token auch dann, wenn zwei Farben gleich aussehen.
- Grenzen in die Beschreibung. Jeder Token sagt, wo er nicht hingehört, etwa „nie auf eingesenkten Flächen“. Genau diese Sätze verhindern die typischen Fehlgriffe.
- Kontrast als Daten, nicht als Hoffnung. Erlaubte Text- und Flächenpaare stehen am Token. Liegt ein Paar unter WCAG AA, scheitert der Build.
- Fertige Textstile. type-heading-m statt Größe, Gewicht und Zeilenhöhe einzeln. Weniger Freiheitsgrade heißen weniger falsche Kombinationen.
- Regeln, die ein Skript prüfen kann. Jede harte Regel in AGENTS.md hat eine Prüfung. Was sich nicht prüfen lässt, steht in den Spezifikationen und nicht in der Anweisungsdatei.
- Fehler im System beheben, nie im Ergebnis. Wenn eine KI etwas falsch baut, ändere ich das System und lasse sie neu bauen. So wird jede Lücke einmal geschlossen und nicht bei jedem Prompt wieder.
Durchläufe
Gemessen statt behauptet
Jeder Durchlauf ist eine frische KI-Sitzung ohne Vorwissen, in einem eigenen Ordner. Die Aufgabe ist für alle gleich: acht Komponenten in allen Zuständen und ein Einstellungs-Screen daraus. Der Durchlauf mit System bekommt Tokens, Spezifikationen, Prüfskripte und AGENTS.md, aber nie die Referenz.
Gezählt wird per Skript: Werte, die an keinem Token hängen, Kontrastverstöße im gerenderten Ergebnis, fehlende Zustände und fehlende Pflicht-Attribute für Barrierefreiheit. Die Optik beurteile ich selbst.
In der ersten Runde blieben mit System 11 (Opus) und 4 (Haiku) Befunde. Ihre Ursachen lagen im System, nicht in den Modellen.
| Durchlauf | Modell | Runde | Gesamt | Freie Werte | Kontrast | Zustände | Barrierefreiheit |
|---|---|---|---|---|---|---|---|
| ohne System | Opus | 1 | 263 | 262 | 0 | 0 | 1 |
| mit System | Opus | 1 | 11 | 11 | 0 | 0 | 0 |
| mit System, klein | Haiku | 1 | 4 | 4 | 0 | 0 | 0 |
| mit System | Opus | 2 | 0 | 0 | 0 | 0 | 0 |
| mit System, klein | Haiku | 2 | 0 | 0 | 0 | 0 | 0 |
Was die erste Runde im System aufgedeckt hat
01
Befund: Alle Durchläufe, und auch meine Referenz, setzten Checkbox, Switch und Icons mit Zahlen-Klassen wie size-5 oder h-6.
Änderung am System: Komponenten-Tokens für diese Größen und eine neue Prüfregel. Alle Durchläufe der ersten Runde habe ich mit der strengeren Regel neu bewertet.
Grund: Größen waren der einzige Bereich ohne Tokens. Die Spezifikation nannte Pixel als Text, also hat jedes Modell sie selbst übersetzt.
02
Befund: Opus legte den Seitenabstand außerhalb der maximalen Spaltenbreite an. Der Inhalt wurde 64 px breiter.
Änderung am System: Die Screen-Spezifikation sagt jetzt, dass die Spalte zentriert ist und den Abstand einschließt.
Grund: Die Spezifikation ließ beide Lesarten zu.
03
Befund: Die Beschreibung eines Textstils nannte h3, die Karten-Spezifikation verlangte die Ebene nach Gliederung. Beide Modelle lösten den Widerspruch unterschiedlich.
Änderung am System: Eine Regel an einer Stelle: Die Ebene folgt der Gliederung.
Grund: Zwei Quellen im System widersprachen sich.
04
Befund: Haiku mischte im Dialog ein gesteuertes Radix-Element mit einer statischen Vorschau. Die Seite warf einen Fehler beim Laden.
Änderung am System: Die Dialog-Spezifikation legt den Aufbau jetzt verbindlich fest.
Grund: Sie verlangte nur „Radix Dialog“. Das Muster meiner Referenz stand nirgends.

System zum Anfassen
Die Referenz-Komponenten
Diese Komponenten sind die Referenz, gebaut nur aus Bedeutungs-Tokens. Sie lassen sich bedienen, auch per Tastatur.
Profile
Shown to everyone in the workspace.
Enter a full address, like name@example.com.
Preferences
A summary of activity every Monday.
Was ich gelernt habe
- Die KI findet die Lücken. Jede Abweichung in der ersten Runde zeigte auf eine Stelle, an der das System mehrdeutig war oder schwieg. Die Durchläufe sind damit der beste Test für das System selbst.
- Ein kleines Modell reicht, wenn das System trägt. Haiku mit System erreicht dasselbe Ergebnis wie Opus mit System. Das spart in der Praxis Zeit und Geld.
- Der Unterschied ist nicht im Screenshot. Ohne System sieht das Ergebnis fast richtig aus. Wer nur auf Bilder schaut, merkt nicht, dass jeder Wert kopiert statt verknüpft ist.
Grenzen
- Pro Variante gab es einen Durchlauf je Runde. Das zeigt eine Richtung, ist aber keine Statistik.
- Die Prüfregel für Größen habe ich nach der ersten Runde verschärft. Damit die Zahlen vergleichbar bleiben, sind alle Durchläufe mit derselben Regel bewertet.
- Fehler beim Laden der Seite zählt die Prüfung nicht. Ich habe sie für jeden Durchlauf einzeln geprüft und festgehalten.
- Ein Agent hat kurz eine Hilfsdatei im gemeinsamen Elternordner der Durchläufe abgelegt. Er gibt an, dort nichts gelesen zu haben. Überprüfen lässt sich das nicht.
Was ich daraus mitnehme
Ein Designsystem für KI ist kein Styleguide mit mehr Text. Es ist eine Sammlung von Entscheidungen, die als Daten vorliegen und sich prüfen lassen. Dann baut auch ein kleines Modell, was ich meine.
Nächstes Projekt