بنقرة واحدة
Build layouts using GenerateBlocks V2 elements for WordPress
npx skills add https://github.com/wpgaurav/generateblocks-skills --skill generateblocks-layoutsانسخ والصق هذا الأمر في Claude Code لتثبيت المهارة
Build layouts using GenerateBlocks V2 elements for WordPress
npx skills add https://github.com/wpgaurav/generateblocks-skills --skill generateblocks-layoutsانسخ والصق هذا الأمر في Claude Code لتثبيت المهارة
Convert Elementor layouts to clean GenerateBlocks V2 format, eliminating DIVception
Convert Figma designs to GenerateBlocks V2 format for WordPress
Convert HTML/CSS layouts to GenerateBlocks V2 format with inline styles
| name | generateblocks-layouts |
| version | 2.1.0 |
| description | Build layouts using GenerateBlocks V2 elements for WordPress |
| author | Gaurav Tiwari |
| trigger | ["GenerateBlocks","GB blocks","GB layouts","HTML to GenerateBlocks","convert to GB","WordPress block layout","landing page section","blog grid","related posts","query loop with GenerateBlocks"] |
| tags | ["wordpress","generateblocks","layouts","blocks"] |
| references | ["references/_index.md","references/recovery-rules.md","references/block-types.md","references/query-block.md","references/gb-pro.md","references/css-patterns.md","references/svg-icons.md","references/responsive.md","references/troubleshooting.md"] |
| examples | ["examples/basic/","examples/compound/","examples/layouts/","examples/svg/"] |
Build professional WordPress layouts using GenerateBlocks V2's four core blocks plus the Query / Looper / Loop-Item family for dynamic content.
Before generating any markup, read these in order:
references/_index.md — task router. Tells you which other files to load.references/recovery-rules.md — every known cause of "Attempt Recovery"
errors with the exact fix. This is non-negotiable. Skip it and you will
produce broken markup._index.md.The most common task-specific files:
block-types.mdquery-block.mdgb-pro.mdThe WordPress block editor validates blocks by re-serializing the attributes and string-comparing against the markup you pasted. Any deviation — even semantically-equivalent JSON or HTML — is treated as corruption and triggers "Attempt Recovery".
This is the unifying principle. Every rule in recovery-rules.md exists to
make your output byte-identical to what the editor itself would emit.
That means matching:
block.json declarations-- < > & → \u002d\u002d \u003c \u003e \u0026) on every JSON stringIf you remember nothing else: emit what the editor emits, not what you think is correct.
ALWAYS output generated blocks to a file, never inline in the chat.
{section-name}.html (e.g., hero-section.html, services-grid.html)Why file output?
GenerateBlocks V2 uses four block types:
| Block | Class Pattern | Use For |
|---|---|---|
generateblocks/element | .gb-element-{id} | Containers (div, section, article, header, nav, footer) |
generateblocks/text | .gb-text-{id} | Text content (h1-h6, p, span, a, button) |
generateblocks/media | .gb-media-{id} | Images (static only, no dynamic features) |
generateblocks/shape | .gb-shape-{id} | SVG icons and decorative shapes |
For elements not available in GenerateBlocks or requiring advanced media features, use WordPress Core Blocks:
| Content Type | Use Core Block | Why |
|---|---|---|
| Images with captions | core/image | Built-in caption support |
| Image galleries | core/gallery | Lightbox, columns, captions |
| Videos | core/video | Native video player, controls |
| Embedded media | core/embed | YouTube, Vimeo, Twitter, etc. |
| Audio files | core/audio | Native audio player |
| File downloads | core/file | Download links with filename |
| Tables | core/table | Structured data tables |
| Lists | core/list | Semantic ul/ol with .list class |
| Quotes | core/quote | Blockquote with citation |
| Code blocks | core/code | Preformatted code display |
| Separators | core/separator | Horizontal rules |
| Buttons (grouped) | core/buttons | Multiple button layouts |
| Columns (simple) | core/columns | Quick equal-width layouts |
| Cover images | core/cover | Background images with overlays |
| Dynamic post content | core/post-* | Post title, excerpt, featured image, etc. |
| Query loops | core/query | Dynamic content from posts |
| Emojis | core/paragraph | GenerateBlocks doesn't render emojis properly |
Rule of thumb: Use GenerateBlocks for layout structure and custom styling. Use Core Blocks for specialized content types and media with built-in functionality.
<!-- wp:generateblocks/{type} {json_attributes} -->
<{tag} class="gb-{type} gb-{type}-{uniqueId}">
{content}
</{tag}>
<!-- /wp:generateblocks/{type} -->
Element blocks use "className":"gb-element" (just the base class — the plugin auto-injects the id-class). The rendered HTML class is gb-element-{id} gb-element:
<!-- wp:generateblocks/element {"uniqueId":"card001","tagName":"div","styles":{...},"css":"...","className":"gb-element"} -->
<div class="gb-element-card001 gb-element">...</div>
<!-- /wp:generateblocks/element -->
Every block needs (in this canonical key order, from block.json):
uniqueId — Unique identifier ({section}{number} like hero001, card023)tagName — HTML element type (omitted for shape, which uses html instead)content — (text block only, position 3) the rich text contentstyles — CSS properties as JSON object (camelCase). Supports responsive keys like "@media (max-width:1024px)":{...}css — Generated CSS string (kebab-case, minified, alphabetically sorted)globalClasses — Array of global CSS class slugs (optional)htmlAttributes — Plain object of attribute key-value pairs (for links, IDs, data attributes)align (element), mediaId (media), queryType, paginationType, query, inheritQuery (query), midSize (query-page-numbers), icon, iconLocation, iconOnly (text)className — always last. WordPress core attribute. Should NOT include the auto-injected gb-{type}-{uniqueId} class — the plugin adds that itself.Per-block exceptions:
content is at position 3, BEFORE styles. This is the only block that breaks the standard order.tagName. html is at position 2.queryType, paginationType, query, inheritQuery come after htmlAttributes.See references/recovery-rules.md §3.4 for the verified per-block declaration order.
The plugin auto-injects gb-{type}-{uniqueId} into the rendered HTML class
list whenever styles is non-empty. If you also put it in className, the
rendered HTML has it twice and you trigger recovery on save.
// RIGHT — let the plugin auto-inject
"className":"gb-element"
"className":"gb-element alignfull"
// WRONG — duplicates the id-class
"className":"gb-element-card001 gb-element"
The rendered HTML class list always shows the id-class once (auto-injected
at the front) followed by whatever is in className:
<div class="gb-element-card001 gb-element"> <!-- ✓ -->
<header class="gb-element-hero001 gb-element alignfull"> <!-- ✓ -->
htmlAttributes MUST be a plain object, NOT an array:
// ✅ CORRECT - Plain object
"htmlAttributes": {"href": "https://example.com/page/", "target": "_blank", "id": "section-id"}
// ❌ WRONG - Array of objects (causes block editor recovery errors)
"htmlAttributes": [
{"attribute": "href", "value": "/contact/"},
{"attribute": "target", "value": "_blank"}
]
Use full absolute URLs, not relative paths. The block editor saves links as absolute URLs; relative paths get converted on save, causing a mismatch that triggers block recovery.
// ✅ CORRECT
"htmlAttributes": {"href": "https://gauravtiwari.org/services/web-development/"}
// ❌ WRONG
"htmlAttributes": {"href": "/services/web-development/"}
There are two failure modes to avoid:
generateblocks/text with tagName:"a" strips its href on save. The
href does not survive the round trip. Don't use it for action links.generateblocks/element with tagName:"a" containing raw text triggers
recovery — element blocks expect inner blocks, not text content.The correct pattern: element <a> wrapping a text span child.
<!-- wp:generateblocks/element {"uniqueId":"link1","tagName":"a","styles":{"display":"inline-block","color":"#c0392b"},"css":".gb-element-link1{color:#c0392b;display:inline-block}","htmlAttributes":{"href":"https://example.com/page/?a=1\u0026b=2"},"className":"gb-element"} -->
<a class="gb-element-link1 gb-element" href="https://example.com/page/?a=1&b=2">
<!-- wp:generateblocks/text {"uniqueId":"link2","tagName":"span","content":"Read more →","styles":{},"css":""} -->
<span class="gb-text-link2 gb-text">Read more →</span>
<!-- /wp:generateblocks/text -->
</a>
<!-- /wp:generateblocks/element -->
This works because:
<a> has an inner block child → no "raw text" recoveryhtmlAttributes.href on the element block survives save → href preservedspan, not an a → no href stripping→ in the text — never use a CSS \2192 escape& in the JSON htmlAttributes is escaped as \u0026& in the rendered HTML href is escaped as &className is just "gb-element" (no id-class duplicate) — the plugin
auto-injects gb-element-link1 so the rendered HTML has it onceuniqueId, tagName, styles, css, htmlAttributes, className
(canonical block.json order, with className last)For inline links inside a paragraph, write the <a> directly in the rich text
content of a single generateblocks/text paragraph block — don't wrap each
inline link in its own block.
See references/recovery-rules.md §4 for the full explanation.
Always use both styles AND css attributes:
{
"uniqueId": "card001",
"tagName": "div",
"styles": {
"backgroundColor": "#ffffff",
"display": "flex",
"padding": "2rem"
},
"css": ".gb-element-card001{background-color:#ffffff;display:flex;padding:2rem}"
}
CSS rules:
css attribute contains only base styles - no hover states, no transitions (the plugin generates those from the styles object)css: pseudo-elements (::before/::after), media queries, animations, parent hover targeting children/* Base styles only (alphabetically sorted) + pseudo-elements + media queries */
.gb-element-card001{background-color:#ffffff;border-radius:1rem;display:flex;padding:2rem;position:relative}.gb-element-card001::after{content:'';position:absolute;bottom:0;left:0;width:100%;height:3px;background:#c0392b;transform:scaleX(0)}@media(max-width:768px){.gb-element-card001{padding:1rem}}
Parent hover targeting children is written in the child's css:
.gb-element-card001:hover .gb-text-title001{color:#c0392b}
Desktop-first approach with standard breakpoints:
| Breakpoint | Width | Use For |
|---|---|---|
| Desktop | 1025px+ | Default styles (no media query) |
| Tablet | 768px - 1024px | @media(max-width:1024px) |
| Mobile | < 768px | @media(max-width:768px) |
Two approaches for responsive styles:
styles object (preferred for simple overrides):{
"styles": {
"display": "grid",
"gridTemplateColumns": "minmax(0, 1fr) minmax(0, 1fr)",
"gap": "4rem",
"@media (max-width:1024px)": {
"gridTemplateColumns": "minmax(0, 1fr)"
}
}
}
css string (for complex responsive rules):.gb-element-hero001{display:grid;gap:4rem;grid-template-columns:minmax(0,1fr) minmax(0,1fr)}@media (max-width:1024px){.gb-element-hero001{grid-template-columns:minmax(0,1fr)}}
Common responsive patterns:
grid-template-columns:minmax(0,1fr) minmax(0,1fr) → grid-template-columns:minmax(0,1fr)padding:6rem 0 → padding:4rem 0 → padding:3rem 0clamp() for fluid typographyflex-direction:row → flex-direction:columngap:4rem → gap:2remtext-align:left → text-align:centerFor full-width sections with contained inner content:
<!-- wp:generateblocks/element {"uniqueId":"hero001","tagName":"section","styles":{...},"css":"...","align":"full","className":"gb-element-hero001 gb-element alignfull"} -->
<section class="gb-element-hero001 gb-element alignfull">
<!-- wp:generateblocks/element {"uniqueId":"hero002","tagName":"div","styles":{"maxWidth":"var(\u002d\u002dgb-container-width)","marginLeft":"auto","marginRight":"auto"},"css":".gb-element-hero002{margin-left:auto;margin-right:auto;max-width:var(\u002d\u002dgb-container-width)}","className":"gb-element-hero002 gb-element"} -->
<div class="gb-element-hero002 gb-element">
<!-- Inner content -->
</div>
<!-- /wp:generateblocks/element -->
</section>
<!-- /wp:generateblocks/element -->
Key:
"align":"full" + "className":"gb-element-hero001 gb-element alignfull"maxWidth: "var(\u002d\u002dgb-container-width)" (unicode-escaped --gb-container-width)Format: {section}{number}{letter}
hero, serv, card, feat, blog)a, b, c)Examples: hero001, serv023a, card014, feat007b
Start with _index.md to figure out which file you need.
See /examples/ folder for copy-paste ready blocks:
⛔ NEVER add HTML comments other than WordPress block markers.
The ONLY allowed comments are WordPress block delimiters:
<!-- wp:generateblocks/element {...} --> and <!-- /wp:generateblocks/element --><!-- wp:generateblocks/text {...} --> and <!-- /wp:generateblocks/text --><!-- wp:generateblocks/media {...} --> and <!-- /wp:generateblocks/media --><!-- wp:generateblocks/shape {...} --> and <!-- /wp:generateblocks/shape --><!-- wp:image {...} --> and <!-- /wp:image --><!-- wp:video {...} --> and <!-- /wp:video --><!-- wp:embed {...} --> and <!-- /wp:embed --><!-- wp:{namespace}/{block} --> formatWRONG - These will break the block editor:
<!-- Hero Section -->
<!-- Card container -->
<!-- Button wrapper -->
<!-- This is a heading -->
<!-- Content goes here -->
CORRECT - Only block delimiters:
<!-- wp:generateblocks/element {"uniqueId":"hero001",...,"className":"gb-element"} -->
<section class="gb-element-hero001 gb-element">
<!-- wp:generateblocks/text {"uniqueId":"hero002",...} -->
<h1 class="gb-text gb-text-hero002">Heading</h1>
<!-- /wp:generateblocks/text -->
</section>
<!-- /wp:generateblocks/element -->
Any extra HTML comments will break the WordPress block editor and cause parsing errors. This is non-negotiable.
css attribute, no spaces inside function args (repeat(3,1fr) not repeat(3, 1fr))transition declarations and no :hover rules in the css string. The plugin generates both from the styles object. Exceptions: pseudo-elements, media queries, animations, parent-hover targeting childrencss stringstyles object AND the css string-- as \u002d\u002d anywhere it appears inside JSON strings (both styles values and css strings) — literal -- in JSON triggers recovery on save. Inline style="" on rendered HTML can use literal var(--foo) because it's not JSONcss — selectors like .gb-text-x small{} or .gb-text-x .u{} get stripped and trigger recovery. Put inline style="" on the inner <small>, <code>, <strong>, <span> directly. Allowed exceptions: pseudo-elements on the block's own selector, and parent-hover targeting another GB block by its own generated class\xxxx escape sequences — write literal characters: content:'→', not content:'\2192'. Better: put arrows in the rendered text content, not in pseudo-elements<a> wrapping a text span child — text <a> strips its href on save, element <a> with raw text triggers recovery. The element-a wraps text-span pattern avoids both. See SKILL.md "The link block pattern" sectionhtmlAttributes is always a plain object — {"href":"..."} never [{"attribute":"href","value":"..."}]htmlAttributes.href — relative paths get canonicalized on save → recovery& encoding — keep literal & in JSON htmlAttributes, encode as & in the rendered HTML <a href="..."> bodyclassName must include the uniqueId class — "gb-element-{uniqueId} gb-element", never just "gb-element"csscore/image, NOT generateblocks/media. generateblocks/media is for dynamic loop images. Plain static images without captions can use either, but core/image is more reliablecore/list with className:"list"core/paragraph — GB renders emoji glyphs incorrectlyquery-block.md — use generateblocks/query + looper + loop-item for any post list, archive, or related-posts sectionstyles.svg for SVG-specific props OR simple styles with inline SVG attributes; both workvar(\u002d\u002dgb-container-width) for inner containers with align:"full" on the parent section for full-width layoutsstroke-linejoin, stroke-linecap, stroke-width, stroke, fill, viewBox, height, width. Write them in that order.For the full list of recovery causes and the exact fix for each, see
references/recovery-rules.md.
When no CSS values are specified, infer styles based on context:
#0073e6#22222217px, line-height 1.742px, H2: 35px, H3: 29px60pxvar(--gb-container-width)15px 30px#c0392b#0a0a0a, Muted: #5c5c5c#ffffff, Light: #f5f5f3900, tight letter-spacing4rem1rem, Button radius: 2remtranslateY(-6px)0 20px 60px rgba(0,0,0,0.15)For large sections (50+ blocks), break into chunks:
See Troubleshooting for detailed guidance on complex layouts.