Przejdź do głównej zawartości

Pipeline design-to-code z czterema artefaktami prowadzi interfejs użytkownika od intencji do produkcji przez cztery wersjonowane artefakty: kierunek wizualny, prototyp interakcji, kontrakt designu i implementację z dowodami. Każdy artefakt ma imiennego właściciela, który go akceptuje, a ostatni sprawdzają testy stanów, wzorcowe zrzuty ekranu i skany dostępności, a nie czytanie każdej linii.

Poprosiłeś agenta o podsumowanie koszyka, po dziesięciu minutach dostałeś dopracowany ekran, a kolejne dwa tygodnie zeszły na to, czego nikt nie określił: pusty koszyk, odrzuconą kartę, ścieżkę klawiaturą i kolory, których nie ma nigdzie w design systemie. Ta strona jest dla developerów i tech leadów, którzy dostarczają frontend z Claude Code, Codeksem albo Cursorem i chcą, żeby te decyzje zapadały przed kodem, a po nim były sprawdzane automatycznie.

  • Prompt na każdy etap: od trzech naprawdę różnych kierunków wizualnych po review designu oparte wyłącznie na dowodach.
  • Plik kontraktu designu, który przypina komponenty, stany, tokeny i breakpointy do istniejącego design systemu.
  • Wzorzec specyfikacji Playwright, który zamienia macierz stanów z kontraktu w bramki zrzutów ekranu i dostępności.
  • Tabelę akceptacji, która mówi, kto zatwierdza który artefakt, więc agent nigdy nie zatwierdza własnej pracy.
  • Sposoby wyjścia z pięciu typowych awarii tego pipelinu.

Dopasuj koszt artefaktu do ryzyka projektowego. Cztery artefakty z bramkami opłacają się, gdy błędne założenie oznacza przeróbki na kilku ekranach; przy drobnej zmianie są ceremonią.

SytuacjaCo zastosować
Nowy flow dla klienta, kilka stanów, więcej niż jeden breakpointWszystkie cztery artefakty
Nowy ekran złożony wyłącznie z istniejących komponentówPomiń etap 1, zacznij od prototypu
Narzędzie wewnętrzne, dojrzała biblioteka komponentówJeden artefakt akceptacji wizualnej i bramki z kroku 5
Poprawka tekstu lub odstępówZwykła zmiana, aktualizacja wzorcowego zrzutu zatwierdzona w review

Pipeline obejmuje etap Design cyklu życia i przekazuje pracę do planowania. Zakłada, że masz już zaakceptowany intent.md; kontrakt designu zasila potem spec.md i plan.md w łańcuchu artefaktów.

EtapCzytaProdukujeAkceptujeZachowane dowody
1. Kierunek wizualnyintent.md, ograniczenia marki, referencjeDwa lub trzy opisane kierunkiProdukt i designWybrany kierunek, odrzucone z uzasadnieniem
2. Prototyp interakcjiZaakceptowany kierunekPrototyp i macierz stanówProdukt i designStabilny link lub zacommitowany prototyp, macierz stanów
3. Kontrakt designuPrototyp, źródło design systemudesign/<feature>/contract.yamlWłaściciel design systemuWersja kontraktu, ścieżka źródła tokenów
4. ImplementacjaKontrakt, spec.md, plan.mdKod, testy, wzorcowe zrzuty ekranuWłaściciel kodu (code owner)Zielone bramki, raport z review

Trzymaj jeden kanoniczny artefakt na decyzję. Gdy źródło żyje w narzędziu projektowym, linkuj je stabilną wersją i eksportuj ramki potrzebne recenzentom, bo nie każdy recenzent ma licencję w tym narzędziu.

Pipeline działa na zwykłych plikach graficznych, ale dwa serwery MCP usuwają większość ręcznego kopiowania: oficjalny serwer MCP Figmy dostarcza kontekst projektu, a Playwright MCP (npm @playwright/mcp) pozwala agentowi otworzyć działającą aplikację. Oba działają we wszystkich trzech narzędziach; różni się tylko instalacja.

Okno terminala
# Figma: plugin zawiera serwer MCP i skille Figmy
claude plugin install figma@claude-plugins-official
# albo sam serwer, potem /mcp w sesji, żeby się zalogować
claude mcp add --transport http figma https://mcp.figma.com/mcp
# Playwright; --isolated sprawia, że równoległe agenty nie dzielą jednego profilu przeglądarki
claude mcp add playwright -- npx @playwright/mcp@latest --isolated

Wyeksportowane ramki i zrzuty ekranu wskazuj w prompcie ścieżką; Claude Code czyta pliki graficzne bezpośrednio.

Kroki od 1 do 3 tworzą pierwsze trzy artefakty. Kroki od 4 do 6 razem tworzą czwarty: implementację z dowodami.

  1. Wygeneruj istotnie różne kierunki wizualne.

    Proś o alternatywy, które różnią się hierarchią, gęstością albo nawigacją, a nie o trzy warianty kolorystyczne jednego układu. Na tym etapie agent nie pisze kodu produkcyjnego.

    Zapisz wybrany kierunek i po jednym zdaniu o każdej odrzuconej alternatywie w design/<feature>/decisions.md. Powody odrzucenia nie pozwalają, żeby ten sam pomysł wrócił przy implementacji (krok 4).

  2. Opisz zachowanie macierzą stanów, żeby dało się je sprawdzić.

    Buduj prototyp tam, gdzie leży ryzyko: w Figmie, gdy chodzi o zgodność z systemem, jako lokalny sandbox HTML, gdy chodzi o interakcję, albo w samej aplikacji na danych z fixture’ów, gdy potrzebujesz wysokiej wierności. Prototyp to tylko połowa artefaktu; macierz stanów to część, która staje się testami.

    Produkt i design akceptują prototyp, przechodząc przez macierz stanów, a nie oglądając happy path.

  3. Wyodrębnij kontrakt designu ze źródła design systemu.

    Kontrakt wskazuje istniejące tokeny i komponenty zamiast wymyślać nowe. Z podłączonym serwerem MCP Figmy agent czyta zmienne i komponenty z ramki przez get_design_context; bez niego czyta wyeksportowane ramki i twój plik tokenów.

    design/checkout/contract.yaml
    artifact: design-contract
    version: 3
    source: https://www.figma.com/design/FILE_KEY/Checkout?node-id=12-345 # version-pinned link
    tokens_source: src/styles/tokens.css
    components:
    - name: CheckoutSummary
    reuses: [Card, Button, Alert]
    states: [ready, empty, loading, error, card-declined, permission-denied]
    states_doc: design/checkout/states.md
    breakpoints: [375, 1280]
    accessibility: "no serious or critical axe violations; focus order as in states.md"
    new_tokens: [] # any entry needs design-system owner approval
    acceptance_owner: design-system lead

    FILE_KEY to klucz twojego pliku w Figmie. Pusta lista new_tokens to stan domyślny; każdy dodany token zatwierdza właściciel design systemu, zanim zacznie się implementacja.

  4. Najpierw plan, potem implementacja zgodna z kontraktem.

    Przekaż contract.yaml i states.md do kroku planowania, żeby ukształtowały spec.md i plan.md, i przejrzyj plan, zanim powstanie jakikolwiek kod: /plan w Claude Code i Codeksie, Plan Mode w Cursorze. Implementuj na izolowanej gałęzi albo w worktree i każ agentowi napisać testy z kroku 5 na podstawie states.md przed komponentem. Testy muszą umieć wprowadzić prawdziwą aplikację w każdy stan, więc każ agentowi udostępnić fixture’y ze states.md tylko w buildzie testowym, na przykład przez parametr zapytania fixture obsługiwany wyłącznie przy NODE_ENV równym test albo przez mockowanie tras w page.route, i wpisać ten mechanizm do plan.md.

  5. Udowodnij implementację w prawdziwej aplikacji.

    Macierz stanów staje się specyfikacją Playwright: jeden test na stan, uruchamiany dla obu viewportów; każdy sprawdza wzorcowy zrzut ekranu, fokus klawiatury i skan axe (@axe-core/playwright 4.13.0). Viewporty pochodzą z dwóch projektów Playwrighta, więc zadeklaruj je w konfiguracji; bez niej specyfikacja działa w jednym viewporcie i pokrywa połowę states.md:

    playwright.config.ts
    import { defineConfig } from '@playwright/test';
    export default defineConfig({
    testDir: 'e2e',
    use: { baseURL: process.env.BASE_URL ?? 'http://localhost:3000' },
    projects: [
    { name: 'mobile-375', use: { viewport: { width: 375, height: 812 } } },
    { name: 'desktop-1280', use: { viewport: { width: 1280, height: 800 } } },
    ],
    });

    Playwright automatycznie dodaje nazwę projektu do nazwy każdego pliku zrzutu, więc każdy stan ma osobny wzorzec dla każdego viewportu. Ustaw BASE_URL na adres swojego serwera deweloperskiego.

    e2e/checkout-summary.spec.ts
    import { test, expect } from '@playwright/test';
    import AxeBuilder from '@axe-core/playwright';
    // First focusable element per state (accessible name), from the focus
    // order in states.md; null means the state has nothing focusable.
    const firstFocus: Record<string, string | null> = {
    ready: 'Pay now',
    empty: 'Browse products',
    loading: null,
    error: 'Try again',
    'card-declined': 'Use another card',
    'permission-denied': 'Sign in',
    };
    for (const [state, name] of Object.entries(firstFocus)) {
    test(`checkout summary: ${state}`, async ({ page }) => {
    await page.goto(`/checkout?fixture=${state}`);
    const summary = page.getByTestId('checkout-summary');
    await expect(summary).toHaveScreenshot(`summary-${state}.png`);
    if (name !== null) {
    // Tab past the header and skip links until focus enters the summary
    const focused = summary.locator(':focus');
    for (let i = 0; i < 20 && (await focused.count()) === 0; i++) {
    await page.keyboard.press('Tab');
    }
    await expect(focused).toHaveAccessibleName(name); // toHaveAccessibleName: Playwright 1.44+
    }
    const { violations } = await new AxeBuilder({ page })
    .include('[data-testid="checkout-summary"]')
    .analyze();
    expect(violations.filter((v) => v.impact === 'serious' || v.impact === 'critical')).toEqual([]);
    });
    }

    Dodaj bramkę tokenów, żeby żaden surowy kolor nie ominął kontraktu. rg zwraca 1 tylko wtedy, gdy nic nie pasuje, więc bramka przepuszcza wyłącznie kod 1: trafienie (kod 0), błąd rg, np. zła ścieżka (kod 2), albo brak rg (kod 127) oblewają krok CI. Samo ! rg … przepuściłoby dwa ostatnie przypadki. || s=$? sprawia, że niezerowy kod rg nie przerywa kroku przedwcześnie pod bash -e w GitHub Actions:

    Okno terminala
    s=0; rg -n -e '#[0-9a-fA-F]{3,8}\b' -e '\b(rgb|hsl)a?\(' --glob '*.{css,ts,tsx}' src/components/checkout/ || s=$?
    [ "$s" -eq 1 ] || { echo 'raw colour found, or rg failed'; exit 1; }

    Wzorzec łapie wartości szesnastkowe oraz wywołania rgb()/hsl(), ale nie nazwane kolory, takie jak red; na nie dodaj regułę stylelint, na przykład color-named: never. Sporadyczny fałszywy alarm, np. kotwicę #add, usuwasz, przenosząc wartość do tokenu albo zawężając glob.

    Pierwsze uruchomienie tworzy wzorcowe zrzuty. Designer raz porównuje je z prototypem; od tej chwili każda zmiana pikseli oblewa test, dopóki człowiek nie zatwierdzi nowego wzorca.

  6. Przejrzyj wynik w świeżym kontekście.

    Recenzent, który nie budował komponentu, porównuje działającą implementację z zaakceptowanymi artefaktami i zgłasza tylko te niezgodności, które potrafi pokazać. Daj mu uprawnienia tylko do odczytu.

    Zastąp <DEV_URL> adresem własnego serwera deweloperskiego. Przy równoległych worktree domyślny port może należeć do serwera innego agenta.

    Zapisz prompt jako design/checkout/review-prompt.md i uruchom go bez sesji interaktywnej:

    Okno terminala
    claude -p --permission-mode dontAsk \
    --allowedTools "Read Grep Glob mcp__playwright" \
    < design/checkout/review-prompt.md

    Prompt trafia na stdin, bo --allowedTools przyjmuje kilka wartości: prompt umieszczony po tej fladze zostałby odczytany jako kolejna nazwa narzędzia (sprawdzone w Claude Code 2.1.283).

    dontAsk odrzuca każde wywołanie narzędzia, które wymagałoby pytania i nie jest w --allowedTools, więc recenzent może czytać pliki i sterować przeglądarką, ale nie może edytować.

    Możesz też zdefiniować własnego subagenta do review designu, tylko z odczytem, i wywoływać go na koniec każdej sesji implementacyjnej.

Przeglądasz artefakty i bramki, nie diff. Kontrakt i macierz stanów są na tyle krótkie, że człowiek przeczyta je w całości; kod sprawdzają względem nich maszyny.

KontrolaCo dowodziKto za nią odpowiada
Specyfikacja Playwright z macierzy stanówKażdy uzgodniony stan renderuje się w każdym uzgodnionym viewporcieWłaściciel kodu
Wzorcowe zrzuty ekranuNic wizualnego nie zmieniło się bez zgodyDesign (zatwierdza aktualizacje wzorców)
Skan axe, asercje fokusuBrak poważnych i krytycznych naruszeń dostępności; ścieżka klawiaturą działaWłaściciel kodu, a jeśli jest, osoba odpowiedzialna za dostępność
Bramka tokenówŻadnych kolorów spoza źródła tokenówWłaściciel design systemu
Raport z review w świeżym kontekścieNiezgodności z zaakceptowanymi ramkami, każda z dowodemProdukt i design przyjmują albo odrzucają każde zgłoszenie

Utrudnij ciche zmiany wzorców: katalog zrzutów obejmij wpisem w CODEOWNERS należącym do designu, a uruchomienie przez agenta npx playwright test --update-snapshots traktuj jako nieudane zadanie. Ogólniejszą zasadę opisuje strona o ochronie wyroczni przed agentem. Zielony przebieg, raport z review i zatwierdzone wzorce zbierz w pakiecie dowodów do PR.

Agent aktualizuje wzorcowe zrzuty, żeby testy przeszły. Wszystko jest zielone, a UI się rozjechało. Przywróć katalog zrzutów do ostatniego zatwierdzonego commita, uruchom testy ponownie i dodaj opisaną wyżej regułę CODEOWNERS, żeby kolejna aktualizacja wymagała zgody designu.

Kontrakt wymyśla tokeny. Implementacja wprowadza #1f6feb, bo użył go prototyp. Uruchom bramkę tokenów, przypisz każdą surową wartość do najbliższego istniejącego tokenu albo do zatwierdzonego wpisu w new_tokens, a jeśli sam prototyp wyszedł poza design system, przygotuj ponownie kontrakt designu (etap 3).

Ekran zgadza się z jednym zrzutem, ale nie z flow. Happy path wygląda dobrze, a odrzucona karta pokazuje pusty panel. Sprawdź, którego wiersza brakuje w states.md, dodaj fixture i pozwól, żeby czerwony test poprowadził poprawkę. Stan bez fixture’a dla bramek nie istnieje.

Wzorce migają między przebiegami. Fonty, daty albo animacje zmieniają piksele, a zestaw testów staje się szumem, który ludzie uczą się ignorować. Zamroź zegar i dane w fixture’ach, poczekaj na fonty webowe przed zrzutem, a naprawdę dynamiczne obszary zamaskuj opcją mask w toHaveScreenshot. Nie podnoś tolerancji pikseli do poziomu, na którym test niczego już nie wykrywa.

Narzędzie projektowe albo konektor przestaje być dostępny. Zmienia się licencja, kończy się beta albo granica danych blokuje dostawcę. Artefakty w design/<feature>/ nadal niosą każdą decyzję, więc powtarzasz tylko etap zależny od narzędzia, na wyeksportowanych plikach.

  • decisions.md zapisuje wybrany kierunek i powód odrzucenia pozostałych.
  • states.md ma fixture i linię akceptacji dla każdego stanu w każdym viewporcie.
  • contract.yaml wskazuje kanoniczne źródło tokenów i nie zawiera niezatwierdzonych new_tokens.
  • Specyfikacja Playwright pokrywa każdy wiersz states.md i przechodzi w CI.
  • Zmiany wzorców w PR zatwierdził design, a nie wygenerował ich agent.
  • Raport z review w świeżym kontekście nie ma otwartych blockerów.