{"slug":"gutenberg-block-development","title":"Gutenberg Block Development","tags":["gutenberg","blocks","javascript","react","block-editor"],"agent_summary":"Custom Gutenberg block development using PHP server-side rendering and JavaScript/React with @wordpress/scripts build tooling, block.json API version 3, and RichText editor integration.","trigger_phrases":["gutenberg block","custom block wordpress","register_block_type","wordpress blocks","block editor development","wp-scripts build","block.json wordpress"],"runnable":true,"markdown":"\nGutenberg supports custom blocks via PHP (server-side render) or JavaScript (React). Use PHP SSR for dynamic content, JS for interactive editing.\n\n## PHP — Server-Side Rendering\n\n```php\n// Register block\nfunction register_testimonial_block() {\n    register_block_type('myplugin/testimonial', [\n        'render_callback' => 'render_testimonial_block',\n        'attributes'      => [\n            'quote'  => ['type' => 'string', 'default' => ''],\n            'author' => ['type' => 'string', 'default' => ''],\n            'rating' => ['type' => 'integer', 'default' => 5],\n        ],\n    ]);\n}\nadd_action('init', 'register_testimonial_block');\n\nfunction render_testimonial_block($attributes) {\n    $quote  = esc_html($attributes['quote'] ?? '');\n    $author = esc_html($attributes['author'] ?? '');\n    return \"<blockquote class='wp-block-testimonial'><p>{$quote}</p><cite>{$author}</cite></blockquote>\";\n}\n```\n\n## JavaScript — React Block\n\n```javascript\nimport { registerBlockType } from '@wordpress/blocks';\nimport { RichText, useBlockProps } from '@wordpress/block-editor';\n\nregisterBlockType('myplugin/testimonial', {\n    title: 'Testimonial',\n    category: 'content',\n    attributes: {\n        quote:  { type: 'string', source: 'html', selector: 'p' },\n        author: { type: 'string', source: 'html', selector: 'cite' },\n    },\n    edit({ attributes, setAttributes }) {\n        const blockProps = useBlockProps();\n        return (\n            <blockquote {...blockProps}>\n                <RichText\n                    tagName=\"p\"\n                    value={attributes.quote}\n                    onChange={(quote) => setAttributes({ quote })}\n                    placeholder=\"Enter quote...\"\n                />\n                <RichText\n                    tagName=\"cite\"\n                    value={attributes.author}\n                    onChange={(author) => setAttributes({ author })}\n                    placeholder=\"Author name...\"\n                />\n            </blockquote>\n        );\n    },\n    save({ attributes }) {\n        const blockProps = useBlockProps.save();\n        return (\n            <blockquote {...blockProps}>\n                <RichText.Content tagName=\"p\" value={attributes.quote} />\n                <RichText.Content tagName=\"cite\" value={attributes.author} />\n            </blockquote>\n        );\n    },\n});\n```\n\n## Build Setup\n\n```bash\nnpm install @wordpress/scripts --save-dev\n```\n\npackage.json:\n```json\n{\n  \"scripts\": {\n    \"build\": \"wp-scripts build\",\n    \"start\": \"wp-scripts start\"\n  }\n}\n```\n\n## block.json (API Version 3 — WP 5.8+)\n\n```json\n{\n    \"$schema\": \"https://schemas.wp.org/trunk/block.json\",\n    \"apiVersion\": 3,\n    \"name\": \"myplugin/testimonial\",\n    \"title\": \"Testimonial\",\n    \"category\": \"content\",\n    \"icon\": \"format-quote\",\n    \"editorScript\": \"file:./index.js\",\n    \"style\": \"file:./style-index.css\"\n}\n```\n","html":"<p>Gutenberg supports custom blocks via PHP (server-side render) or JavaScript (React). Use PHP SSR for dynamic content, JS for interactive editing.</p>\n<h2>PHP — Server-Side Rendering</h2>\n<pre><code class=\"language-php\">// Register block\nfunction register_testimonial_block() {\n    register_block_type('myplugin/testimonial', [\n        'render_callback' => 'render_testimonial_block',\n        'attributes'      => [\n            'quote'  => ['type' => 'string', 'default' => ''],\n            'author' => ['type' => 'string', 'default' => ''],\n            'rating' => ['type' => 'integer', 'default' => 5],\n        ],\n    ]);\n}\nadd_action('init', 'register_testimonial_block');\n\nfunction render_testimonial_block($attributes) {\n    $quote  = esc_html($attributes['quote'] ?? '');\n    $author = esc_html($attributes['author'] ?? '');\n    return \"&#x3C;blockquote class='wp-block-testimonial'>&#x3C;p>{$quote}&#x3C;/p>&#x3C;cite>{$author}&#x3C;/cite>&#x3C;/blockquote>\";\n}\n</code></pre>\n<h2>JavaScript — React Block</h2>\n<pre><code class=\"language-javascript\">import { registerBlockType } from '@wordpress/blocks';\nimport { RichText, useBlockProps } from '@wordpress/block-editor';\n\nregisterBlockType('myplugin/testimonial', {\n    title: 'Testimonial',\n    category: 'content',\n    attributes: {\n        quote:  { type: 'string', source: 'html', selector: 'p' },\n        author: { type: 'string', source: 'html', selector: 'cite' },\n    },\n    edit({ attributes, setAttributes }) {\n        const blockProps = useBlockProps();\n        return (\n            &#x3C;blockquote {...blockProps}>\n                &#x3C;RichText\n                    tagName=\"p\"\n                    value={attributes.quote}\n                    onChange={(quote) => setAttributes({ quote })}\n                    placeholder=\"Enter quote...\"\n                />\n                &#x3C;RichText\n                    tagName=\"cite\"\n                    value={attributes.author}\n                    onChange={(author) => setAttributes({ author })}\n                    placeholder=\"Author name...\"\n                />\n            &#x3C;/blockquote>\n        );\n    },\n    save({ attributes }) {\n        const blockProps = useBlockProps.save();\n        return (\n            &#x3C;blockquote {...blockProps}>\n                &#x3C;RichText.Content tagName=\"p\" value={attributes.quote} />\n                &#x3C;RichText.Content tagName=\"cite\" value={attributes.author} />\n            &#x3C;/blockquote>\n        );\n    },\n});\n</code></pre>\n<h2>Build Setup</h2>\n<pre><code class=\"language-bash\">npm install @wordpress/scripts --save-dev\n</code></pre>\n<p>package.json:</p>\n<pre><code class=\"language-json\">{\n  \"scripts\": {\n    \"build\": \"wp-scripts build\",\n    \"start\": \"wp-scripts start\"\n  }\n}\n</code></pre>\n<h2>block.json (API Version 3 — WP 5.8+)</h2>\n<pre><code class=\"language-json\">{\n    \"$schema\": \"https://schemas.wp.org/trunk/block.json\",\n    \"apiVersion\": 3,\n    \"name\": \"myplugin/testimonial\",\n    \"title\": \"Testimonial\",\n    \"category\": \"content\",\n    \"icon\": \"format-quote\",\n    \"editorScript\": \"file:./index.js\",\n    \"style\": \"file:./style-index.css\"\n}\n</code></pre>\n"}