Oto przepływ pracy, który stał się domyślnym w każdym zespole design-to-code: eksportuj ramkę z Figmy, wklej PNG do Claude lub Cursora, wpisz „zbuduj to" i iteruj od halucynowanego wyniku. Działa wystarczająco dobrze, żeby sprawiać wrażenie produktywności. Nie działa wystarczająco dobrze, żeby z tego wysyłać.

To nie jest problem możliwości modelu. To problem danych wejściowych. Zrzut ekranu to najgorszy możliwy sposób reprezentacji projektu Figmy dla LLM-u — i jest to prawie powszechnie pierwsza rzecz, po którą sięgają zespoły. Pakiet kontekstowy figmascope to strukturalna alternatywa.

Hierarchia znika

Plik Figmy to drzewo. Ramki zawierają grupy auto-layoutu, które zawierają instancje komponentów, które zawierają warstwy tekstu i wypełnień. To drzewo koduje intencję układu: ten wiersz to kontener flex, ta karta to opakowane pudełko, te trzy elementy to rodzeństwo z 16px przerwami między nimi.

Zrzut ekranu spłaszcza to drzewo do siatki pikseli. LLM widzi kształty i kolory. Nie widzi struktury układu — wnioskuje ją. A wnioskowanie jest stratne w obu kierunkach: model może zrekonstruować strukturę wyglądającą poprawnie wizualnie, ale błędną semantycznie (div o stałej szerokości zamiast dziecka flex, pozycjonowanie absolutne zamiast auto-layoutu), albo może zobaczyć strukturalną niejednoznaczność i wybrać jedną arbitralnie.

Z PNG nie możesz powiedzieć, czy poziomy rząd elementów jest zaimplementowany przez display: flex, CSS Grid, niestandardowy HStack czy trzy absolutnie pozycjonowane divy. Są wizualnie identyczne. LLM wybiera jeden. Wybór zmienia się między uruchomieniami.

Semantyka nie przeżywa rasteryzacji

LLM może zobaczyć, że prostokąt z zaokrąglonymi narożnikami zawiera jakiś tekst i ikonę. Czego nie może zobaczyć:

Semantyka w Figmie żyje w drzewie warstw: nazwy komponentów, właściwości wariantów, rodzaje węzłów. Komponent Button/Primary/Large jest jawnie typowany. Na zrzucie ekranu to zaokrąglony prostokąt z cieniem i etykietą. Model zazwyczaj poprawnie zgaduje „to pewnie przycisk" — a następnie zgaduje „to pewnie wariant primary" na podstawie koloru, co może, ale nie musi, odpowiadać faktycznej nazwie w twoim systemie projektowym.

Małe rozbieżności się kumulują. Przycisk ghost wyrenderowany jako outlined. Tooltip wyrenderowany jako wyzwalacz modalu. Stan wyłączony wyrenderowany jako aktywny. Każdy z nich to jeden krok wnioskowania ze zrzutu ekranu od źródła prawdy.

Systemy odstępów nie rozwiązują się do liczb

Spójrz na zrzut ekranu karty z paddingiem. Jaki jest padding? Nie możesz powiedzieć bez mierzenia pikseli, znajomości skali płótna, znajomości rozdzielczości eksportu i zrobienia matematyki. LLM robi matematykę źle — szacuje, zaokrągla i nie ma możliwości wiedzieć, czy twój system odstępów używa siatki bazowej 8px czy 4px czy czegoś niestandardowego.

Więc zgaduje. Generuje padding: 12px gdy projekt mówi 16. Generuje gap: 8px gdy projekt mówi 12. Te liczby wyglądają sensownie w izolacji, ale są błędne — a jeśli twój system projektowy używa tokenów odstępów jak spacing.md czy Spacing/400, LLM w ogóle o nich nie wie. Koduje literały na stałe, które będą dryfować od twojego systemu w momencie jakiejkolwiek zmiany.

LLM nie halucynuje. Robi dokładnie to, co ty byś zrobił mając tylko zrzut ekranu: zgaduje. Zaskakuje cię tylko wtedy, gdy domysły są błędne, bo przez cały czas widziałeś prawidłową odpowiedź w pliku Figmy.

Relacje tokenów znikają

Twój projektant ustawił to tło na #7F5CFE. W Figmie ta wartość hex jest powiązana ze zmienną: color/brand/primary. To powiązanie jest znaczące — oznacza, że kolor uczestniczy w tematyzowaniu, oznacza, że tryb ciemny go zamienia, oznacza, że jeśli kolor marki się zmieni, aktualizujesz jedną zmienną i każda instancja się aktualizuje.

Na zrzucie ekranu: jest fioletowy. LLM generuje background-color: #7F5CFE. Relacja tokenów znika. Twoja baza kodu ma teraz zakodowaną wartość hex, która nigdy nie będzie śledzić twojego systemu projektowego. Pomnóż to przez każdy komponent na ekranie.

To samo dotyczy skal typografii, promieni obramowań i definicji cieni. Każda wartość w dobrze utrzymanym pliku Figmy jest potencjalnie nazwanym tokenem. Każda wartość na zrzucie ekranu to tylko liczba.

Ponowne użycie komponentów jest niewidoczne

Dobrze złożony ekran ponownie używa komponentów. Cztery karty produktów to cztery instancje tego samego komponentu ProductCard. Awatar w nawigacji i awatar w wątku komentarzy to obie instancje Avatar/Medium. To ma znaczenie dla kodu: chcesz jednego komponentu React, nie czterech ręcznie pisanych wariantów, które będą dryfować.

Ze zrzutu ekranu LLM widzi cztery wizualnie podobne prostokąty. Może wygenerować jeden komponent wielokrotnego użytku — albo cztery prawie identyczne bloki JSX, bo nie zauważył, że są takie same. W obrazie nie ma sygnału mówiącego, które jest poprawne.

IR eksportowany przez figmascope niesie componentId na każdym węźle instancji. Agent wie: te cztery węzły to wszystko ProductCard. Generuj raz, renderuj cztery razy z różnymi propsami. To wynik, którego chcesz. To wynik, którego nie możesz uzyskać z pikseli.

Tożsamość ciągów jest tracona

Masz przycisk „Kontynuuj" na trzech różnych ekranach. Czy te trzy instancje to ten sam ciąg, czy projektant napisał je niezależnie? W dobrze ustrukturyzowanym pliku Figmy odwołują się do tego samego klucza ciągu. Oznacza to jeden wpis i18n, jedna zmiana propaguje się wszędzie.

Na trzech zrzutach ekranu: trzy razy LLM generuje zakodowany ciąg. Jeśli budujesz zunifikowaną aplikację, masz teraz trzy ciągi do znalezienia i zastąpienia zamiast jednego do wyszukania. Mała rzecz. Kumuluje się w realnej bazie kodu.

Dlaczego LLM halucynuje: ponownie wyprowadza strukturę za każdym razem

Model nie ma pamięci poprzednich uruchomień. Za każdym razem gdy wklejasz ten sam zrzut ekranu, rekonstruuje strukturę od zera. Rekonstrukcja jest probabilistyczna — co oznacza, że ten sam zrzut ekranu + ten sam prompt + ten sam model może produkować mierzalnie różne wyniki w różnych uruchomieniach. Ten sam projekt, różny kod. Różne nazwy komponentów, różne wzorce className, różne decyzje układu.

To nie jest błąd modelu. To oczekiwane zachowanie modelu probabilistycznego przy niewystarczających ograniczeniach. Zrzut ekranu zapewnia niewystarczające ograniczenia. Model wypełnia luki. Luki są wypełniane różnie za każdym razem.

Możesz częściowo to obejść dłuższymi, bardziej szczegółowymi promptami — „użyj Tailwind, użyj siatki 8px, użyj tych nazw komponentów..." — ale wtedy ręcznie określiłeś strukturę, która powinna być w pliku projektu od samego początku. Wykonujesz pracę ekstrakcji, którą narzędzie powinno robić.

Problem reprodukowalności

Zespoły używające zrzutów ekranu do przekazywania design-to-code napotykają ten sam problem: wynik nie jest reprodukowalny. Dwóch deweloperów, ten sam zrzut ekranu Figmy, niezależnie promtują Claude — dostają różne struktury komponentów, różne wzorce className, różne decyzje zagnieżdżenia. Teraz masz dwie bazy kodu wyglądające tak samo wizualnie, ale architektonicznie niespójne.

To utrudnia code review. Utrudnia refaktoryzację. Sprawia, że audyt zgodności z systemem projektowym jest niemożliwy. Nie możesz robić diffa „co agent wygenerował z tego projektu", jeśli odpowiedź zmienia się przy każdym uruchomieniu.

Kontekst strukturalny naprawia reprodukowalność, bo naprawia dane wejściowe. Deterministyczny pakiet wejściowy — ten sam JSON z tymi samymi ID węzłów, nazwami komponentów, wartościami tokenów i relacjami przestrzennymi — produkuje znacznie bardziej spójny wynik między uruchomieniami, agentami i deweloperami. Nie w pełni deterministyczny: model jest wciąż probabilistyczny. Ale wariancja drastycznie spada, gdy struktura jest określona, a nie wnioskowana.

Co zrzut ekranu daje agentowi vs. co daje IR

Weź kartę produktu: obraz, tytuł, podtytuł, cena, przycisk „Dodaj do koszyka". Oto co każde wejście daje agentowi:

Wejście z zrzutu ekranu: Prostokąt z obrazem na górze, dwie linie tekstu, liczba i przycisk. Kolory są wnioskowane. Padding jest szacowany. Czy to komponent czy jednorazowy jest nieznane. Wariant przycisku jest wnioskowany z koloru. System odstępów jest nieznany.

Wejście IR: Rodzaj węzła FRAME, nazwa ProductCard, ID komponentu łączące z definicją komponentu. Auto-layout z kierunkiem pionowym, 16px gap, 16px poziomy padding, 12px pionowy padding. Węzły potomne: IMAGE (wypełnia szerokość, stała wysokość), TEXT z stringRef.key: "product.title" i stylem typography/heading.sm, TEXT z stringRef.key: "product.subtitle" i stylem typography/body.md, TEXT z wypełnieniem color/price, INSTANCE z Button/Primary/Medium. Wypełnienie tła color/surface.card. Promień obramowania radius/card.

IR daje agentowi specyfikację. Zrzut ekranu daje mu sugestię.

Rama: to jest problem dokumentacji

Rozwiązaliśmy dokładnie ten problem dla kodu źródłowego dekady temu. Nie dajesz agentowi zrzutu ekranu swojej bazy kodu i nie prosisz go o rozumowanie na temat architektury. Dajesz mu kod — strukturalną, parsowalną, semantycznie znaczącą reprezentację. Abstrakcyjne drzewo składni, nie obraz edytora.

Projekty Figmy to dane strukturalne. Mają dobrze zdefiniowaną strukturę drzewa z typowanymi węzłami i nazwanymi wartościami. Figma API w pełni tę strukturę udostępnia. Jedynym powodem, dla którego przepływ pracy ze zrzutami ekranu trwa, jest to, że wyodrębnienie struktury i formatowanie jej jako kontekstu ma tarcie.

Redukcja tego tarcia to właśnie to, co robi figmascope. Wklejasz URL Figmy, eksport uruchamia się w przeglądarce i dostajesz ZIP ze strukturalnym kontekstem: CONTEXT.md, tokens.json, IR per-screen, inwentarz komponentów, manifest ciągów. Wszystko, czego agent potrzebuje, nic nie jest wnioskowane z pikseli.

Zachowaj zrzuty ekranu do wizualnego potwierdzenia — pakiet zawiera 2x PNG dokładnie w tym celu. Używaj struktury do wszystkiego innego. Zobacz to w praktyce: przepływ pracy Cursor, przepływ pracy Claude Code lub przepływ pracy Aider.