Design-as-Code

Design-as-Code: tokeny jako standard UI w platformie agentowej

Kiedy ostatnio kłóciłeś się z kimś, czy ten guzik jest #A8482A, czy jednak #A94A2B? Ja swoje odkłóciłem — i dlatego kolory, typografię i odstępy trzymam dziś nie w pliku graficznym, tylko jako dane. To z pozoru drobna zmiana nośnika ma daleko idącą konsekwencję: decyzja wizualna, która jest danymi, daje się wersjonować, walidować i egzekwować jak każdy inny kod. A skoro tak, to można ją powierzyć maszynie do stosowania, zostawiając człowiekowi to, czego maszyna nie udźwignie: osąd.

Ten artykuł rozwija tokeny od zera, a potem stawia tezę dla platformy agentowej (ADP, którą opisujemy od IDP do ADP): design-as-code to warstwa, w której platforma egzekwuje standardy UI maszynowo — a UX zostaje przy człowieku w pętli. Sprawdzimy, czy ten podział jest prawidłowy, pokażemy gdzie się rozmywa, przedstawimy konkurencyjną koncepcję (generative UI) i damy macierz wyboru ścieżki wdrożenia.

Teza

Tokeny czynią deterministyczną warstwę UI (kolor, odstęp, typografia, promień) maszynowo egzekwowalną — agent wybiera z zamkniętego zbioru, a audyt w CI odrzuca odstępstwa. Warstwa osądu (architektura informacji, przepływy, dobór komponentu, intencja dostępności) pozostaje przy człowieku. Granica nie biegnie więc dokładnie między „UI" a „UX", lecz między tym, co deterministyczne, a tym, co wymaga osądu.

Dlaczego tokeny

Token to nazwana wartość — color.link = #A8482A — której używają jednocześnie strona, komponenty i materiały marketingowe. Zmiana w jednym miejscu propaguje się wszędzie. To samo, co Infrastructure-as-Code zrobił z serwerami — zamienił ręcznie strojone, nigdy nie identyczne maszyny w odtwarzalną, audytowalną konfigurację — tokeny robią z decyzjami wizualnymi: przestają być „bo ktoś tak kiedyś kliknął w Figmie”, a stają się reprodukowalnym faktem w repo.

Wartość tokenów rośnie wprost proporcjonalnie do liczby miejsc, w których ta sama decyzja musi być spójna: light/dark, wiele marek, web/iOS/Android, aplikacja i landing. Bez tokenów każde z tych miejsc dryfuje niezależnie. Z tokenami dryf jest wykrywalny i odwracalny.

Anatomia: trzy warstwy tokenów

Dojrzały zbiór tokenów to nie płaska lista, lecz trzy warstwy pośrednictwa — i to właśnie pośrednictwo daje siłę.

  1. Prymitywy (primitive / global) — surowa paleta faktów: --ds-rust-600: #A8482A, --ds-space-2: 8px. Bez znaczenia, sama wartość.
  2. Tokeny semantyczne (alias) — nadają prymitywom rolę: --color-link: var(--ds-rust-600), --space-inset-sm: var(--ds-space-2). To tu mieszka intencja („to jest kolor linku”), nie konkretny hex.
  3. Tokeny komponentu — opcjonalna warstwa najbliżej UI: --button-bg: var(--color-link). Komponent nigdy nie sięga do prymitywu ani do surowej wartości.
// W3C DTCG: prymitywy i alias ($value/$type, alias przez {ścieżka})
{
  "ds": {
    "rust": { "600": { "$value": "#A8482A", "$type": "color" } },
    "space": { "2": { "$value": "8px", "$type": "dimension" } }
  },
  "color": {
    "link": { "$value": "{ds.rust.600}", "$type": "color" }
  },
  "space": {
    "inset-sm": { "$value": "{ds.space.2}", "$type": "dimension" }
  }
}
/* Ta sama hierarchia w CSS — trzy warstwy pośrednictwa */
:root {
  --ds-rust-600: #A8482A;        /* prymityw  */
  --color-link: var(--ds-rust-600);   /* semantyka */
}
.button { color: var(--color-link); } /* komponent */

Pośrednictwo jest tym, co ratuje skórę: gdy marka zmienia odcień, podmieniasz jeden prymityw; gdy dochodzi dark mode czy druga marka, przepinasz warstwę alias — komponenty nie wiedzą o niczym. Płaska lista hexów takiej operacji nie przeżywa.

Standard, nie dialekt: W3C DTCG

Do niedawna każde narzędzie miało własny format tokenów. To się zmieniło: Design Tokens Format Module grupy W3C Design Tokens Community Group osiągnął pierwszą stabilną wersję (2025.10) — wendor-neutralny JSON z polami $value/$type, aliasami, theming/multi-brand i nowoczesnymi przestrzeniami koloru (Display P3, Oklch, CSS Color 4). Trzymanie się standardu, zamiast formatu jednego dostawcy, to dokładnie ta sama zasada, którą stosujemy wobec licencji i suwerenności: unikasz zamknięcia.

Ekosystem narzędziowy zna już ten format. W praktyce sięga się po Style Dictionary (transpilacja jednego źródła do CSS/iOS/Android/Flutter), Tokens Studio (pomost Figma ↔ repo), a do dokumentacji i izolowanego rozwoju komponentów Storybook; całość projektowa może żyć w otwartym Penpot. Wspólny mianownik: tokeny są źródłem, a kod i materiały są generowane — nie odwrotnie.

Tokeny jako guardrails dla agenta

Tu wchodzi platforma agentowa. Gdy interfejs pisze (lub współpisze) model, pojawia się problem, którego nie ma przy człowieku z dobrą pamięcią zespołową. Asystent kodujący nie odpytuje design systemu — on generuje prawdopodobnie wyglądające wartości. W jednej sesji potrafi podjąć 200–300 mikrodecyzji wizualnych (padding, odcień, promień), każda z osobna sensowna, a w sumie niespójna; a następna sesja nie pamięta poprzedniej i zgaduje od nowa (opis problemu i metoda — Hardik Pandya).

Trzy słabości modeli i ich tokenowe przeciwlekarstwa:

  • Fabrykuje wartości → daj zamkniętą warstwę tokenów: agent wybiera z var(--color-link), a nie wymyśla #1D4ED8. Nie ma „złego niebieskiego”, bo jest tylko jeden.
  • Nie ma pamięci między sesjami → daj pliki spec w repo (foundations + komponenty), które model czyta na starcie każdej sesji. Decyzję podjął człowiek raz; model ją odczytuje.
  • Nie czyta intencji ze źródłaaudyt w CI: skrypt skanuje CSS, a każda surowa wartość to błąd ze wskazaniem właściwego tokenu i exit 1. Czego nie da się scalić, tego nie ma.
# Bramka tokenowa w CI: zero surowych wartości w UI
$ npm run token-audit
src/components/Nav.css
 L42: zakodowany #1868DB → użyj var(--color-link)
 L78: surowy 12px w padding użyj var(--space-inset-sm)
Errors: 2   # exit 1 → PR nie przechodzi

To jest dokładnie ten sam ruch, co deterministyczny szkielet ADP: nie ufamy modelowi „że będzie ładnie”, tylko zamykamy go w polityce, która jest policy-as-code i bramką w pipeline. Smak człowieka wchodzi raz — do tokenów i specyfikacji — a model stosuje go mechanicznie. Tokeny są więc dla UI tym, czym OPA dla wdrożeń: zamkniętym zbiorem dozwolonych decyzji.

Prymitywy Tokeny semantyczne Komponenty Audyt w CI #A8482A · 8px --color-link var(--…) exit 1 = stop człowiek: smak raz → agent: stosuje mechanicznie, audyt pilnuje
Tokeny jako guardrails: człowiek ustawia warstwę raz, agent wybiera wyłącznie z zamkniętego zbioru, a audyt w CI odrzuca surowe wartości.

Gdzie kończy się automat: weryfikacja tezy

Czy założenie „UI maszynowo, UX przy człowieku” jest prawidłowe? Źródła w większości je potwierdzają — ale z istotną korektą, którą trzeba uczciwie postawić.

Co potwierdza tezę. Praktyka pokazuje, że gdy tylko zamkniesz warstwę tokenów i dodasz audyt, jakość wizualna dziesiątej sesji agenta dorównuje pierwszej — czyli deterministyczna część UI faktycznie się automatyzuje. Po drugiej stronie, UX z udziałem AI jest dziś opisywany jako wzorzec human-in-the-loop: AI proponuje, człowiek zatwierdza lub koryguje, bo to człowiek odpowiada za zaufanie, prowadzenie użytkownika i nadzór (wzorzec HITL w UX). AI ma być współpracownikiem, nie zamiennikiem projektanta.

Gdzie teza wymaga korekty. Linia podziału nie biegnie czysto między „UI” a „UX”. Część UI to wciąż osąd: który komponent użyć (modal czy inline message), jak ułożyć architekturę informacji, jak brzmi mikrokopia, jaka jest intencja dostępności (nie samo aria-, lecz sensowny przepływ dla czytnika ekranu). Tego model nie wyczyta ze źródła — ta wiedza „mieszka w głowach projektantów” i musi zostać spisana albo dostarczona przez człowieka. Dlatego trafniejsza granica brzmi: deterministyczne (tokeny, audyt, stany komponentu) → maszyna; wymagające osądu (IA, przepływy, dobór, kopia, intencja a11y) → człowiek w pętli. Sam zgodny token nie gwarantuje dobrego doświadczenia — gwarantuje tylko spójność.

To rozróżnienie ma też wymiar regulacyjny: nadzór człowieka nad istotnymi decyzjami i ślad audytowy to nie tylko dobra praktyka UX, ale i kierunek, w którym idzie AI Act.

Koncepcja alternatywna: generative UI

Powyższe zakłada statyczny interfejs: tokeny i komponenty są ustalone, a agent wypełnia je w czasie budowy. Istnieje jednak inna szkoła — generative UI (GenUI): interfejs nie jest z góry zaprojektowany, lecz składany przez AI w czasie działania, dopasowany do kontekstu i intencji użytkownika (przegląd GenUI). Zamiast kodować każdy wariant ekranu, projektant ustawia guardrails — system prompt, model intencji i kuratorowany katalog komponentów — w których AT generuje UI na bieżąco.

Co istotne dla naszej tezy: nawet GenUI nie znosi standardów — przesuwa je. Nadal potrzebuje zamkniętego katalogu komponentów i tokenów jako budulca; zmienia się tylko moment składania (runtime zamiast build-time). Spotykane są trzy tryby, o rosnącym ryzyku:

  • Statyczny (parametryczny) — AI wypełnia z góry zaprojektowane sloty danymi. Przewidywalny.
  • Deklaratywny (z rejestru) — AI komponuje UI z zamkniętego rejestru komponentów. Zwykle najlepszy kompromis elastyczność/niezawodność.
  • W pełni generatywny — AI emituje surowy HTML/CSS. Maksymalna elastyczność, maksymalne ryzyko (niespójność, halucynacje komponentów, bezpieczeństwo).

GenUI płaci za elastyczność znanymi kosztami: spójność (każde wygenerowanie może wyglądać inaczej), wydajność (generowanie trwa), bezpieczeństwo (dynamiczny kod) i halucynacje. Dlatego nie jest „następcą” design systemu, lecz innym punktem na tej samej osi — z tym samym fundamentem tokenów pod spodem.

Wybierz ścieżkę wdrożenia

Nie ma jednej słusznej drogi — jest spektrum, a wybór zależy od tolerancji ryzyka, skali i tego, jak bardzo interfejs musi się adaptować do użytkownika. Trzy realne ścieżki:

ŚcieżkaKiedy ma sensRola agentaCzłowiek w pętliGłówne ryzyko
A. Statyczny design system + tokenyWiększość produktów; potrzeba spójności i audytowalnościPisze kod w granicach tokenów; audyt go pilnujeUstala tokeny/spec, projektuje IA i przepływy, recenzujeSztywność; „złota klatka” przy nietypowych potrzebach
B. Deklaratywny GenUI (z rejestru)Interfejsy mocno kontekstowe (asystenci, dashboardy dopasowane do roli)Składa UI z zamkniętego rejestru w runtimeProjektuje rejestr + guardrails, definiuje intencje, nadzorujeNiespójność między wygenerowaniami; wydajność
C. W pełni generatywnyEksperymenty, prototypy, wysoce spersonalizowane niszeEmituje surowy markup w runtimeDefiniuje twarde bariery bezpieczeństwa, waliduje wyjścieHalucynacje, bezpieczeństwo, brak powtarzalności

Reguła kciuka: zacznij od A (tokeny + audyt to fundament, który i tak przyda się w B i C), sięgnij po B, gdy realnie potrzebujesz adaptacji do kontekstu, a C trzymaj za barierą człowieka w pętli i poza ścieżką krytyczną. We wszystkich trzech tokeny pozostają wspólnym mianownikiem — różni się tylko, kiedy i jak swobodnie agent z nich korzysta. Mapuje się to wprost na cztery poziomy agentowego wytwarzania: im wyżej autonomia, tym mocniejsze muszą być guardrails i tym wyraźniejszy punkt, w którym decyzję zatwierdza człowiek.

Pierwszy plik

Niezależnie od ścieżki, start jest ten sam — jeden plik, który staje się źródłem prawdy:

{
  "color": { "link": { "$value": "#A8482A", "$type": "color" } }
}

Stąd generujesz CSS variables, motywy i dokumentację — wszystko z repo, wszystko audytowalne, wszystko gotowe, by agent z tego korzystał, a nie zgadywał.

Podsumowanie

Design-as-code zamienia decyzje wizualne w dane, a tokeny — w trójwarstwowy, standaryzowany (W3C DTCG) zbiór, który platforma agentowa potrafi egzekwować maszynowo: zamknięta warstwa tokenów, pliki spec i audyt w CI sprawiają, że agent stosuje smak człowieka, zamiast go wymyślać. Teza „UI dla maszyny, UX dla człowieka” jest w rdzeniu prawidłowa, ale precyzyjniej brzmi: deterministyczne dla maszyny, wymagające osądu dla człowieka w pętli. Alternatywa — generative UI — nie znosi tego fundamentu, tylko przesuwa moment składania na runtime. Wybór ścieżki (statyczny DS, deklaratywny GenUI, pełna generacja) należy do Ciebie i Twojej tolerancji ryzyka — ale każda z nich stoi na tym samym fundamencie tokenów. Zacznij od jednego pliku tokenów i audytu w CI, a potem sam zdecyduj, jak daleko wpuścisz agenta. Polecam się tym pobawić. :)