WordPress Block Editor (Gutenberg): Building Custom Blocks for Clients | SoniNow Blog

Limited TimeLearn More

wordpressgutenbergcustom blocksreactcms

WordPress Block Editor (Gutenberg): Building Custom Blocks for Clients

Published

2026-06-23

Read Time

4 mins

WordPress Block Editor (Gutenberg): Building Custom Blocks for Clients

The WordPress Block Editor, known as Gutenberg, has matured into a powerful content authoring environment. For developers building client sites, custom blocks are no longer optional — they are the primary way to deliver tailored editing experiences without relying on third-party page builders. Custom blocks give clients a clear, structured editing interface while giving developers full control over the output markup and styling.

Setting Up Your Block Development Environment

The official @wordpress/create-block package scaffolds a modern block development environment with webpack, ESBuild, and the WordPress scripts package. Run it from your theme or plugin directory:

npx @wordpress/create-block custom-testimonial --namespace soninow

This generates a structured plugin with src/, build/, and block metadata in block.json. The block.json file defines the block's name, title, icon, category, attributes, and supports — this metadata-driven approach means WordPress handles registration automatically.

{
  "apiVersion": 3,
  "name": "soninow/testimonial",
  "title": "Testimonial",
  "icon": "format-quote",
  "category": "widgets",
  "attributes": {
    "quote": { "type": "string", "source": "html", "selector": "blockquote" },
    "author": { "type": "string", "source": "text", "selector": ".author" }
  },
  "supports": { "align": true }
}

Building the Edit Component with React

The Edit component renders in the Block Editor and controls how authors interact with your block. Use useBlockProps to get the editor wrapper attributes, and RichText for editable content areas:

import { RichText, useBlockProps } from '@wordpress/block-editor';

export default function Edit({ attributes, setAttributes }) {
  const blockProps = useBlockProps();
  return (
    <div {...blockProps}>
      <RichText
        tagName="blockquote"
        value={attributes.quote}
        onChange={(quote) => setAttributes({ quote })}
        placeholder="Enter testimonial..."
      />
      <RichText
        tagName="p"
        className="author"
        value={attributes.author}
        onChange={(author) => setAttributes({ author })}
        placeholder="— Author name"
      />
    </div>
  );
}

Use InspectorControls to add block settings in the sidebar — color pickers, alignment toggles, padding controls. Register these as panel bodies within the BlockControls or InspectorControls slot.

Leveraging InnerBlocks for Flexible Layouts

For complex blocks like grid layouts or multi-column sections, InnerBlocks allow authors to nest any registered block inside yours. This is how the Columns and Group blocks work in core. Register allowed block types to constrain what authors can insert:

import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';

const ALLOWED_BLOCKS = ['core/image', 'soninow/testimonial', 'core/paragraph'];

export default function Edit() {
  return (
    <div {...useBlockProps()}>
      <InnerBlocks allowedBlocks={ALLOWED_BLOCKS} />
    </div>
  );
}

The Save component for dynamic blocks can simply return null if you render the block server-side with PHP — this keeps your block's output fully customizable without rebuilding the frontend bundle.

Creating Block Patterns and Templates

Block patterns are pre-made layouts that clients can insert with one click. Register them in your theme's functions.php:

register_block_pattern('soninow/hero-section', [
  'title' => 'Hero Section',
  'description' => 'Full-width hero with heading, text, and CTA button',
  'categories' => ['soninow'],
  'content' => '<!-- wp:cover -->...<!-- /wp:cover -->',
]);

Block templates define the default content of a custom post type. For a "Case Study" post type, you could pre-populate the editor with blocks for project overview, results, and testimonial.

Compiling and Deploying Blocks

Run npm run build to compile your block assets into the build/ folder. The WordPress plugin will automatically register the blocks when activated. For client deployments, consider keeping blocks in a must-use plugin (wp-content/mu-plugins/) so they are always active and cannot be accidentally deactivated.

Testing Block Compatibility

Test your blocks across the full Gutenberg compatibility matrix — the List View, the Navigation block, the Style Book, and wp:pattern synced patterns. Each update to WordPress core can introduce breaking changes to block APIs, so maintain a CI pipeline that runs block rendering tests against the latest WP version.

Custom Gutenberg blocks are the foundation of a modern WordPress development workflow. SoniNow's WordPress development team builds tailor-made block ecosystems for agencies and brands. Let's build something exceptional together.