Matthew Hodge
Full Stack Developer

Creating multiple Gutenberg blocks doesn't mean you need multiple plugins. Let's explore how to create a single plugin that can house multiple blocks efficiently.

Initial Setup

First, create your plugin's base structure using the @wordpress/create-block tool, we will be creating a plugin called "demo" for the sake of this tutorial, if you use a different name update references accordingly.

cd wp-content/plugins
npx @wordpress/create-block@latest demo

This creates your plugin's basic structure with one block. Now, let's add more blocks to it.

Adding Additional Blocks

Navigate to your plugin's source directory:

cd demo/src

Create additional blocks using the --no-plugin flag to avoid generating unnecessary plugin files, I have just called my two additional blocks "foo" and "bar" respectively, if you use different names update references accordingly

npx @wordpress/create-block@latest foo --no-plugin
npx @wordpress/create-block@latest bar --no-plugin

Plugin Structure

Your directory structure should now look like something like this:

demo/
├── src/
│   ├── demo/
│   ├── foo/
│   ├── bar/
└── demo.php

Update the demo.php file to enable loading the additional blocks

The generated demo.php file will look something like this

<?php
/**
 * Plugin Name:       Demo
 * Description:       Example block scaffolded with Create Block tool.
 * Version:           0.1.0
 * Requires at least: 6.7
 * Requires PHP:      7.4
 * Author:            The WordPress Contributors
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       demo
 *
 * @package CreateBlock
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
function create_block_demo_block_init() {
    register_block_type( __DIR__ . '/build/demo' );
}
add_action( 'init', 'create_block_demo_block_init' );

Lets update the create_block_demo_block_init to allow it to use ALL our blocks

Replace

function create_block_demo_block_init() {
    register_block_type( __DIR__ . '/build/demo' );
}
add_action( 'init', 'create_block_demo_block_init' );

With this

function create_block_demo_blocks_init() {
    $blocks = array_map( function( $block ) {
        return [
            'name' => $block,
        ];
    }, array_filter( scandir( __DIR__ . '/build' ), function( $block ) {
        return $block[0] !== '.' && is_dir( __DIR__ . '/build/' . $block );
    } ) );

    foreach ( $blocks as $block ) {
        register_block_type( __DIR__  . '/build/' . $block['name'] );
    }
}
add_action( 'init', 'create_block_demo_blocks_init' );

Building Your Blocks

To build all blocks for production:

npm run build

For development with live reload:

npm run start

Block Usage

You can now navigate to the post and or page you would like to include your relevant block after altering the functionality as you desire

Using the blocks

When navigating to the front end you can now see the blocks which will display the content accordingly

Front end view of the blocks

This approach allows you to maintain multiple Gutenberg blocks within a single plugin, making maintenance and updates more manageable. Each block remains independent but shares the same build process and plugin infrastructure.

For more information, check out the @wordpress/create-block.