Use when developing WordPress (Gutenberg) blocks: block.json metadata, register_block_type(_from_metadata), attributes/serialization, supports, dynamic rendering (render.php/render_callback), deprecations/migrations, viewScript vs viewScriptModule, and @wordpress/scripts/@wordpress/create-block build and test workflows.
Add this skill
npx mdskills install WordPress/wp-block-developmentComprehensive block development workflow with clear structure, scanning scripts, and extensive reference material
1---2name: wp-block-development3description: "Use when developing WordPress (Gutenberg) blocks: block.json metadata, register_block_type(_from_metadata), attributes/serialization, supports, dynamic rendering (render.php/render_callback), deprecations/migrations, viewScript vs viewScriptModule, and @wordpress/scripts/@wordpress/create-block build and test workflows."4compatibility: "Targets WordPress 6.9+ (PHP 7.2.24+). Filesystem-based agent with bash + node. Some workflows require WP-CLI."5---67# WP Block Development89## When to use1011Use this skill for block work such as:1213- creating a new block, or updating an existing one14- changing `block.json` (scripts/styles/supports/attributes/render/viewScriptModule)15- fixing “block invalid / not saving / attributes not persisting”16- adding dynamic rendering (`render.php` / `render_callback`)17- block deprecations and migrations (`deprecated` versions)18- build tooling for blocks (`@wordpress/scripts`, `@wordpress/create-block`, `wp-env`)1920## Inputs required2122- Repo root and target (plugin vs theme vs full site).23- The block name/namespace and where it lives (path to `block.json` if known).24- Target WordPress version range (especially if using modules / `viewScriptModule`).2526## Procedure2728### 0) Triage and locate blocks29301. Run triage:31 - `node skills/wp-project-triage/scripts/detect_wp_project.mjs`322. List blocks (deterministic scan):33 - `node skills/wp-block-development/scripts/list_blocks.mjs`343. Identify the block root (directory containing `block.json`) you’re changing.3536If this repo is a full site (`wp-content/` present), be explicit about *which* plugin/theme contains the block.3738### 1) Create a new block (if needed)3940If you are creating a new block, prefer scaffolding rather than hand-rolling structure:4142- Use `@wordpress/create-block` to scaffold a modern block/plugin setup.43- If you need Interactivity API from day 1, use the interactive template.4445Read:46- `references/creating-new-blocks.md`4748After scaffolding:49501. Re-run the block list script and confirm the new block root.512. Continue with the remaining steps (model choice, metadata, registration, serialization).5253### 2) Ensure apiVersion 3 (WordPress 6.9+)5455WordPress 6.9 enforces `apiVersion: 3` in the block.json schema. Blocks with apiVersion 2 or lower trigger console warnings when `SCRIPT_DEBUG` is enabled.5657**Why this matters:**58- WordPress 7.0 will run the post editor in an iframe regardless of block apiVersion.59- apiVersion 3 ensures your block works correctly inside the iframed editor (style isolation, viewport units, media queries).6061**Migration:** Changing from version 2 to 3 is usually as simple as updating the `apiVersion` field in `block.json`. However:62- Test in a local environment with the iframe editor enabled.63- Ensure any style handles are included in `block.json` (styles missing from the iframe won't apply).64- Third-party scripts attached to a specific `window` may have scoping issues.6566Read:67- `references/block-json.md` (apiVersion and schema details)6869### 3) Pick the right block model7071- **Static block** (markup saved into post content): implement `save()`; keep attributes serialization stable.72- **Dynamic block** (server-rendered): use `render` in `block.json` (or `render_callback` in PHP) and keep `save()` minimal or `null`.73- **Interactive frontend behavior**:74 - Prefer `viewScriptModule` for modern module-based view scripts where supported.75 - If you're working primarily on `data-wp-*` directives or stores, also use `wp-interactivity-api`.7677### 4) Update `block.json` safely7879Make changes in the block’s `block.json`, then confirm registration matches metadata.8081For field-by-field guidance, read:82- `references/block-json.md`8384Common pitfalls:8586- changing `name` breaks compatibility (treat it as stable API)87- changing saved markup without adding `deprecated` causes “Invalid block”88- adding attributes without defining source/serialization correctly causes “attribute not saving”8990### 5) Register the block (server-side preferred)9192Prefer PHP registration using metadata, especially when:9394- you need dynamic rendering95- you need translations (`wp_set_script_translations`)96- you need conditional asset loading9798Read and apply:99- `references/registration.md`100101### 6) Implement edit/save/render patterns102103Follow wrapper attribute best practices:104105- Editor: `useBlockProps()`106- Static save: `useBlockProps.save()`107- Dynamic render (PHP): `get_block_wrapper_attributes()`108109Read:110- `references/supports-and-wrappers.md`111- `references/dynamic-rendering.md` (if dynamic)112113### 7) Inner blocks (block composition)114115If your block is a “container” that nests other blocks, treat Inner Blocks as a first-class feature:116117- Use `useInnerBlocksProps()` to integrate inner blocks with wrapper props.118- Keep migrations in mind if you change inner markup.119120Read:121- `references/inner-blocks.md`122123### 8) Attributes and serialization124125Before changing attributes:126127- confirm where the attribute value lives (comment delimiter vs HTML vs context)128- avoid the deprecated `meta` attribute source129130Read:131- `references/attributes-and-serialization.md`132133### 9) Migrations and deprecations (avoid "Invalid block")134135If you change saved markup or attributes:1361371. Add a `deprecated` entry (newest → oldest).1382. Provide `save` for old versions and an optional `migrate` to normalize attributes.139140Read:141- `references/deprecations.md`142143### 10) Tooling and verification commands144145Prefer whatever the repo already uses:146147- `@wordpress/scripts` (common) → run existing npm scripts148- `wp-env` (common) → use for local WP + E2E149150Read:151- `references/tooling-and-testing.md`152153## Verification154155- Block appears in inserter and inserts successfully.156- Saving + reloading does not create “Invalid block”.157- Frontend output matches expectations (static: saved markup; dynamic: server output).158- Assets load where expected (editor vs frontend).159- Run the repo’s lint/build/tests that triage recommends.160161## Failure modes / debugging162163If something fails, start here:164165- `references/debugging.md` (common failures + fastest checks)166- `references/attributes-and-serialization.md` (attributes not saving)167- `references/deprecations.md` (invalid block after change)168169## Escalation170171If you’re uncertain about upstream behavior/version support, consult canonical docs first:172173- WordPress Developer Resources (Block Editor Handbook, Theme Handbook, Plugin Handbook)174- Gutenberg repo docs for bleeding-edge behaviors175
Full transparency — inspect the skill content before installing.