What this prompt does
This prompt builds a custom Gutenberg block named [block_name] for [block_purpose] the correct, modern way. It generates a block.json with [attributes], an Edit component exposing [controls] in InspectorControls, a properly serialized Save component, ServerSideRender for dynamic data from [data_source], block variations [variations], InnerBlocks for [inner_block_content], transforms from/to [transform_blocks], block styles [block_styles], a @wordpress/scripts build config, and PHP registration with a render callback — styled with [styling_approach].
The structure works because real Gutenberg blocks are React components with strict serialization rules, not shortcodes in disguise. Defining [attributes] in block.json first gives the editor and the saved markup a single contract. ServerSideRender handles dynamic content that can't be hardcoded, InnerBlocks makes [inner_block_content] flexible without breaking layout, and transforms let editors convert from [transform_blocks] they already use.
When to use it
- You're building a real Gutenberg block, not faking one with a shortcode
- You need editor controls for
[controls]in InspectorControls - Your block renders dynamic content from
[data_source]and needs ServerSideRender - You want flexible nested content via InnerBlocks for
[inner_block_content] - You need
[variations]and transforms from[transform_blocks]for editor convenience - You want a proper
@wordpress/scriptsbuild and an E2E test, not ad-hoc tooling
Example output
Expect a block package: a block.json declaring [attributes], an Edit component with [controls], a serialized Save component (or ServerSideRender for dynamic data from [data_source]), variation and transform definitions, InnerBlocks setup, block style registrations, a @wordpress/scripts build config, PHP registration with a render callback, and an E2E test using @wordpress/e2e-test-utils.
Pro tips
- Define
[attributes]carefully inblock.json— they're the contract between Edit and Save, and mismatches cause block validation errors - Use ServerSideRender for anything truly dynamic from
[data_source]; baking dynamic data into Save breaks on re-render - Keep
[controls]minimal and grouped in InspectorControls so the editor stays usable - Add transforms from
[transform_blocks]editors already use, like core/table, so migration into your block is one click - Match
[styling_approach]to your theme tokens so the block inherits the site's design system - Run the generated E2E test — block validation issues often only surface when you actually edit and re-save in the editor