Get started with Blank Blocks Plugin

If you are getting started with blocks, you can always use the official ‘@wordpress/create-block’ application to generate a new plugin with a single block. This new plugin would be fine for some use cases, but I prefer a more robust solution.

I have prepared a new blank plugin that is good as a starting point for creating a new plugin that will contain one or more blocks. And, this blank plugin uses different block registration methods, and it is more veritable for real-world usage. So far, I have used this method for all the plugins I made with blocks (with some modifications, depending on the plugin).

You can get this blank plugin from Github:

The plugin contains one very basic block that has no settings, and it just renders simple content with some styling applied. But, it is easy to modify, and easy to start building your own blocks.

The plugin structure

Main plugin file ‘blank-blocks-plugin.php’, is a fairly basic one, it defines few constants with path and URL for the plugin, loads PHP file holding all the code we need (class Blocks in ‘code/blocks-registration.php’ file), and run the instance of the class Blocks. Directory ‘src’ contains our blocks JavaScript and SASS files (for styling). And, finally, it has a ‘build’ directory where the blocks compiled JavaScript and CSS will be placed.

Blocks Source

Directory ‘src’ contains an ‘index.js’ file that is used as a starting point for compiling the final JavaScript, and inside of this file, we are going to load all the blocks we have. This example has one block, and the index.js looks like this:

 Load each block here, by linking to block's index.js file.
import './blocks/block/index.js';

All blocks are placed inside the ‘blocks’ directory, and we have a ‘helpers’ directory for some shared code that is used in multiple blocks. Inside the ‘helpers’ directory, we now have an ‘icons.js’ file where we have constant Icons with one or more SVG icons. You are perfectly fine using WordPress DashIcons, or placing SVG inside the blocks JavaScript directly, but I find it much better to have all the SVG icons defined in your own file, because it is possible that you will reuse icons, not to mention, that it is much easier to maintain SVG files in one place.

Each block inside the ‘blocks’ directory has its own directory. This example has one block, and that block is placed inside the directory called ‘block’. The block needs only one file (the file you import inside the main JavaScript file), but for the readability of the code, each block code is split into multiple files, and loaded inside the ‘index.js’ for each block.

This is the recommended structure for each block. The index is the main entry point. We use ‘block’ for the block name, but give it any name you want.

└── block/
    ├── edit.js
    ├── editor.scss
    ├── index.js
    ├── save.js
    └── style.scss
Block – index.js

For all intense and purposes, this is the code for one block. It starts with the import directives to load core libraries and functions. After that, we import the SASS file with the block styling (so it will be compiled when the plugin build process is run). This is the actual styling of the block, and it is loaded in the block editor and on the frontend.

 Main file for a block, using import directives to load various core libraries.
import {__} from '@wordpress/i18n';
import {registerBlockType} from '@wordpress/blocks';

 Include SASS file with styling for the block.
 If you don't have dedicated styling file for the block, remove this.
import './style.scss';

 * Import functions for Edit and Save, and Icons constant with SVG icons.
import Edit from './edit';
import Save from './save';
import Icons from "../../helpers/icons";

 * Register the new block
registerBlockType('millan-dev/blank-block', {
    apiVersion: 2,
    name: 'millan-dev/blank-block',
    title: __('Blank Block', 'blank-blocks-plugin'),
    description: __('Simple blank block', 'blank-blocks-plugin'),
    category: 'widgets',
    icon: Icons.icon,
    supports: {},
    attributes: {},
    edit: Edit,
    save: Save,

Next comes the import for Edit and Save functions. These are imported from edit.js and save.js files for this block. We also import the Icons constant with the SVG icons we need to use.

Finally, the block is registered. Each block name has two parts namespace/name. The namespace part should be unique for the plugin, and all the blocks in this plugin should use the same namespace, followed by the actual block name. So, here we have the namespace set to ‘millan-dev’, and the block name to ‘blank-block’. Block registration attributes should contain block title and description, category, icon. Property ‘supports’ is very important because it configures various aspects for the block, including the automatic inclusion of various inspector elements. To learn more about it, check the official documentation.

For the category you can use any of the default categories: text, media, design, widgets, theme, embed, reusable.

Can I add my own category for blocks in the block editor?

Yes. New categories can be defined using PHP code, and WordPress filter ‘block_categories_all‘. Each category is defined with ‘slug’ and ‘title’. More information about that will be included later in this article.

Property attributes contain all the block settings, and finally, we are setting ‘edit’ and ‘save’ properties by assigning imported functions.

Block – edit.js

This file is used to define how the block works and behaves in the editor. This blank template shows a single paragraph of text. It also imports ‘editor.scss’ with the SASS styling that will be used in block editor only.

 Edit function for the block.
import {__} from '@wordpress/i18n';
import {useBlockProps} from '@wordpress/block-editor';

 Include SASS file with editor styling only for the block.
 This will be compiled into file loaded only inside the editor.
 If you don't have dedicated styling file for the block, remove this.
import './editor.scss';

export default function Edit({attributes, setAttributes}) {
    return (
        <p {...useBlockProps()}>
            {__('Blank Blocks Plugin - Just a placeholder!', 'blank-blocks-plugin')}
Block – save.js

This file is used to define what happens when the block has changed, and what is saved as content for that block. Any change made in the editor will trigger the Save function also, and it will generate markup for the block to be saved in the post content.

 Edit function for the block.
import {__} from '@wordpress/i18n';
import {useBlockProps} from '@wordpress/block-editor';

export default function Save({attributes}) {
    return (
        <p {}>
            {__('Blank Blocks Plugin - Just a placeholder!', 'blank-blocks-plugin')}
Block – style.scss and editor.scss

These two files are SASS styling files, and they are used to define CSS styling for the block. File ‘style.scss’ is the main one, and that is the styling loaded both inside the editor and on the frontend. And, ‘editor.scss’ is the styling that is loaded inside the editor only. If there is something you want to add to the block styling while it is edited, it should be done with the ‘editor.scss’ file.

By default, each block class name is created as ‘wp-block-{namespace}-{name}’. Namespace and name are what we used for our block to define the block name, and for this blank block that is ‘millan-dev’ and ‘blank-block’ respectively, so the class name for the block would be ‘wp-block-millan-dev-blank-block’.

Blocks Build

The block source code is pretty much useless when it comes to running the plugin. It has to be compiled, and the compiled files are stored inside the ‘build’ directory. There are several files located there.

├── index.asset.php
├── index.css
├── index.js
└── style-index.css

The PHP file added there contains information needed for the blocks code enqueue and loading (we will see that a bit later). File ‘index.css’ is the compiled CSS for the style to be used in the editor only. And, ‘index.js’ is the compiled JavaScript for our books, and it is also loaded in editor only. Finally, ‘style-index.css’ is the compiled styling for our blocks, loaded in the editor and on the frontend.

PHP Code

For this blank plugin, all the PHP code needed is inside the ‘code’ directory, file ‘blocks-registration.php’. For your plugin, you can move this code somewhere else, but I try to keep all the block-related PHP code inside one class.

This class has a code to register a new blocks category (if you want to use it), and it is defined through WordPress filter ‘block_categories_all’.

Do not abuse custom categories!

It is perfectly fine to define custom categories for blocks in the editor. But, do not do that if you are adding one or two blocks only. If every plugin adds blocks in its own category, it would create a mess. You should place blocks into one of the default categories, if possible, or create a new category if you are adding more than 3 blocks.

To register all needed CSS and JS files, we have the ‘register_files()’ method that uses the ‘index.asset.php’ file from the ‘build’ directory. This file contains an array with JavaScript dependencies, and a version identifier (the hash string that should be unique.

Finally, inside the ‘register_blocks()’ method, we have PHP code to register each block and define scripts and styles dependencies (from files we registered in the previous step). This registration method can be expanded with other stuff, but for this example, they are enough.

Development and Building

Blocks development requires quite a few things, and two basic components are Node.js and NPM. I am not going to detail here how to install them (it depends on your operating system), and it is very possible that you already have both. If you don’t, there are plenty of tutorials on the internet. Once you have the Node and NPM up and running, you can proceed with setting up the environment for your plugin.

This basic plugin comes with a ‘package.json’ file that describes what libraries and dependencies are needed. When you are starting with the new project, you need to run an installation process that will use the package file to download what is needed. To do that, open your plugin directory in the command prompt, and run NPM install:

npm install

This process will take a while, and will download close to 500 MB of node modules needed for the build process.

And, during development, you can have a build monitor running that will detect changes to the plugin files (‘src’ directory only), and compile debug versions of the JavaScript and CSS on the fly. Once you are ready, you can build the distribution version.

# start the development and webpack watch process
npm start

# build production/distribution code
npm run build

# update all the packages to the latest versions
npm run packages-update


This is a fully functional starter plugin for adding blocks. You can use it as is, by renaming the plugin and blocks, or you can incorporate it inside your own plugin, it is up to you.

Let me know if you have any questions about the plugin, or some suggestions for it, or for future tutorials related to blocks development.

Please wait...

Leave a Comment