Claude Skill

wp-block-registration-and-assets

Create or audit WordPress blocks registered through block.json, metadata collections, or PHP-only autoRegister. Covers register_block_type, register_block_type_from_metadata, API version 3, attributes and roles, dynamic rendering, wrapper attributes, editor/frontend asset fields,

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download lonsdale201-wp-agent-skills-wordpress_wp-block-registration-and-assets-52f6020.zip · 5 KB
Part of lonsdale201/wp-agent-skills — 226 skills

Install

skills CLI npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/wordpress/wp-block-registration-and-assets
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
Git git clone https://github.com/Lonsdale201/wp-agent-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

WordPress Block Registration and Assets

Treat block.json as the shared server/editor contract. Register from metadata, let WordPress resolve generated asset files and supports, and keep the saved markup compatible with the block's current and deprecated versions.

Choose the registration model

Need Model
Normal editable block with custom editor UI block.json plus JavaScript registration/build
Dynamic block with custom editor UI metadata plus render/render_callback
Simple server-rendered fields, no custom editor JS PHP supports.autoRegister on WordPress 7.0+
Fixed composition of existing blocks pattern or block variation
Dynamic value in a supported existing attribute Block Bindings source

Register on init. Prefer register_block_type_from_metadata() for one block or wp_register_block_metadata_collection() plus metadata registration for a compiled collection. Do not register the same block independently in PHP and JavaScript with drifting attributes or supports.

add_action( 'init', static function (): void {
	register_block_type_from_metadata( __DIR__ . '/build/card' );
} );

Use API version 3 for current blocks. Give every attribute a deliberate type, default, and persistence model. Attribute role: local is editor-only and is not serialized. Treat block attributes and inner markup as untrusted content.

Dynamic rendering

Use a render.php file declared by "render": "file:./render.php", or a render_callback, when output depends on current data. Keep rendering pure, cache repeated expensive reads, and return markup instead of echoing unrelated output.

$title = isset( $attributes['title'] ) ? (string) $attributes['title'] : '';
?>
<section <?php echo get_block_wrapper_attributes(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Core returns escaped wrapper attributes. ?>>
	<h2><?php echo esc_html( $title ); ?></h2>
</section>

Use get_block_wrapper_attributes() so style engine output, alignment, supports, and class names reach the outer element. Escape each plugin-owned value for its final HTML context. Never trust the editor's preview, block validation, or a hidden Inspector control as authorization.

PHP-only blocks on WordPress 7.0+

For a simple dynamic block, set supports.autoRegister and provide a render callback. Core can register the client representation and generate supported Inspector controls from PHP attribute schemas. This is intentionally narrower than a JavaScript block; use a normal build when edit behavior is custom.

register_block_type(
	'acme/server-card',
	array(
		'title'           => __( 'Server card', 'acme' ),
		'attributes'      => array(
			'title' => array(
				'type'    => 'string',
				'label'   => __( 'Title', 'acme' ),
				'default' => '',
			),
		),
		'supports'        => array( 'autoRegister' => true ),
		'render_callback' => 'acme_render_server_card',
	)
);

Do not expect generated controls for local attributes or unsupported schema types. Feature-detect this model or set the plugin's minimum WordPress version.

Asset placement

Use metadata fields rather than global enqueues:

  • editorScript: editor registration and edit UI;
  • script: classic script loaded in both editor and frontend contexts;
  • viewScript: classic frontend-only script;
  • viewScriptModule: frontend script module, including Interactivity API code;
  • style: content styles for frontend and editor canvas;
  • editorStyle: canvas-only/editor presentation.

Consume the build-generated .asset.php dependency/version file. Do not load editor UI code on every wp-admin screen, or put block content CSS only in the parent editor document. WordPress 7.1 always iframes the post editor canvas.

WordPress 7.1 block support changes

Opt in only when the block wrapper and save/render implementation can consume the generated support attributes:

{
  "apiVersion": 3,
  "supports": {
    "background": {
      "backgroundImage": true,
      "gradient": true
    },
    "dimensions": {
      "minWidth": true
    }
  }
}
  • background.gradient stores at style.background.gradient and renders via background-image, allowing it to layer with a background image. It is separate from legacy color.gradient.
  • dimensions.minWidth stores at style.dimensions.minWidth, renders min-width, and can use dimension presets.
  • Optional controls are not necessarily shown by default. Use __experimentalDefaultControls only where the current block-support contract requires a default-visible control; do not rename stable support keys as experimental.
  • core/list-item now supports a content Block Binding.

Test saved markup and dynamic output on the oldest supported WordPress. A block saved with a new support still needs a coherent fallback when opened or rendered where that support is unavailable.

Variations, transforms, and Custom HTML

In 7.1, transforms can target a variation with variationName, and switchToBlockType() accepts the target variation as its third argument. Use stable cloneSanitizedBlock() and sanitizeBlockAttributes(); their __experimental* aliases now warn.

Only core/html variations accept innerContent: static HTML fragments with a null slot for each matching innerBlocks entry. The editable inner blocks are locked inside the static shell. Do not advertise innerContent as a generic custom-block variation API, and never use it to bypass KSES or capability checks. Scripts in Custom HTML do not run in the editor preview.

Compatibility and security checklist

  • Register on init; assert that registration succeeded.
  • Keep server/client attribute schemas, context, supports, and defaults equal.
  • Use stable public package exports and metadata fields, not private editor APIs.
  • Preserve fallback/saved content and declare deprecations for save-markup changes.
  • Use wrapper attributes on the intended outer element.
  • Authorize REST/Ajax writes server-side and sanitize stored data.
  • Avoid remote requests and writes during render; cache repeatable reads.
  • Test editor, frontend, REST raw/rendered content, reusable content, and failure fallbacks.
  • Test 7.1's iframe, responsive styles, theme.json, RTL, keyboard, and multiple block instances.

Read references/wp-71-block-contracts.md for the 7.1 support paths, Custom HTML variation shape, transforms, and migration probes.

Related skills

  • wp-block-editor-iframe-compatibility for canvas DOM and asset boundaries.
  • wp-block-bindings-api for dynamic supported attributes.
  • wp-interactivity-api for reactive frontend blocks.
  • block-theme-global-styles for theme.json values and responsive states.
  • wp-plugin-assets-loading for shared admin/frontend asset registration.

References

Files (wp-agent-skills)
  • agents
    • openai.yaml 260 B
      interface:
        display_name: "WordPress block registration"
        short_description: "Build secure, compatible metadata and PHP blocks"
        default_prompt: "Use $wp-block-registration-and-assets to build or audit this WordPress block and its asset/support contracts."
      
  • references
    • wp-71-block-contracts.md 3.4 KB
      # WordPress 7.1 block contracts
      
      ## Support paths
      
      | Capability | `block.json` opt-in | Attribute/style path | CSS output |
      |---|---|---|---|
      | Background gradient | `supports.background.gradient` | `style.background.gradient` | `background-image` |
      | Minimum width | `supports.dimensions.minWidth` | `style.dimensions.minWidth` | `min-width` |
      | List Item binding | no new block opt-in | `metadata.bindings.content` on `core/list-item` | bound list-item content |
      
      The new background gradient may be combined with a background image as
      comma-separated `background-image` layers. When that support and value are
      active, Core suppresses the older Color-panel gradient to avoid duplicate
      controls. Existing `color.gradient` data remains supported.
      
      ## Custom HTML variation slots
      
      ```js
      wp.blocks.registerBlockVariation( 'core/html', {
      	name: 'acme-callout-shell',
      	title: 'Callout shell',
      	innerContent: [ '<aside class="acme-callout">', null, '</aside>' ],
      	innerBlocks: [
      		[ 'core/paragraph', { content: 'Editable content' } ],
      	],
      } );
      ```
      
      Each `null` corresponds positionally to an `innerBlocks` entry. The contract is
      specific to `core/html`; other block types ignore `innerContent`. Verify exact
      serialization round trips and KSES behavior for the author role being supported.
      
      ## 7.1 package migrations
      
      - Use a transform object's `variationName` when the target is a particular
        variation rather than only a base block type.
      - `switchToBlockType( blocks, targetName, variationName )` supports the same
        explicit target.
      - Replace `__experimentalCloneSanitizedBlock` with `cloneSanitizedBlock`.
      - Replace `__experimentalSanitizeBlockAttributes` with
        `sanitizeBlockAttributes`.
      - Direct `pasteHandler()` consumers should re-test Markdown edge cases because
        Core's internal parser changed from Showdown to Marked/CommonMark-GFM behavior.
      - Paragraph `editableRoot` work can change native event targets. Filters adding
        editing event props to `editor.BlockListBlock` should test the pseudo
        SyntheticEvent bridge instead of assuming the original DOM target.
      
      ## Deferred features are not 7.1 contracts
      
      Do not write a compatibility path that assumes React 19, real-time
      collaboration, or removal of the Classic block. Those changes did not ship in
      WordPress 7.1.
      
      ## Verification probes
      
      1. Assert `WP_Block_Type_Registry::get_instance()->is_registered()` after
         `init` and inspect the final server block type.
      2. Parse and render fixture markup with `parse_blocks()` and `do_blocks()`.
      3. Compare saved markup before/after editing and exercise declared deprecated
         block versions.
      4. Confirm metadata asset handles resolve and are absent on unrelated screens.
      5. Inspect wrapper classes/styles for every enabled support.
      6. Test Custom HTML slot markup with an author affected by unfiltered HTML rules.
      7. Run editor console tests with deprecated/experimental export use treated as
         a failure.
      
      ## Primary sources
      
      - <https://make.wordpress.org/core/2026/07/26/new-block-support-in-wordpress-7-1-background-gradient-background-gradient/>
      - <https://make.wordpress.org/core/2026/07/26/new-block-support-in-wordpress-7-1-minimum-width/>
      - <https://make.wordpress.org/core/2026/07/23/editable-blocks-inside-the-custom-html-block/>
      - <https://make.wordpress.org/core/2026/08/04/miscellaneous-block-editor-changes-in-wordpress-7-1/>
      - Core: `wp-includes/blocks.php`, `class-wp-block-type.php`,
        `block-supports/background.php`, `block-supports/dimensions.php`.
      
      
  • SKILL.md 8.5 KB
    ---
    name: wp-block-registration-and-assets
    description: >-
      Create or audit WordPress blocks registered through block.json, metadata
      collections, or PHP-only autoRegister. Covers register_block_type,
      register_block_type_from_metadata, API version 3, attributes and roles,
      dynamic rendering, wrapper attributes, editor/frontend asset fields,
      script modules, block supports, deprecations, transforms, variations, and
      WordPress 7.1 background.gradient, dimensions.minWidth, Custom HTML
      innerContent, List Item bindings, and always-iframed editor compatibility.
      Use when building a custom block, reviewing block metadata or render.php,
      adding design supports, fixing editor/frontend parity, or migrating block
      extensions to WordPress 7.1.
    license: GPLv2-or-later
    metadata:
      wp-skills-author: "Soczó Kristóf"
      wp-skills-contact: "mailto:lonsdale201@hotmail.com"
      wp-skills-plugin: "wordpress"
      wp-skills-plugin-version-tested: "7.0 - 7.1"
      wp-skills-wp-version-tested: "7.1"
      wp-skills-php-min: "7.4"
      wp-skills-last-updated: "2026-08-20"
    ---
    
    # WordPress Block Registration and Assets
    
    Treat `block.json` as the shared server/editor contract. Register from metadata,
    let WordPress resolve generated asset files and supports, and keep the saved
    markup compatible with the block's current and deprecated versions.
    
    ## Choose the registration model
    
    | Need | Model |
    |---|---|
    | Normal editable block with custom editor UI | `block.json` plus JavaScript registration/build |
    | Dynamic block with custom editor UI | metadata plus `render`/`render_callback` |
    | Simple server-rendered fields, no custom editor JS | PHP `supports.autoRegister` on WordPress 7.0+ |
    | Fixed composition of existing blocks | pattern or block variation |
    | Dynamic value in a supported existing attribute | Block Bindings source |
    
    Register on `init`. Prefer `register_block_type_from_metadata()` for one block
    or `wp_register_block_metadata_collection()` plus metadata registration for a
    compiled collection. Do not register the same block independently in PHP and
    JavaScript with drifting attributes or supports.
    
    ```php
    add_action( 'init', static function (): void {
    	register_block_type_from_metadata( __DIR__ . '/build/card' );
    } );
    ```
    
    Use API version 3 for current blocks. Give every attribute a deliberate type,
    default, and persistence model. Attribute `role: local` is editor-only and is
    not serialized. Treat block attributes and inner markup as untrusted content.
    
    ## Dynamic rendering
    
    Use a `render.php` file declared by `"render": "file:./render.php"`, or a
    `render_callback`, when output depends on current data. Keep rendering pure,
    cache repeated expensive reads, and return markup instead of echoing unrelated
    output.
    
    ```php
    $title = isset( $attributes['title'] ) ? (string) $attributes['title'] : '';
    ?>
    <section <?php echo get_block_wrapper_attributes(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Core returns escaped wrapper attributes. ?>>
    	<h2><?php echo esc_html( $title ); ?></h2>
    </section>
    ```
    
    Use `get_block_wrapper_attributes()` so style engine output, alignment,
    supports, and class names reach the outer element. Escape each plugin-owned
    value for its final HTML context. Never trust the editor's preview, block
    validation, or a hidden Inspector control as authorization.
    
    ## PHP-only blocks on WordPress 7.0+
    
    For a simple dynamic block, set `supports.autoRegister` and provide a render
    callback. Core can register the client representation and generate supported
    Inspector controls from PHP attribute schemas. This is intentionally narrower
    than a JavaScript block; use a normal build when edit behavior is custom.
    
    ```php
    register_block_type(
    	'acme/server-card',
    	array(
    		'title'           => __( 'Server card', 'acme' ),
    		'attributes'      => array(
    			'title' => array(
    				'type'    => 'string',
    				'label'   => __( 'Title', 'acme' ),
    				'default' => '',
    			),
    		),
    		'supports'        => array( 'autoRegister' => true ),
    		'render_callback' => 'acme_render_server_card',
    	)
    );
    ```
    
    Do not expect generated controls for `local` attributes or unsupported schema
    types. Feature-detect this model or set the plugin's minimum WordPress version.
    
    ## Asset placement
    
    Use metadata fields rather than global enqueues:
    
    - `editorScript`: editor registration and edit UI;
    - `script`: classic script loaded in both editor and frontend contexts;
    - `viewScript`: classic frontend-only script;
    - `viewScriptModule`: frontend script module, including Interactivity API code;
    - `style`: content styles for frontend and editor canvas;
    - `editorStyle`: canvas-only/editor presentation.
    
    Consume the build-generated `.asset.php` dependency/version file. Do not load
    editor UI code on every wp-admin screen, or put block content CSS only in the
    parent editor document. WordPress 7.1 always iframes the post editor canvas.
    
    ## WordPress 7.1 block support changes
    
    Opt in only when the block wrapper and save/render implementation can consume
    the generated support attributes:
    
    ```json
    {
      "apiVersion": 3,
      "supports": {
        "background": {
          "backgroundImage": true,
          "gradient": true
        },
        "dimensions": {
          "minWidth": true
        }
      }
    }
    ```
    
    - `background.gradient` stores at `style.background.gradient` and renders via
      `background-image`, allowing it to layer with a background image. It is
      separate from legacy `color.gradient`.
    - `dimensions.minWidth` stores at `style.dimensions.minWidth`, renders
      `min-width`, and can use dimension presets.
    - Optional controls are not necessarily shown by default. Use
      `__experimentalDefaultControls` only where the current block-support contract
      requires a default-visible control; do not rename stable support keys as
      experimental.
    - `core/list-item` now supports a `content` Block Binding.
    
    Test saved markup and dynamic output on the oldest supported WordPress. A block
    saved with a new support still needs a coherent fallback when opened or
    rendered where that support is unavailable.
    
    ## Variations, transforms, and Custom HTML
    
    In 7.1, transforms can target a variation with `variationName`, and
    `switchToBlockType()` accepts the target variation as its third argument.
    Use stable `cloneSanitizedBlock()` and `sanitizeBlockAttributes()`; their
    `__experimental*` aliases now warn.
    
    Only `core/html` variations accept `innerContent`: static HTML fragments with a
    `null` slot for each matching `innerBlocks` entry. The editable inner blocks are
    locked inside the static shell. Do not advertise `innerContent` as a generic
    custom-block variation API, and never use it to bypass KSES or capability
    checks. Scripts in Custom HTML do not run in the editor preview.
    
    ## Compatibility and security checklist
    
    - Register on `init`; assert that registration succeeded.
    - Keep server/client attribute schemas, context, supports, and defaults equal.
    - Use stable public package exports and metadata fields, not private editor APIs.
    - Preserve fallback/saved content and declare deprecations for save-markup changes.
    - Use wrapper attributes on the intended outer element.
    - Authorize REST/Ajax writes server-side and sanitize stored data.
    - Avoid remote requests and writes during render; cache repeatable reads.
    - Test editor, frontend, REST raw/rendered content, reusable content, and failure fallbacks.
    - Test 7.1's iframe, responsive styles, theme.json, RTL, keyboard, and multiple block instances.
    
    Read `references/wp-71-block-contracts.md` for the 7.1 support paths,
    Custom HTML variation shape, transforms, and migration probes.
    
    ## Related skills
    
    - `wp-block-editor-iframe-compatibility` for canvas DOM and asset boundaries.
    - `wp-block-bindings-api` for dynamic supported attributes.
    - `wp-interactivity-api` for reactive frontend blocks.
    - `block-theme-global-styles` for theme.json values and responsive states.
    - `wp-plugin-assets-loading` for shared admin/frontend asset registration.
    
    ## References
    
    - Read `references/wp-71-block-contracts.md` for the per-support contract table and asset-field matrix.
    - `background.gradient` support: <https://make.wordpress.org/core/2026/07/26/new-block-support-in-wordpress-7-1-background-gradient-background-gradient/>
    - `dimensions.minWidth` support: <https://make.wordpress.org/core/2026/07/26/new-block-support-in-wordpress-7-1-minimum-width/>
    - Editable blocks inside Custom HTML: <https://make.wordpress.org/core/2026/07/23/editable-blocks-inside-the-custom-html-block/>
    - Miscellaneous block editor changes in WordPress 7.1: <https://make.wordpress.org/core/2026/08/04/miscellaneous-block-editor-changes-in-wordpress-7-1/>
    - WordPress 7.1 Field Guide: <https://make.wordpress.org/core/2026/08/05/wordpress-7-1-field-guide/>
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related