GenerateBlocks V2 Layout Builder
Build professional WordPress layouts with GenerateBlocks V2: four core blocks,
the Query/Looper family for dynamic content, dynamic tags for data binding,
and GB Pro for CSS Mode, global styles, interactive components, forms, and
conditions.
Read first — routing
This file holds only the non-negotiables. The depth lives in references/:
references/_index.md — task router. Tells you which files to load.
references/recovery-rules.md — every known cause of "Attempt
Recovery" errors with the exact fix. Read on every task. Skip it and
you will produce broken markup.
- The task-specific reference(s) from the router — query loops, dynamic
tags, ACF, animations, conditions, forms, template authoring, Pro blocks.
For styling work, also read:
references/css-mode.md when CSS Mode, raw CSS, nested selectors,
Global Styles, or the styles/css relationship matters.
references/responsive.md for any breakpoint, media query, container
query, or responsive composition.
references/design-quality.md whenever the skill invents or materially
changes a visual direction.
When the task is to put the markup on a real site rather than hand it over,
read references/mcp-publishing.md — MCP servers and REST writes have
their own silent failure modes and a 200 response proves nothing.
If the task involves dynamic data at all, references/dynamic-tags.md is
mandatory — the tag syntax is precise and wrong forms fail silently.
The meta-rule (read this twice)
The WordPress block editor validates blocks by re-serializing and
string-comparing against the markup you pasted. Any deviation — even
semantically-equivalent JSON or HTML — is treated as corruption and
triggers "Attempt Recovery".
Emit what the editor emits, not what you think is correct. That means the
canonical JSON key order, the five string substitutions
(--→\u002d\u002d, <→\u003c, >→\u003e, &→\u0026,
\"→\u0022), and the exact class lists. Compile new css
deterministically from styles so later editor saves remain stable, but do not
misdiagnose harmless formatting in an existing CSS cache as a recovery cause.
Details: recovery-rules.md and css-mode.md.
The blocks
| Block |
Class pattern |
Use for |
generateblocks/element |
gb-element-{id} gb-element |
Containers: div, section, article, header, footer, nav, main, figure, a, ul, ol, li, dl, dt, dd |
generateblocks/text |
gb-text-{id} gb-text |
Text: p, span, div, h1–h6, a, button, figcaption, li |
generateblocks/media |
gb-media-{id} gb-media |
Images (img only). Static AND dynamic loop images |
generateblocks/shape |
gb-shape-{id} gb-shape |
Inline SVG icons/shapes |
generateblocks/query + looper + loop-item (+ query-no-results, query-page-numbers) |
gb-query-{id} etc. |
All dynamic post lists — query-block.md |
GB Pro adds 27 more (accordion, tabs, carousel, navigation, site-header,
forms) — gb-pro.md has the map.
Use core blocks for specialized content: core/image (captions),
core/list, core/table, core/video, core/embed, core/paragraph
(emoji). Full table: block-types.md §5.
The ten commandments
Before serialization, apply these 2 default presentation rules:
- Do not invent decorative eyebrows. Start with the heading unless the
nearest project design system explicitly requires a useful category, status,
or navigation label. Repeated tiny uppercase pretitles are not hierarchy.
- Never use zero-padded numbers. Use
1, 2, and 3, never 01, 02, or
03, in visible copy, step labels, section numbering, filenames, CSS classes, or
newly generated IDs. Preserve exact fixed-format external data only, such as ISO
dates, versions, timestamps, URLs, code samples, or third-party IDs.
- Canonical attribute order per block (block.json declaration order;
className last). Text block puts content 3rd. Pro blocks differ —
check pro-interactive.md before emitting Pro JSON.
- The five JSON substitutions on every string value in block comments.
Inline HTML
style="" in the body is NOT JSON — literal characters there.
- Class lists follow the measured target. For a new element block, prefer
Option A:
"className":"gb-element", rendered as
class="gb-element-{id} gb-element". Text/media/shape commonly omit
className and render base-first. Preserve an existing block's convention;
never normalize it during an unrelated edit.
htmlAttributes is a plain object, never an array. Absolute URLs in
href.
styles is the editable source; css is its compiled cache. Put base
declarations, nested selectors, transitions, and supported at-rules in
styles, then mirror the compiled result in css. CSS Mode supports one
selector level plus @media, @supports, and @container. A selector in
css without an equivalent styles branch is durability debt because an
editor save can remove it. Details: css-mode.md.
- Links: element
<a> wrapping a text span child. Text <a> strips
its href; element <a> with raw text triggers recovery. Inline links go
inside a text block's rich-text content.
- Dynamic tags:
{{tag option:value|option2:value}} — space after the
tag name, pipes between options, no quotes ever. {{post_permalink}},
{{featured_image size:large}}, {{post_meta key:field}},
{{term_list tax:category}}. Wrong tags save fine and render as literal
text — worse than recovery. dynamic-tags.md is law.
- No HTML comments other than
<!-- wp:... --> delimiters. Compact
nesting — closing comment adjacent to closing tag.
- Dynamic loop images use
generateblocks/media (+ tag in src);
static captioned images use core/image.
- Responsive: use the installed build's exact at-rule keys. In 2.4.1 the
native defaults are
@media (max-width:1024px) for Tablet & Mobile and
@media (max-width:767px) for Mobile. Pro allows custom queries. Preserve
existing custom 768px rules; do not silently rewrite their boundary.
Keep at-rules in styles and mirror them in css.
Output requirements
- Always write generated blocks to a file (
{section-name}.html), never
inline in chat — block code breaks chat formatting and truncates.
- Run
scripts/preflight.py <file> before delivering. It executes the
recovery-rules.md §7 checklist as assertions and catches what inspection
misses: no-op escape tables, misordered keys, duplicate uniqueIds, stray
CSS not represented in styles, mixed class-list conventions, thick rounded
surfaces, and invalid clamp() + spacing.
Pass the actual WordPress post ID with --post-id N; new output fails if any
GenerateBlocks ID is outside that post namespace. Add --links N to assert
the internal link count survived a conversion.
- If you are also writing to a live site, follow the round trip in
references/mcp-publishing.md: draft first for the real post ID, read
content.raw, splice, preflight, write, read back, and verify with
scripts/verify_roundtrip.py. Never write to production without a snapshot
or a saved copy of the original content.raw.
- Summarize in chat: what was built, block count, anything needing Pro.
Tooling
| Script |
Use |
scripts/gb_serialize.py |
make_unique_id() for post-scoped IDs, build_css() for styles→css, serialize_attrs() for all five WP substitutions, and ordered() for canonical key order. Import these; don't re-derive them by hand. |
scripts/preflight.py |
Pre-delivery validation. Run with --post-id N for all new output. Exit 0 = clean. |
scripts/verify_roundtrip.py |
Post-write validation. Compare what you sent against the content.raw you read back; names the specific corruption (escape reversal, re-serialization, wpautop, wp_kses) instead of leaving you to diff by hand. |
For anything beyond a few blocks, generate the markup from a script rather
than hand-typing it. Hand-authored escapes and key order drift; a generator plus
preflight does not. See field-notes.md §1.1 for the escape-table no-op trap
that has shipped broken markup more than once.
Before hand-authoring for an EXISTING site
Measure the target's conventions first — plugin behaviour varies by version and
the live page is ground truth for the build actually installed. field-notes.md
§7 has the inspection script. Check versions via authenticated
GET /wp-json/wp/v2/plugins. Treat existing content as evidence, not as a
template: a site can contain editor-authored blocks, imported patterns, and
hand-authored markup with different conventions. Two points matter most:
- preserve the target's established
content/className convention per block
type rather than normalizing it during an unrelated edit;
- the
css attribute is not re-derived during initial block validation, but a
later style edit can recompile it from styles.
Resolve the numeric WordPress post ID before generating any block IDs. For a new
page, product, post, or template, create the record as a draft first, read back its
ID, and only then serialize the blocks. Never substitute the slug, FluentCart
product-detail ID, variation ID, a guessed number, or a literal {post_id} token.
Unique ID convention
Every newly generated ID uses
{section}-{post_id}-{sequence}{optional_suffix}. Examples for WordPress post
1173976: hero-1173976-1, hero-1173976-2a, card-1173976-14.
section is a short lowercase component name such as hero, card, or faq.
post_id is the actual numeric WordPress post ID.
sequence starts at 1 and is never zero-padded.
optional_suffix is a lowercase nesting letter only when useful.
Use make_unique_id('hero', post_id, 1) from scripts/gb_serialize.py instead
of assembling IDs by hand. The {post_id} notation is documentation only and
must never survive into serialized markup. Preserve IDs already stored on an
existing block unless that block is being replaced; do not rename established IDs
solely to conform to this convention.
Design inference (when no design is given)
Read the nearest project design system and inspect the target page before
inventing tokens. Theme variables, existing Global Styles, container width,
type scale, and current breakpoints outrank this skill.
If no project guidance exists, use a quiet baseline: inherit typography,
var(--gb-container-width) for the main rail, a restrained spacing scale,
1px separators, modest radii, and one clear action. Do not infer a site's
current design language from an old example or hard-code a brand palette.
For gauravtiwari.org or gatilab.com, load /gt-design; it owns the current
GT design language. The GenerateBlocks skill supplies delivery mechanics only.
Design quality — no slop
Any design this skill invents or materially changes must pass
references/design-quality.md. If /design-slop is available, load it too;
the nearest project design system still owns brand-specific decisions. The
non-negotiables either way:
- Never a thick border (2px+) on a rounded card, callout, or container
— including one thick side. Separate with whitespace first, then a 1px
hairline, then a subtle background tint. Shadows only for elements that
truly float.
- Cards only for independently interactive or genuinely distinct units.
Whitespace before containers, dividers before cards — no card soup.
- One dominant visual idea per section. Gradients, glows, glass, blur, and
decorative motion stay rare and purposeful — never crutches for weak
hierarchy.
- Consistent, modest radius scale. Not every element a pill.
- Hierarchy comes from type scale, spacing, and alignment — not decoration.
- Real content and real states: no fabricated metrics or testimonials;
survive long titles and empty fields; compose mobile deliberately instead
of just stacking.
- Responsive behavior is part of the design, not a cleanup pass. Verify the
content order, tap targets, overflow, long strings, and at least one awkward
tablet width.
Final check: if the business name could be swapped without the section
changing, it's generic — make it specific before shipping.
Complex layout strategy
For 50+ block sections: map the structure first, build bottom-up, keep one
post-scoped ID family per component, validate each chunk against the checklist
before assembling. See troubleshooting.md for failure recipes.
Examples
Structural block templates live in examples/: basic/ (buttons, containers),
compound/ (cards), layouts/ (hero, query blog grid), svg/ (icons).
Namespace every example with the target post ID before serialization; an example
ID never overrides the convention above.
Golden full sections live at the repo root examples/ (14 section types +
production pages from gauravtiwari.org).
1---2name: generateblocks-layouts-23description: Build and audit WordPress layouts with GenerateBlocks V2, including CSS Mode, responsive at-rules, dynamic data, Pro components, and recovery-safe block serialization. Use for new GB layouts, conversions, repairs, and hand-authored block markup.4---56# GenerateBlocks V2 Layout Builder78Build professional WordPress layouts with GenerateBlocks V2: four core blocks,9the Query/Looper family for dynamic content, dynamic tags for data binding,10and GB Pro for CSS Mode, global styles, interactive components, forms, and11conditions.1213## Read first — routing1415This file holds only the non-negotiables. The depth lives in `references/`:16171. **`references/_index.md`** — task router. Tells you which files to load.182. **`references/recovery-rules.md`** — every known cause of "Attempt19 Recovery" errors with the exact fix. **Read on every task.** Skip it and20 you will produce broken markup.213. The task-specific reference(s) from the router — query loops, dynamic22 tags, ACF, animations, conditions, forms, template authoring, Pro blocks.2324For styling work, also read:2526- **`references/css-mode.md`** when CSS Mode, raw CSS, nested selectors,27 Global Styles, or the `styles`/`css` relationship matters.28- **`references/responsive.md`** for any breakpoint, media query, container29 query, or responsive composition.30- **`references/design-quality.md`** whenever the skill invents or materially31 changes a visual direction.3233When the task is to put the markup on a real site rather than hand it over,34read **`references/mcp-publishing.md`** — MCP servers and REST writes have35their own silent failure modes and a 200 response proves nothing.3637If the task involves dynamic data at all, `references/dynamic-tags.md` is38mandatory — the tag syntax is precise and wrong forms fail silently.3940## The meta-rule (read this twice)4142> The WordPress block editor validates blocks by **re-serializing and43> string-comparing against the markup you pasted**. Any deviation — even44> semantically-equivalent JSON or HTML — is treated as corruption and45> triggers "Attempt Recovery".4647Emit what the editor emits, not what you think is correct. That means the48canonical JSON key order, the five string substitutions49(`--`→`\u002d\u002d`, `<`→`\u003c`, `>`→`\u003e`, `&`→`\u0026`,50`\"`→`\u0022`), and the exact class lists. Compile new `css`51deterministically from `styles` so later editor saves remain stable, but do not52misdiagnose harmless formatting in an existing CSS cache as a recovery cause.53Details: `recovery-rules.md` and `css-mode.md`.5455## The blocks5657| Block | Class pattern | Use for |58|---|---|---|59| `generateblocks/element` | `gb-element-{id} gb-element` | Containers: div, section, article, header, footer, nav, main, figure, a, ul, ol, li, dl, dt, dd |60| `generateblocks/text` | `gb-text-{id} gb-text` | Text: p, span, div, h1–h6, a, button, figcaption, li |61| `generateblocks/media` | `gb-media-{id} gb-media` | Images (img only). Static AND dynamic loop images |62| `generateblocks/shape` | `gb-shape-{id} gb-shape` | Inline SVG icons/shapes |63| `generateblocks/query` + `looper` + `loop-item` (+ `query-no-results`, `query-page-numbers`) | `gb-query-{id}` etc. | All dynamic post lists — `query-block.md` |6465GB Pro adds 27 more (accordion, tabs, carousel, navigation, site-header,66forms) — `gb-pro.md` has the map.6768Use core blocks for specialized content: `core/image` (captions),69`core/list`, `core/table`, `core/video`, `core/embed`, `core/paragraph`70(emoji). Full table: `block-types.md` §5.7172## The ten commandments7374Before serialization, apply these 2 default presentation rules:7576- **Do not invent decorative eyebrows.** Start with the heading unless the77 nearest project design system explicitly requires a useful category, status,78 or navigation label. Repeated tiny uppercase pretitles are not hierarchy.79- **Never use zero-padded numbers.** Use `1`, `2`, and `3`, never `01`, `02`, or80 `03`, in visible copy, step labels, section numbering, filenames, CSS classes, or81 newly generated IDs. Preserve exact fixed-format external data only, such as ISO82 dates, versions, timestamps, URLs, code samples, or third-party IDs.83841. **Canonical attribute order per block** (block.json declaration order;85 `className` last). Text block puts `content` 3rd. Pro blocks differ —86 check `pro-interactive.md` before emitting Pro JSON.872. **The five JSON substitutions** on every string value in block comments.88 Inline HTML `style=""` in the body is NOT JSON — literal characters there.893. **Class lists follow the measured target.** For a new element block, prefer90 Option A: `"className":"gb-element"`, rendered as91 `class="gb-element-{id} gb-element"`. Text/media/shape commonly omit92 `className` and render base-first. Preserve an existing block's convention;93 never normalize it during an unrelated edit.944. **`htmlAttributes` is a plain object**, never an array. Absolute URLs in95 `href`.965. **`styles` is the editable source; `css` is its compiled cache.** Put base97 declarations, nested selectors, transitions, and supported at-rules in98 `styles`, then mirror the compiled result in `css`. CSS Mode supports one99 selector level plus `@media`, `@supports`, and `@container`. A selector in100 `css` without an equivalent `styles` branch is durability debt because an101 editor save can remove it. Details: `css-mode.md`.1026. **Links**: element `<a>` wrapping a text `span` child. Text `<a>` strips103 its href; element `<a>` with raw text triggers recovery. Inline links go104 inside a text block's rich-text content.1057. **Dynamic tags**: `{{tag option:value|option2:value}}` — space after the106 tag name, pipes between options, no quotes ever. `{{post_permalink}}`,107 `{{featured_image size:large}}`, `{{post_meta key:field}}`,108 `{{term_list tax:category}}`. Wrong tags save fine and render as literal109 text — worse than recovery. `dynamic-tags.md` is law.1108. **No HTML comments** other than `<!-- wp:... -->` delimiters. Compact111 nesting — closing comment adjacent to closing tag.1129. **Dynamic loop images** use `generateblocks/media` (+ tag in `src`);113 static captioned images use `core/image`.11410. **Responsive**: use the installed build's exact at-rule keys. In 2.4.1 the115 native defaults are `@media (max-width:1024px)` for Tablet & Mobile and116 `@media (max-width:767px)` for Mobile. Pro allows custom queries. Preserve117 existing custom `768px` rules; do not silently rewrite their boundary.118 Keep at-rules in `styles` and mirror them in `css`.119120## Output requirements121122- **Always write generated blocks to a file** (`{section-name}.html`), never123 inline in chat — block code breaks chat formatting and truncates.124- **Run `scripts/preflight.py <file>` before delivering.** It executes the125 `recovery-rules.md` §7 checklist as assertions and catches what inspection126 misses: no-op escape tables, misordered keys, duplicate uniqueIds, stray127 CSS not represented in `styles`, mixed class-list conventions, thick rounded128 surfaces, and invalid `clamp()` `+` spacing.129 Pass the actual WordPress post ID with `--post-id N`; new output fails if any130 GenerateBlocks ID is outside that post namespace. Add `--links N` to assert131 the internal link count survived a conversion.132- **If you are also writing to a live site**, follow the round trip in133 `references/mcp-publishing.md`: draft first for the real post ID, read134 `content.raw`, splice, preflight, write, read back, and verify with135 `scripts/verify_roundtrip.py`. Never write to production without a snapshot136 or a saved copy of the original `content.raw`.137- Summarize in chat: what was built, block count, anything needing Pro.138139## Tooling140141| Script | Use |142|---|---|143| `scripts/gb_serialize.py` | `make_unique_id()` for post-scoped IDs, `build_css()` for `styles`→`css`, `serialize_attrs()` for all five WP substitutions, and `ordered()` for canonical key order. Import these; don't re-derive them by hand. |144| `scripts/preflight.py` | Pre-delivery validation. Run with `--post-id N` for all new output. Exit 0 = clean. |145| `scripts/verify_roundtrip.py` | Post-write validation. Compare what you sent against the `content.raw` you read back; names the specific corruption (escape reversal, re-serialization, `wpautop`, `wp_kses`) instead of leaving you to diff by hand. |146147For anything beyond a few blocks, **generate the markup from a script** rather148than hand-typing it. Hand-authored escapes and key order drift; a generator plus149preflight does not. See `field-notes.md` §1.1 for the escape-table no-op trap150that has shipped broken markup more than once.151152## Before hand-authoring for an EXISTING site153154Measure the target's conventions first — plugin behaviour varies by version and155the live page is ground truth for the build actually installed. `field-notes.md`156§7 has the inspection script. Check versions via authenticated157`GET /wp-json/wp/v2/plugins`. Treat existing content as evidence, not as a158template: a site can contain editor-authored blocks, imported patterns, and159hand-authored markup with different conventions. Two points matter most:160161- preserve the target's established `content`/`className` convention per block162 type rather than normalizing it during an unrelated edit;163- the `css` attribute is not re-derived during initial block validation, but a164 later style edit can recompile it from `styles`.165166Resolve the numeric WordPress post ID before generating any block IDs. For a new167page, product, post, or template, create the record as a draft first, read back its168ID, and only then serialize the blocks. Never substitute the slug, FluentCart169product-detail ID, variation ID, a guessed number, or a literal `{post_id}` token.170171## Unique ID convention172173Every newly generated ID uses174`{section}-{post_id}-{sequence}{optional_suffix}`. Examples for WordPress post175`1173976`: `hero-1173976-1`, `hero-1173976-2a`, `card-1173976-14`.176177- `section` is a short lowercase component name such as `hero`, `card`, or `faq`.178- `post_id` is the actual numeric WordPress post ID.179- `sequence` starts at `1` and is never zero-padded.180- `optional_suffix` is a lowercase nesting letter only when useful.181182Use `make_unique_id('hero', post_id, 1)` from `scripts/gb_serialize.py` instead183of assembling IDs by hand. The `{post_id}` notation is documentation only and184must never survive into serialized markup. Preserve IDs already stored on an185existing block unless that block is being replaced; do not rename established IDs186solely to conform to this convention.187188## Design inference (when no design is given)189190Read the nearest project design system and inspect the target page before191inventing tokens. Theme variables, existing Global Styles, container width,192type scale, and current breakpoints outrank this skill.193194If no project guidance exists, use a quiet baseline: inherit typography,195`var(--gb-container-width)` for the main rail, a restrained spacing scale,1961px separators, modest radii, and one clear action. Do not infer a site's197current design language from an old example or hard-code a brand palette.198199For `gauravtiwari.org` or `gatilab.com`, load `/gt-design`; it owns the current200GT design language. The GenerateBlocks skill supplies delivery mechanics only.201202## Design quality — no slop203204Any design this skill **invents** or materially changes must pass205`references/design-quality.md`. If `/design-slop` is available, load it too;206the nearest project design system still owns brand-specific decisions. The207non-negotiables either way:208209- **Never a thick border (2px+) on a rounded card, callout, or container**210 — including one thick side. Separate with whitespace first, then a 1px211 hairline, then a subtle background tint. Shadows only for elements that212 truly float.213- Cards only for independently interactive or genuinely distinct units.214 Whitespace before containers, dividers before cards — no card soup.215- One dominant visual idea per section. Gradients, glows, glass, blur, and216 decorative motion stay rare and purposeful — never crutches for weak217 hierarchy.218- Consistent, modest radius scale. Not every element a pill.219- Hierarchy comes from type scale, spacing, and alignment — not decoration.220- Real content and real states: no fabricated metrics or testimonials;221 survive long titles and empty fields; compose mobile deliberately instead222 of just stacking.223- Responsive behavior is part of the design, not a cleanup pass. Verify the224 content order, tap targets, overflow, long strings, and at least one awkward225 tablet width.226227Final check: if the business name could be swapped without the section228changing, it's generic — make it specific before shipping.229230## Complex layout strategy231232For 50+ block sections: map the structure first, build bottom-up, keep one233post-scoped ID family per component, validate each chunk against the checklist234before assembling. See `troubleshooting.md` for failure recipes.235236## Examples237238Structural block templates live in `examples/`: `basic/` (buttons, containers),239`compound/` (cards), `layouts/` (hero, query blog grid), `svg/` (icons).240Namespace every example with the target post ID before serialization; an example241ID never overrides the convention above.242Golden full sections live at the repo root `examples/` (14 section types +243production pages from gauravtiwari.org).