System projektowy w WordPressie to zestaw tokenów, dozwolonych kontrolek edytora i gotowych do wstawienia układów, które Gutenberg faktycznie egzekwuje. Pliki z Figmy niczego na opublikowanej stronie nie egzekwują. W 2026 roku ten kontrakt tworzą theme.json w wersji 3, katalog /patterns i niewielka liczba własnych bloków. Cała reszta to prototyp albo obiekt w bazie danych, który trzeba traktować jak obiekt w bazie danych.
Na dużych serwisach redakcyjnych ciągle widzimy ten sam błąd. Księga marki żyje w Figmie, CSS w pięciu arkuszach stylów, a edytor nadal oferuje dowolny wybór koloru. Marketing wypuszcza kampanijny hex, który istnieje na jednym landingu. Następna kampania go kopiuje. Po pół roku nikt nie potrafi powiedzieć, która zieleń jest zielenią marki. Gutenberg może temu zapobiec, ale tylko wtedy, gdy wyłączysz te kontrolki i umieścisz paletę w theme.json.
Ten tekst nie namawia do migracji z page buildera. Jeśli wybierasz między Gutenbergiem a Elementorem lub Divi, przeczytaj porównanie page builderów na 2026 rok. Jeśli wybierasz między block theme a klasycznym motywem PHP, zajrzyj do tekstu o motywach klasycznych i block themes. Ten artykuł dotyczy warstwy, która przychodzi po tym wyborze: jak system zachowuje spójność, kiedy redaktorzy codziennie korzystają z insertera.
Jak skonfigurować theme.json w wersji 3 dla systemu projektowego
Żywa specyfikacja to theme.json w wersji 3. Wprowadził ją WordPress 6.6: wpis na WordPress Developer Blog o stylach sekcji podaje, że schemat w wersji 3 działa wyłącznie na WordPressie 6.6 i nowszym albo ze starszym core, na którym działa wtyczka Gutenberg. Starsze pliki z version: 2 nadal się ładują. Nowe ustawienia trafiają do wersji 3. Wersji 4 w tej specyfikacji nie ma, choć sporo zestawień z 2025 roku twierdziło inaczej.
Wskaż w pliku schemat odpowiadający minimalnej wersji WordPressa, którą wspierasz, a nie trunk, chyba że strona zawsze działa z wtyczką Gutenberg:
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"settings": {},
"styles": {}
}settings określa, co wolno robić w edytorze. styles to domyślny wygląd, gdy nikt nie nadpisuje bloku. Mieszanie tych dwóch rzeczy kończy się tym, że zespół przypadkiem wypuszcza ładne ustawienia domyślne, które redaktor może zepsuć jednym kliknięciem.
Na stronie, która ma trzymać się marki, pierwszy blok settings, jaki piszemy, wygląda tak. Zamyka swobodny wybór koloru, rozmiaru czcionki i odstępów, a w zamian daje redaktorowi stałe skale:
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"settings": {
"color": {
"custom": false,
"customDuotone": false,
"customGradient": false,
"defaultPalette": false,
"defaultGradients": false,
"defaultDuotone": false,
"palette": [
{ "slug": "base", "name": "Bazowy", "color": "#ffffff" },
{ "slug": "contrast", "name": "Kontrastowy", "color": "#111111" },
{ "slug": "primary", "name": "Główny", "color": "#0b3d91" },
{ "slug": "accent", "name": "Akcent", "color": "#c2410c" }
]
},
"typography": {
"customFontSize": false,
"dropCap": false,
"fontSizes": [
{ "slug": "small", "name": "Mały", "size": "0.875rem" },
{ "slug": "medium", "name": "Średni", "size": "1rem" },
{ "slug": "large", "name": "Duży", "size": "1.5rem" },
{ "slug": "x-large", "name": "Bardzo duży", "size": "2.25rem" }
]
},
"spacing": {
"customSpacingSize": false,
"defaultSpacingSizes": false,
"spacingSizes": [
{ "slug": "20", "name": "XS", "size": "0.5rem" },
{ "slug": "30", "name": "S", "size": "1rem" },
{ "slug": "40", "name": "M", "size": "1.5rem" },
{ "slug": "50", "name": "L", "size": "2.5rem" },
{ "slug": "60", "name": "XL", "size": "4rem" }
]
}
}
}color.custom: false to dawne add_theme_support( 'disable-custom-colors' ). defaultPalette: false ukrywa szaro-niebieskie próbki z core, więc w wyborze kolorów zostają tylko twoje slugi. To mapowanie opisuje podręcznik Global Settings and Styles. Jeśli te dwie flagi zostaną przy wartościach domyślnych (true), system projektowy pozostaje sugestią, której nikt nie musi przestrzegać.
customSpacingSize: false usuwa pole na dowolną wartość odstępu, a defaultSpacingSizes: false sprawia, że core nie dokłada własnej skali odstępów obok twojej. Oba klucze są wymienione w żywej specyfikacji w settings.spacing, obok spacingSizes i spacingScale.
appearanceTools: true nie służy do blokowania edytora. Żywa specyfikacja wymienia, co ten klucz włącza: obraz tła i jego rozmiar, kolor, promień, styl i szerokość obramowania, kolory linków, nagłówków, przycisków i podpisów, proporcje obrazu, wysokość, minimalną wysokość, minimalną szerokość i szerokość, pozycję sticky, odstęp między blokami, marginesy i dopełnienie oraz interlinię. Włącz go, gdy praca nad układem ma się odbywać w edytorze. Zostaw go wyłączonego albo ustaw pojedyncze klucze, gdy odstępy mają pochodzić wyłącznie z presetów.
Jak Gutenberg zamienia presety z theme.json na zmienne CSS
Każdy slug z palety staje się właściwością --wp--preset--color--{slug} oraz klasami pomocniczymi, takimi jak .has-{slug}-color i .has-{slug}-background-color. Rozmiary czcionek i odstępów mają analogiczne nazwy: --wp--preset--font-size--{slug} i --wp--preset--spacing--{slug}. To nazewnictwo opisuje ten sam podręcznik. Własny CSS w motywie powinien korzystać z tych zmiennych, a nie z drugiego zestawu tokenów w rodzaju --brand-primary, który z czasem się rozjedzie.
Wartości bez własnego typu presetu, na przykład głębokości cieni albo promienie zaokrągleń, którym chcesz nadać nazwy, trafiają do settings.custom. Podręcznik podaje, że każdy klucz w tym miejscu staje się właściwością --wp--custom--{key}, a zagnieżdżone klucze łączy podwójny łącznik. Mały arkusz tokenów dla powyższego przykładu wygląda w wygenerowanym CSS tak:
/* Presety z settings.color.palette i settings.typography.fontSizes */
--wp--preset--color--primary: #0b3d91;
--wp--preset--color--accent: #c2410c;
--wp--preset--font-size--large: 1.5rem;
/* Presety z settings.spacing.spacingSizes */
--wp--preset--spacing--30: 1rem;
--wp--preset--spacing--40: 1.5rem;
/* Z settings.custom: { "radius": { "card": "8px" } } */
--wp--custom--radius--card: 8px;Na tym kończą się tokeny projektowe w Gutenbergu. WordPress nie importuje Tokens Studio. Generuje presety z theme.json. Jeśli zespół projektowy ma już tokeny w JSON, uczciwy proces to krok builda, który zapisuje settings.color.palette (oraz skale typografii i odstępów) do theme.json. Wdrożenie wysyła wtedy jeden plik. Webhook z Figmy, który „wypycha na produkcję” bez tego zapisu, pozostaje pokazem możliwości, z którego nie powstaje działający system.
Jak podzielić theme.json na dużej stronie
Motywy potomne scalają swój theme.json z plikiem motywu nadrzędnego. Warianty stylów żyją jako dodatkowe pliki JSON w /styles. PHP nadal może zmienić drzewo przez filtr wp_theme_json_data_theme, gdy strona w sieci multisite potrzebuje innego koloru głównego bez forka motywu. Te trzy podziały daje core. Kompilowanie dwunastu fragmentów JSON w zadaniu Node jest w porządku, jeśli zespół już utrzymuje takie zadanie. Nie jest to wymagane i nie jest udokumentowane jako funkcja WordPressa.
Gdy zespół wybiera kompilację, struktura zwykle wygląda tak:
theme/
├── theme.json (generowany, commitowany)
├── config/
│ ├── color.json
│ ├── typography.json
│ ├── spacing.json
│ └── custom.json
└── build-theme-json.js (scala config/ w theme.json)Projektanci, programiści i marketing mogą wtedy edytować własne pliki bez konfliktów przy scalaniu jednego dużego dokumentu JSON. Ceną jest to, że skrypt scalający staje się kodem, który ktoś musi utrzymywać, testować i aktualizować przy zmianie schematu.
Jak warianty stylów podmieniają paletę bez nowego CSS
Alternatywna paleta nie wymaga drugiego arkusza stylów. Rozwiązanie z core to wariant stylu: plik JSON w /styles, który na nowo definiuje te same slugi. Właściciel strony wybiera go w Site Editorze w sekcji Style, a każdy blok, który już korzysta ze zmiennych presetów, dostosowuje się sam.
Wariant stylu w /styles/dark.json:
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"title": "Dark",
"settings": {
"color": {
"palette": [
{ "slug": "base", "name": "Bazowy", "color": "#111111" },
{ "slug": "contrast", "name": "Kontrastowy", "color": "#f5f5f5" }
]
}
},
"styles": {
"color": {
"background": "var(--wp--preset--color--base)",
"text": "var(--wp--preset--color--contrast)"
}
}
}Wariant zachowuje nazwy slugów i zmienia tylko ich wartości. Na tej zasadzie wszystko się opiera: bloki zapisują slug, a nie wartość hex. Automatyczne przełączanie trybu jasnego i ciemnego na podstawie prefers-color-scheme nie jest wbudowane w core. To nadal CSS, który piszesz sam.
Od WordPressa 6.6 ten sam folder przyjmuje też warianty obejmujące tylko kolory albo tylko typografię, jak podaje wpis na Developer Blog o wariantach stylów bloków. Dla grupy marek na jednym kodzie daje to czysty podział: wspólne odstępy i układ w głównym theme.json, jeden plik wariantu na paletę każdej marki.
Jak działają style sekcji w theme.json od WordPressa 6.6
Przed wersją 6.6 własny styl bloku, na przykład „Boxed” dla bloku Pullquote, oznaczał klasę CSS i ręcznie pisany CSS. WordPress 6.3 pozwalał w theme.json edytować tylko style bloków zarejestrowane przez core. W czerwcowym wpisie na Developer Blog z 2024 roku Justin Tadlock wyjaśnia, że WordPress 6.6 pozwala w theme.json ostylować dowolny zarejestrowany wariant stylu bloku, w styles.blocks.{block}.variations.{name}, łącznie z zagnieżdżonymi w nim elementami i blokami. Ten sam wpis opisuje style sekcji jako koncepcję wprowadzoną w 6.6: wariant stylu bloku zastosowany do sekcji razem z zagnieżdżonymi elementami i blokami, którym zmienia wygląd.
Styl sekcji można zarejestrować z pliku JSON w /styles (WordPress szuka też w podfolderach, więc /styles/section/ działa). Klucz blockTypes wymienia bloki, których dotyczy:
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"slug": "section-dark",
"title": "Dark section",
"blockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
"background": "var:preset|color|contrast",
"text": "var:preset|color|base"
},
"elements": {
"link": {
"color": { "text": "var:preset|color|accent" }
}
}
}
}Ten sam wariant można zarejestrować w PHP. W 6.6 funkcja register_block_style() przyjmuje jako pierwszy argument tablicę nazw bloków oraz klucz style_data o takiej samej strukturze jak plik JSON:
register_block_style(
array( 'core/group', 'core/columns' ),
array(
'name' => 'section-dark',
'label' => __( 'Dark section', 'themeslug' ),
'style_data' => array(
'color' => array(
'background' => 'var:preset|color|contrast',
'text' => 'var:preset|color|base',
),
),
)
);W systemie projektowym to usuwa najczęstsze źródło rozjazdu: redaktorów, którzy ręcznie dobierają kolor tła i tekstu w każdym bloku Group. Ze stylami sekcji wybierają „Dark section” w panelu stylów, a zestaw kolorów tła, tekstu i linków pochodzi z jednej definicji. Globalny wariant stylu może potem dostroić tę sekcję przez właściwość najwyższego poziomu styles.variations, więc wariant marki zmienia ciemną sekcję razem z całą resztą. Ten sam wpis wskazuje ograniczenie, o którym warto pamiętać: style sekcji najlepiej działają na blokach-kontenerach, takich jak Group, Columns i Cover.
Wzorce motywu a wzorce synchronizowane w WordPressie
Na tym rozróżnieniu projekty najczęściej się parzą.
Wprowadzenie do wzorców w podręczniku motywów mówi wprost: wzorce umieszczone w /patterns nie są synchronizowane. To szablony dla następnego wstawienia. WordPress kopiuje znaczniki bloków do wpisu. Jeśli później zmienisz plik PHP, istniejące strony się nie zmienią. Ten sam podręcznik dodaje, że wzorce synchronizowane można tworzyć i zarządzać nimi wyłącznie z panelu administracyjnego WordPressa.
Wzorce synchronizowane (przed WordPressem 6.3 nazywane blokami wielokrotnego użytku) to wpisy wp_block w bazie danych. Tworzy się je w edytorze. Wszystkie wystąpienia zmieniają się razem. Tych obiektów nie ma w Gicie. Środowisko stagingowe i produkcja potrzebują każde tego samego wiersza wp_block, w przeciwnym razie odtwarzasz je ręcznie.
Ten podział warto stosować świadomie:
| Rodzaj | Gdzie żyje | Aktualizuje istniejące strony | Przenoszenie między środowiskami |
|---|---|---|---|
Wzorzec motywu (/patterns) | motyw, w Gicie | nie | tak, z wdrożeniem |
| Wzorzec synchronizowany | baza danych | tak | tylko jeśli skopiujesz dane wp_block |
| Część szablonu (header/footer) | plik motywu do pierwszej edycji, potem baza | tak, jako część | plik, dopóki ktoś go nie dostosuje |
Sekcje hero, układy case studies i szkielety landingów należą do /patterns. Zastrzeżenie prawne, linijka o cookies albo baner, który dział prawny może przepisać dziś po południu, należą do wzorca synchronizowanego, z udokumentowanym eksportem, żeby staging nie zaskakiwał.
Wzorce motywu rejestruje się, wrzucając do /patterns plik PHP z nagłówkiem, co zaleca rozdział o rejestrowaniu wzorców, albo wywołując register_block_pattern() na init. Jeden wzorzec, jedna metoda. Nie rejestruj tego samego sluga dwa razy.
W praktyce biblioteka wzorców ma dwie warstwy. Małe wzorce sekcji są cegiełkami: hero z nagłówkiem, wstępem, przyciskiem i obrazem, karta usługi z ikoną, tytułem, tekstem i linkiem, opinia klienta ze zdjęciem, cytatem, imieniem i stanowiskiem, baner z wezwaniem do działania. Wzorce całych stron łączą je w typy stron, które marketing powtarza: landing usługi, case study, stronę zespołu, stronę kontaktu. Redaktor wybiera wzorzec całej strony i podmienia przykładowy tekst, więc nowa strona zaczyna się w granicach zasad marki, a nie od pustego płótna.
Wzorce synchronizowane mają sens przy treściach, które muszą zmienić się wszędzie tego samego dnia: informacjach prawnych, linijkach o zgodach, blokach z adresem i telefonem firmy, wezwaniu do działania bieżącej kampanii.
Jak nadpisywanie wzorców i Block Bindings API łączą treść
Wzorzec synchronizowany działał kiedyś na zasadzie wszystko albo nic: albo każde wystąpienie było identyczne, albo odłączałeś je i traciłeś synchronizację. WordPress 6.6 dodał nadpisywanie we wzorcach synchronizowanych. W omówieniu Nicka Diego na Developer Blog karta zachowuje wspólny wygląd, a każde wystąpienie zmienia swój nagłówek, tekst i przycisk. W edytorze otwierasz wzorzec synchronizowany przez „Edit original”, zaznaczasz blok, klikasz „Enable overrides” w panelu „Advanced” inspektora bloku i nadajesz mu unikalną nazwę. Znaczniki bloku zawierają wtedy powiązanie ze źródłem core/pattern-overrides.
Nadpisywanie opiera się na dwóch starszych mechanizmach. Edycja samej treści, wprowadzona w WordPressie 6.1, to templateLock: "contentOnly" na bloku-kontenerze: edytowalne zostają tylko zagnieżdżone teksty i media, a kontrolki ustawień i stylów w inspektorze są wyłączone. Drugi mechanizm to Block Bindings API, dostępne od WordPressa 6.5, które łączy atrybut bloku ze źródłem danych zamiast ze statyczną treścią.
Podręcznik wymienia, które bloki core i które atrybuty domyślnie przyjmują powiązania:
| Blok | Atrybuty, które można powiązać |
|---|---|
| Image | id, url, title, alt, caption |
| Heading, Paragraph | content |
| Button | url, text, linkTarget, rel |
| Navigation Link, Navigation Submenu | url |
| Post Date | datetime |
Wbudowane źródła to core/post-meta (klucz meta musi być zarejestrowany z show_in_rest i nie może zaczynać się od podkreślnika), core/pattern-overrides oraz, od WordPressa 6.9, core/post-data (data, data modyfikacji i link) i core/term-data. Wtyczka może dodać własne źródło przez register_block_bindings_source() na init, przekazując label, opcjonalną tablicę uses_context i get_value_callback. Samo powiązanie siedzi w metadata bloku:
<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"core/post-meta","args":{"key":"product_sku"}}}}} -->
<p></p>
<!-- /wp:paragraph -->W systemie projektowym dzięki temu wzorzec pozostaje wzorcem, a dane pochodzą z ustrukturyzowanych pól. Wzorzec karty produktu może powiązać akapit z SKU z polem meta wpisu, więc redaktor nigdy nie wpisuje go do układu. Dwa ograniczenia z podręcznika mają tu znaczenie. Rejestracja po stronie edytora przez registerBlockBindingsSource() pojawiła się w 6.7, a powiązanej wartości nie da się edytować w edytorze, jeśli źródło nie udostępnia canUserEditValue. Wpis o nadpisywaniu zaznaczał też, według stanu z czerwca 2024 roku, że wzorce synchronizowane są przechowywane wyłącznie w bazie danych i nie da się ich spakować jako plików wzorców w motywie, a pierwsze próby rozwiązania tego są śledzone w zgłoszeniu w repozytorium Gutenberga.
Jak wersjonować wzorce motywu w Gicie
WordPress nie wersjonuje wzorców: nie ma stanów, akceptacji ani automatycznej migracji wstawionych wystąpień. Jest Git na folderze /patterns, a cykl ustala zespół:
- Szkic: nowy wzorzec żyje na osobnej gałęzi.
- Przegląd: dział marki albo dział prawny akceptuje go w pull requeście.
- Opublikowany: zostaje wdrożony i pojawia się w inserterze.
- Wycofany: znika z insertera po usunięciu pliku albo wywołania
register_block_pattern(). Strony, które już go wstawiły, zachowują swoje znaczniki i trzeba je poprawiać po kolei.
Krok czwarty to powód, by zestaw wzorców był krótki. Każdy opublikowany wzorzec zostawia w treści kopie, do których motyw już nie sięga.
Jak zablokować szablony Gutenberga przez templateLock
Paleta z custom: false nadal zawodzi, jeśli szablon strony to pusty blok Group, a inserter oferuje każdy blok core. Dla typów stron, które muszą trzymać się modelu (produkt, lokalizacja, dokumentacja), zablokuj szablon: allowedBlocks na grupie, templateLock: "insert" albo "all" tam, gdzie układu nie wolno przestawiać, i wzorzec jako treść domyślną, żeby redaktor nigdy nie zaczynał od pustego płótna.
Dokumentacja szablonów bloków definiuje te wartości. all blokuje wstawianie, przenoszenie i usuwanie bloków. insert blokuje wstawianie i usuwanie bloków, ale pozwala przenosić istniejące. contentOnly blokuje wszystkie operacje, ukrywa bloki bez treści w widoku listy i nie może zostać nadpisane przez bloki potomne. Blok Group deklaruje templateLock jako atrybut w swoim block.json, więc blokada może siedzieć bezpośrednio w znacznikach szablonu albo wzorca.
Istnieją jeszcze dwa poziomy. Pojedynczy blok może mieć atrybut lock z flagami move i remove, a dokumentacja podaje, że blokada na poziomie bloku ma pierwszeństwo przed templateLock. Własny typ wpisu może zarejestrować w register_post_type() własną tablicę template i template_lock, dzięki czemu każdy nowy produkt startuje z tej samej struktury bloków.
Wewnątrz własnego bloku ta sama blokada dotyczy bloków zagnieżdżonych:
<InnerBlocks
template={ TEMPLATE }
templateLock="all"
allowedBlocks={ [ 'core/heading', 'core/paragraph', 'core/button' ] }
/>Redaktor nadal może zmieniać teksty i obrazy, ale nie może zmieniać kolejności, usuwać ani dodawać bloków poza zdefiniowaną strukturą.
Kiedy budować własny blok Gutenberga z block.json
W tym miejscu własne bloki zaczynają na siebie zarabiać. Heading, Paragraph i Image z core pokrywają większość modułów marketingowych. Tabela porównawcza, która musi zawierać SKU, walutę i datę ostatniej weryfikacji, potrzebuje atrybutów i walidacji w block.json. Takie bloki budujemy na @wordpress/scripts, znaczniki zapisu trzymamy możliwie nudne i nie odtwarzamy page buildera w inspektorze. Jeśli blok jest tylko skórką wokół bloków zagnieżdżonych, lepszy będzie wzorzec.
Folder bloku w repozytorium systemu projektowego wygląda tak:
blocks/
└── product-comparison/
├── block.json
├── edit.js (interfejs w edytorze)
├── save.js (znaczniki na froncie)
├── style.scss (style frontu i edytora)
└── editor.scss (style tylko dla edytora)Dokumentacja metadanych bloku używa w przykładzie "apiVersion": 3. Trzeba wiedzieć, gdzie kończy się walidacja w block.json. Dokumentacja atrybutów mówi, że każda definicja atrybutu zawiera co najmniej type albo enum oraz informację, skąd odczytać wartość. enum ogranicza zapisywaną wartość. Nie ma maxLength, minimum ani maximum, które Gutenberg egzekwowałby za ciebie:
{
"apiVersion": 3,
"name": "wppoland/product-comparison",
"attributes": {
"heading": { "type": "string", "default": "" },
"price": { "type": "number", "default": 0 },
"variant": {
"type": "string",
"enum": [ "primary", "secondary", "accent" ],
"default": "primary"
}
}
}Limity zakresu i długości nakłada się w komponencie edycji albo w walidacji REST przy zapisie:
<RichText
tagName="h3"
value={ attributes.heading }
onChange={ ( heading ) => setAttributes( { heading: heading.slice( 0, 120 ) } ) }
/>Dokumentacja @wordpress/scripts obejmuje resztę narzędzi w ramach jednej zależności. build tworzy paczkę produkcyjną, a start przebudowuje ją przy każdej zmianie. lint-js i lint-style stosują standardy kodowania WordPressa do skryptów i arkuszy stylów. test-e2e uruchamia testy end-to-end w Playwright, a plugin-zip pakuje wtyczkę. Ten sam pakiet wykrywa pliki block.json w katalogu źródłowym i używa ich jako punktów wejścia, więc nowy folder bloku nie wymaga zmian w konfiguracji webpacka.
Jak używać Storybooka dla komponentów UI Gutenberga
Projekt Gutenberg sam dokumentuje swoje komponenty UI w Storybooku. README folderu storybook w repozytorium Gutenberga podaje, że projekt „używa Storybooka do przeglądania komponentów UI rozwijanych w pakietach WordPressa i do pracy nad nimi” (tłumaczenie własne), publikuje wynik pod adresem wordpress.github.io/gutenberg i uruchamia go lokalnie przez npm run storybook:dev z katalogu głównego repozytorium.
Dwie praktyki z tego README dobrze przenoszą się na system projektowy klienta. Każda strona komponentu deklaruje status (recommended, use-with-caution, not-recommended albo unaudited), widoczny na pasku bocznym, więc programiści widzą, na których komponentach można bezpiecznie budować. Do tego repozytorium commituje snapshot manifestu każdego komponentu i jego propsów: pull request, który usuwa opis propsa, nie przechodzi, dopóki ktoś nie potwierdzi tej zmiany.
Storybook nie obejmuje warstwy treści. Wzorce, presety z theme.json i style sekcji renderują się w edytorze bloków, więc wiarygodnym podglądem jest dla nich strona na stagingu, która wstawia każdy wzorzec, edytowana z konta redaktora. Storybook pasuje do części systemu napisanych w React: komponentów edit własnych bloków i wspólnych kontrolek paska bocznego zbudowanych z @wordpress/components, czyli biblioteki, którą dokumentuje publiczny Storybook.
Jak przenieść tokeny z Figmy do theme.json
Nie ma oficjalnej synchronizacji między Figmą a WordPressem. Core nie czyta plików Figmy, a żadna wtyczka do Figmy sama nie zapisuje niczego na produkcyjnej stronie. Da się natomiast zbudować krok builda: tokeny wychodzą z narzędzia projektowego jako JSON, a skrypt zapisuje je do theme.json, który trafia do wdrożenia.
Nazwy na początku prawie nigdy się nie zgadzają, więc to mapowanie jest kodem, który ktoś utrzymuje. Proces, który się sprawdza:
- Projektant zmienia kolor w Figmie.
- Wtyczka do tokenów eksportuje zaktualizowane tokeny jako JSON.
- CI uruchamia skrypt builda, który przepisuje
settings.color.palettewtheme.json. - Testy regresji wizualnej porównują zrzuty ekranu przed zmianą i po niej.
- Człowiek czyta diff
theme.jsoni akceptuje pull request.
Automatyzację zatrzymaj na kroku piątym. Webhook, który wdraża produkcję bez czytania diffu przez kogokolwiek, to pokaz możliwości, z którego nie powstaje działający system. Kolor marki to dokładnie ten rodzaj zmiany, który zasługuje na przegląd przez człowieka.
| Narzędzie | Zadanie | Co nadal piszesz sam |
|---|---|---|
| Tokens Studio for Figma | Eksportuje tokeny do JSON | Mapowanie z tego JSON na settings w theme.json |
| Style Dictionary | Przekształca tokeny między platformami | Własny format wyjściowy dla theme.json |
| GitHub Actions | Uruchamia build i otwiera pull request | Krok przeglądu przed scaleniem |
| Playwright | Porównanie wizualne | Ścieżki i stany, które są zapisywane na zrzutach |
Dokumentacja może powstać niemal za darmo z materiałów, które już istnieją: strony w serwisie, która wstawia każdy wzorzec z biblioteki, historii Gita dla /patterns i theme.json jako dziennika zmian oraz zrzutów z testów wizualnych jako zapisu stanu przed zmianą i po niej.
Jak sprawdzać dostępność w systemie projektowym WordPressa
WordPress nie zrobi za ciebie żadnej z tych rzeczy. To kontrole, które budujesz wokół motywu.
Paleta to krótka lista wartości hex w pliku JSON, więc kontrast da się sprawdzić w buildzie. Test przechodzi przez dozwolone pary tekstu i tła, oblicza współczynnik WCAG i przerywa build, gdy para spada poniżej 4.5:1 dla zwykłego tekstu. Wadliwą kombinację nazywa slugiem, a nie wartością hex, więc poprawka trafia do theme.json. Edytor bloków już ostrzega w inspektorze, gdy wybrane połączenie kolorów ma niski kontrast, ale to ostrzeżenie nie blokuje publikacji. Pomagają tu style sekcji: gdy para tła i tekstu jest zdefiniowana raz w stylu sekcji, testuje się ją raz.
W CI uruchom axe-core na głównych szablonach i każdym opublikowanym wariancie stylu, a do wzorców z elementami interaktywnymi dodaj testy nawigacji klawiaturą. Pamiętaj o ograniczeniu: narzędzia automatyczne wyłapują tylko część kryteriów WCAG. Reszta to nadal ręczny przegląd z klawiaturą i czytnikiem ekranu.
Jak zasoby bloków ładują się na żądanie w block theme
Źle zbudowany system projektowy może być wolniejszy niż strona kodowana ręcznie, bo każdy wzorzec ciągnie za sobą swój CSS. Core pomaga, jeśli mu na to pozwolisz. W _add_default_theme_supports(), wywoływanej dla block themes, WordPress dodaje zarówno should_load_separate_core_block_assets, jak i should_load_block_assets_on_demand jako filtry __return_true (zobacz wp-includes/theme.php w wordpress-develop). Docblock w script-loader.php opisuje efekt: zasoby bloku ładują się tylko wtedy, gdy blok jest renderowany. Motyw klasyczny włącza to tak:
add_filter( 'should_load_separate_core_block_assets', '__return_true' );Strona bez galerii nie ładuje wtedy CSS galerii. Dla własnych bloków wynika z tego praktyczna zasada: deklaruj style, editorStyle, viewScript albo viewScriptModule w block.json, zamiast globalnie dołączać pliki z functions.php, żeby WordPress mógł je ładować tylko tam, gdzie blok się pojawia. WordPress nie generuje natomiast critical CSS ani nie usuwa nieużywanych reguł. To nadal zadanie twojego builda albo warstwy cache.
Budżety na komponent to decyzja zespołu, a nie pomiar z core, i działają tylko wtedy, gdy ktoś sprawdza je w każdym pull requeście. Najtańszy zysk to często brak skryptu w ogóle: akordeon FAQ zbudowany na bloku Details generuje <details> i <summary>, które otwierają się i zamykają bez JavaScriptu i działają z klawiaturą.
Lista kontrolna skalowalnego systemu projektowego w WordPressie
Przy pracach programistycznych w WordPressie kolejność jest za każdym razem ta sama:
- Tokeny w
theme.jsonw wersji 3, zablokowany wybór kolorów, ukryta paleta z core. - Style sekcji dla par tła i tekstu, żeby redaktorzy przestali ręcznie kolorować bloki Group.
- Krótki zestaw wzorców w
/patternsdla układów, które marketing faktycznie powtarza. - Jeden lub dwa wzorce synchronizowane dla tekstów, za które odpowiada dział prawny, eksportowane razem z synchronizacją treści, nigdy zostawione z myślą, że odtworzy się je na produkcji.
- Własne bloki dopiero wtedy, gdy wzorzec na blokach core nie poradził sobie z realnym ograniczeniem atrybutu.
- Przegląd w Site Editorze z konta redaktora, a nie administratora, bo administrator nadal widzi narzędzia, które według ciebie były ukryte.
Jeśli front korzysta już z CSS opartego na klasach narzędziowych, zostaw theme.json jako źródło tokenów i mapuj slugi na ten CSS. Ten podział dla Tailwinda opisaliśmy w tekście o wykorzystaniu Tailwind CSS w tworzeniu stron na WordPressie. Gutenbergowi jest obojętne, który framework CSS korzysta z --wp--preset--color--primary. Zależy mu na tym, żeby edytor i front używały tego samego sluga.
System działa, gdy nowy landing to wstawienie wzorca, wybór kolorów ma osiem próbek, a prośba o „tylko ten jeden pomarańczowy” kończy się pull requestem do theme.json, a nie wartością hex w bloku Group.
Planujesz system projektowy na WordPressie? Napisz do nas.






