You are currently viewing Building Custom Gutenberg Blocks with Claude Code

Building Custom Gutenberg Blocks with Claude Code

Unchecked AI agent output in your block editor codebase will introduce cross-site scripting vulnerabilities and broken React state loops before your agency even completes its sprint. Claude Code—Anthropic’s agentic CLI tool powered by Claude 3.7 Sonnet—operates directly inside local terminal workflows. It reads your file trees, executes @wordpress/create-block, and modifies React components across your source directories in seconds. Speed is not code quality.
Founders and CTOs evaluating AI toolchains must recognize that while Claude Code automates repetitive boilerplate, it regularly produces subtle, expensive defects in WordPress Block API v3 builds.

Agency development teams waste billable hours debugging auto-generated Gutenberg components because terminal assistants treat React controls and block.json schemas as isolated artifacts. Handing block scaffolding over to an AI agent requires tight guardrails, strict local build checks, and mandatory manual code reviews.

Terminal-Driven Block Scaffolding Creates Schema Drift

Scaffolding a modern Gutenberg block begins in the local terminal using @wordpress/create-block alongside custom parameters. When prompting Claude Code to generate a dynamic content block, the CLI runs node commands, builds directory structures, and wires up initial files like block.json, edit.js, and render.php.

The main breakdown happens when you update interactive block attributes later in development. When you instruct Claude Code to add a toggle control or a text control inside edit.js, the agent frequently modifies the React component without updating the matching attribute definitions inside block.json.

Responsibility LayerClaude Code CapabilityHuman Developer Requirement
ScaffoldingExecutes @wordpress/create-blockDefines plugin architecture
Attribute ManagementWrites React state controlsSyncs block.json API v3 schema
Dynamic RenderingGenerates render.php callbacksEnforces wp_kses_post escaping
AccessibilityImplements basic HTML markupInjects @wordpress/a11y feedback
Build VerificationRuns npm run build scriptsValidates build/index.asset.php

In Block API v3, an undeclared attribute in block.json causes raw attributes passed to render.php to drop silently or render as undefined in the WordPress admin editor. Developers must enforce strict prompt rules or manually inspect block.json whenever component props change in edit.js.

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "swastikaa/testimonial-card",
  "title": "Testimonial Card",
  "category": "widgets",
  "attributes": {
    "authorName": {
      "type": "string",
      "default": ""
    },
    "quoteText": {
      "type": "string",
      "default": ""
    }
  },
  "textdomain": "swastikaa-blocks",
  "editorScript": "file:./build/index.js",
  "render": "file:./render.php"
}

Inspecting Generated JSX and Enforcing Escaping in Render Callbacks

Claude Code excels at writing boilerplate React components using @wordpress/components. It quickly imports RichText, InspectorControls, PanelBody, and TextControl into edit.js. However, generated JSX routinely omits necessary block wrapper hooks or misplaces useBlockProps().

Without useBlockProps() applied directly to the outermost element in edit.js, Gutenberg’s block alignment controls, custom CSS class injections, and inspector sidebar styles fail.

import { useBlockProps, RichText, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, TextControl } from '@wordpress/components';

export default function Edit({ attributes, setAttributes }) {
    const blockProps = useBlockProps();
    const { authorName, quoteText } = attributes;

    return (
        <div { ...blockProps }>
            <InspectorControls>
                <PanelBody title="Author Settings">
                    <TextControl
                        label="Author Name"
                        value={ authorName }
                        onChange={ ( value ) => setAttributes( { authorName: value } ) }
                    />
                </PanelBody>
            </InspectorControls>
            <RichText
                tagName="blockquote"
                value={ quoteText }
                onChange={ ( value ) => setAttributes( { quoteText: value } ) }
                placeholder="Enter quote..."
            />
        </div>
    );
}

The severe risk emerges in the backend dynamic render file (render.php). Claude Code frequently writes raw PHP output, omitting standard WordPress sanitization and escaping functions.

<?php
/**
 * Dynamic block render template
 */
$wrapper_attributes = get_block_wrapper_attributes();
$author_name        = $attributes['authorName'] ?? '';
$quote_text         = $attributes['quoteText'] ?? '';
?>

<div <?php echo $wrapper_attributes; ?>>
    <blockquote class="wp-block-swastikaa-testimonial-quote">
        <?php echo wp_kses_post( $quote_text ); ?>
    </blockquote>
    <p class="wp-block-swastikaa-testimonial-author">
        — <?php echo esc_html( $author_name ); ?>
    </p>
</div>

If the AI agent leaves $quote_text unescaped, malicious actors with contributor-level site access can execute stored XSS attacks through block attribute fields. Every dynamic callback generated by AI requires mandatory replacement of raw variables with esc_html(), esc_attr(), or wp_kses_post().

Fixing Accessibility Gaps and Asset Dependencies in React Controls

Auto-generated Gutenberg blocks routinely fail basic web accessibility requirements. Claude Code will construct interactive components—such as custom accordion toggles or modal dialogues inside edit.js—without adding appropriate ARIA attributes or dynamic screen reader announcements.

WordPress provides the @wordpress/a11y package specifically to handle live region notifications within the editor interface. When a user updates a custom block setting or triggers an async fetch inside the editor sidebar, screen readers stay silent unless speak() is explicitly invoked.

AI code generators reliably construct visible UI elements, but they treat invisible accessibility standards and screen reader announcements as optional afterthoughts.

Another failure point lies in dependency management within build/index.asset.php. When running @wordpress/scripts during local compilation, wp-scripts build inspects imports inside your React code to auto-generate the dependency array.
If Claude Code imports raw third-party npm packages instead of core @wordpress packages, total bundle sizes explode and site performance drops across frontend page loads.

Engineers must verify that scripts rely on native WordPress global handles like wp-element, wp-i18n, wp-components, and wp-block-editor rather than bundling redundant external libraries into compiled JavaScript assets.

The Production Readiness Audit for Claude-Generated Blocks

Before merging any AI-assisted block component into production repositories, engineering teams must execute a standardised human verification checklist.

  • Schema Consistency: Compare every attribute referenced in edit.js against the attributes object in block.json to prevent state dropping.
  • Contextual Escaping: Inspect every PHP output variable in render.php or render_callback functions for explicit wp_kses_post() or esc_html() wrappers.
  • Block Wrapper Props: Confirm that useBlockProps() is called on the root container in edit.js and get_block_wrapper_attributes() is rendered on the outer container in PHP.
  • Accessibility Compliance: Verify that interactive editor controls include proper aria-expanded, aria-controls, and @wordpress/a11y speak announcements.
  • Asset Dependency Verification: Open build/index.asset.php after running npm run build to ensure core WordPress script dependencies are declared correctly.
  • Translation Wrapping: Check that strings inside React components use __('Text', 'domain') from @wordpress/i18n and PHP strings use standard WordPress i18n functions.

Stop Shipping Unverified Terminal Output to Client Workspaces

Treating Claude Code as an automated replacement for WordPress engineering expertise guarantees security vulnerabilities and broken block layouts across client websites. Use Claude Code for fast CLI scaffolding, boilerplate code generation, and rapid component prototyping inside your development environment.

Reserve structural decisions, security escaping, performance optimisations, and accessibility compliance for senior humans who understand WordPress Block API internals. Run npm run build, Inspect your generated PHP output line by line, and never push raw terminal outputs directly to production client repositories.


Leave a Reply