# Wp Gutenberg Blocks

> Use when developing WordPress (Gutenberg) blocks: block.json metadata, register_block_type, attributes/serialization, supports, dynamic rendering (render.php), deprecations/migrations, InnerBlocks, viewScript/viewScriptModule, and @wordpress/scripts build workflows.

- Skill: `majiayu000/wp-gutenberg-blocks` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add majiayu000/wp-gutenberg-blocks`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/wp-gutenberg-blocks/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/wp-gutenberg-blocks

---


# WP Block Development

## When to use

Use this skill for block work such as:

- creating a new block or updating an existing one
- changing `block.json` (scripts/styles/supports/attributes/render)
- fixing "block invalid / not saving / attributes not persisting"
- adding dynamic rendering (`render.php` / `render_callback`)
- block deprecations and migrations (`deprecated` versions)
- build tooling (`@wordpress/scripts`, `@wordpress/create-block`)
- block patterns and variations

## Inputs required

- Repo root and target (plugin vs theme vs full site).
- The block name/namespace and where it lives (path to `block.json` if known).
- Target WordPress version range (especially for `viewScriptModule` / apiVersion 3).

## Procedure

### 0) Triage and locate blocks

1. Search for existing `block.json` files
2. Search for `register_block_type` calls
3. Identify the block root (directory containing `block.json`)

### 1) Create a new block (if needed)

If creating a new block, prefer scaffolding:

```bash
npx @wordpress/create-block@latest my-custom-block
```

For interactive blocks, use the interactive template.

Read:
- `references/creating-blocks.md`

### 2) Ensure apiVersion 3 (WordPress 6.9+)

WordPress 6.9 enforces `apiVersion: 3` in block.json schema. Blocks with apiVersion 2 or lower trigger console warnings when `SCRIPT_DEBUG` is enabled.

**Why this matters:**
- WordPress 7.0 will run the post editor in an iframe regardless of block apiVersion
- apiVersion 3 ensures your block works correctly inside the iframed editor (style isolation, viewport units, media queries)

**Migration from apiVersion 2:**
1. Update the `apiVersion` field in `block.json` to `3`
2. Test in a local environment with the iframe editor enabled
3. Ensure any style handles are included in `block.json` (styles missing from the iframe won't apply)
4. Third-party scripts attached to a specific `window` may have scoping issues

```json
{
  "apiVersion": 3,
  "name": "my-plugin/my-block",
  "...": "..."
}
```

Read:
- `references/block-json.md`

### 3) Pick the right block model

- **Static block** (markup saved into post content): implement `save()`
- **Dynamic block** (server-rendered): use `render` in `block.json` and keep `save()` minimal or `null`
- **Interactive frontend**: use `viewScriptModule` for modern module-based view scripts

**viewScript vs viewScriptModule:**

| Property | `viewScript` | `viewScriptModule` |
|----------|--------------|-------------------|
| Module type | Classic script | ES Module |
| Loading | Synchronous | Async/deferred |
| Use for | Legacy/compatibility | Interactivity API, modern JS |
| Dependencies | Manual registration | Import statements |

```json
{
  "viewScript": "file:./view.js",
  "viewScriptModule": "file:./view.js"
}
```

Prefer `viewScriptModule` for:
- Interactivity API (`@wordpress/interactivity`)
- Modern ES module imports
- Better performance (deferred loading)

### 4) Update block.json safely

For field-by-field guidance:

Read:
- `references/block-json.md`

Common pitfalls:
- Changing `name` breaks compatibility (treat it as stable API)
- Changing saved markup without adding `deprecated` causes "Invalid block"
- Adding attributes without defining source/serialization causes "attribute not saving"

### 5) Register the block (server-side preferred)

Prefer PHP registration using metadata for:
- Dynamic rendering
- Translations (`wp_set_script_translations`)
- Conditional asset loading

Read:
- `references/registration.md`

### 6) Implement edit/save/render patterns

Follow wrapper attribute best practices:
- Editor: `useBlockProps()`
- Static save: `useBlockProps.save()`
- Dynamic render (PHP): `get_block_wrapper_attributes()`

Read:
- `references/edit-save-render.md`

### 7) Inner blocks (block composition)

If your block is a container that nests other blocks:
- Use `useInnerBlocksProps()` to integrate inner blocks with wrapper props
- Keep migrations in mind if you change inner markup

Read:
- `references/inner-blocks.md`

### 8) Block patterns and variations

- Patterns: predefined block arrangements
- Variations: different configurations of a single block

Read:
- `references/patterns-variations.md`

### 9) Migrations and deprecations

If you change saved markup or attributes:
1. Add a `deprecated` entry (newest → oldest)
2. Provide `save` for old versions and optional `migrate`

Read:
- `references/deprecations.md`

## Verification

- Block appears in inserter and inserts successfully.
- Saving + reloading does not create "Invalid block".
- Frontend output matches expectations (static: saved markup; dynamic: server output).
- Assets load where expected (editor vs frontend).
- Run the repo's lint/build/tests.

## Failure modes / debugging

- "Invalid block content" after changes:
  - Missing deprecation entry, changed markup without migration
- Block attributes not saving:
  - Missing `source` definition, wrong attribute type, serialization mismatch
- Block not appearing in inserter:
  - Registration failed, wrong category, PHP fatal error
- Styles not applying in editor:
  - Missing `editorStyle` in block.json, wrong asset path

Read:
- `references/debugging.md`

## Escalation

For canonical detail, consult:
- [Block Editor Handbook](https://developer.wordpress.org/block-editor/)
- [Block API Reference](https://developer.wordpress.org/block-editor/reference-guides/block-api/)
- [Gutenberg Storybook](https://wordpress.github.io/gutenberg/)

