Nice — here’s a clear, practical, step-by-step implementation for Module 10 — Creating Gutenberg (Block Editor) Blocks. I give a no-build approach (works immediately — no npm or build tools) plus an optional modern build path (recommended for production). Follow the steps exactly and you’ll have a working “Hello Block” in the editor.
Quick summary (what you’ll create)
Folder: my-block-plugin/
Files:
-
my-block-plugin.php — plugin bootstrap (registers scripts & block)
-
block/index.js — block editor script (no-build version)
-
block/editor.css — styles for the editor
-
block/style.css — front-end styles
❗ Prerequisites
-
WordPress site with admin access
-
PHP & WP (no extra tooling required for the no-build version)
-
If you want the modern build path: Node.js + npm (optional)
STEP-BY-STEP — No-build approach (fastest)
1) Create plugin folder
Path:
wp-content/plugins/my-block-plugin/
2) Create my-block-plugin.php
File: wp-content/plugins/my-block-plugin/my-block-plugin.php
Paste this full code:
<?php
/**
* Plugin Name: My Gutenberg Block
* Description: Adds a simple "Hello Block" (no-build example).
* Version: 1.0
* Author: Your Name
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
function mgb_register_block() {
// register editor script (no build - using WordPress provided globals)
wp_register_script(
'mgb-block-js',
plugins_url( 'block/index.js', __FILE__ ),
array( 'wp-blocks', 'wp-element', 'wp-editor' ), // dependencies
filemtime( plugin_dir_path( __FILE__ ) . 'block/index.js' )
);
wp_register_style(
'mgb-block-editor-style',
plugins_url( 'block/editor.css', __FILE__ ),
array(),
filemtime( plugin_dir_path( __FILE__ ) . 'block/editor.css' )
);
wp_register_style(
'mgb-block-style',
plugins_url( 'block/style.css', __FILE__ ),
array(),
filemtime( plugin_dir_path( __FILE__ ) . 'block/style.css' )
);
register_block_type( 'mgb/hello-block', array(
'editor_script' => 'mgb-block-js',
'editor_style' => 'mgb-block-editor-style',
'style' => 'mgb-block-style',
) );
}
add_action( 'init', 'mgb_register_block' );
Explanation: this registers the JS and CSS, and declares the block type mgb/hello-block. filemtime() forces browsers to reload when you change files.
3) Create block/index.js (no-build, uses wp.* globals)
File: wp-content/plugins/my-block-plugin/block/index.js
Paste:
( function ( wp ) {
const el = wp.element.createElement;
const registerBlockType = wp.blocks.registerBlockType;
const { RichText } = wp.blockEditor || wp.editor; // compatibility
registerBlockType( 'mgb/hello-block', {
title: 'Hello Block',
icon: 'smiley',
category: 'widgets',
attributes: {
content: {
type: 'string',
source: 'html',
selector: 'p'
}
},
edit: function ( props ) {
const content = props.attributes.content;
return el(
'div',
{ className: 'mgb-hello-block' },
el( RichText, {
tagName: 'p',
onChange: function ( value ) { props.setAttributes( { content: value } ); },
value: content,
placeholder: 'Say hello... 👋'
} )
);
},
save: function ( props ) {
return el( wp.blockEditor.RichText.Content || wp.RichText.Content, {
tagName: 'p',
value: props.attributes.content
} );
}
} );
} )( window.wp );
Notes:
4) Create editor & front-end CSS
block/editor.css (editor view styling):
.mgb-hello-block {
background: #002b36;
border-radius: 10px;
padding: 10px;
color: #00ffa3;
}
block/style.css (front-end styling):
.mgb-hello-block p {
font-size: 18px;
color: #00d4ff;
margin: 0;
}
5) Activate plugin & test
-
Zip or copy folder to wp-content/plugins/ (already done).
-
In WP Admin: Plugins → Activate “My Gutenberg Block”.
-
Edit or create a post: Add block → search “Hello Block” (category: Widgets).
-
Type text in the block, save/update post, view on front-end.
If block does not appear: flush caches, ensure WP version >= 5.x (Gutenberg built-in).
Troubleshooting (no-build)
-
If block fails to load, open browser console — missing wp globals indicate block script loaded on front-end instead of editor. Ensure editor_script is registered — you used register_block_type() correctly.
-
If icons or editor UI missing, check dependencies: 'wp-blocks','wp-element','wp-editor'. For newer WP, consider 'wp-block-editor' too.
-
If CSS not loading: check file paths and permissions.
OPTIONAL: Modern build path (recommended for production)
If you want JSX, ESNext, and modules — use @wordpress/scripts. Short steps:
-
cd my-block-plugin/block
-
npm init -y
-
npm install @wordpress/scripts --save-dev
-
Create src/index.js (JSX) and build/index.js generated by the tool.
-
Add package.json scripts:
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start"
}
-
Example src/index.js (JSX version):
import { registerBlockType } from '@wordpress/blocks';
import { RichText } from '@wordpress/block-editor';
import { createElement } from '@wordpress/element';
registerBlockType('mgb/hello-block', {
title: 'Hello Block',
icon: 'smiley',
category: 'widgets',
attributes: {
content: { type: 'string', source: 'html', selector: 'p' }
},
edit: ({ attributes, setAttributes }) => (
createElement('div', { className: 'mgb-hello-block' },
createElement(RichText, {
tagName: 'p',
onChange: value => setAttributes({ content: value }),
value: attributes.content,
placeholder: 'Say hello... 👋'
})
)
),
save: ({ attributes }) => (
createElement(RichText.Content, {
tagName: 'p',
value: attributes.content
})
)
});
-
Run npm run build → this produces build/index.js. Update PHP to point to block/build/index.js instead of block/index.js.
Advantages: cleaner code, JSX, compatibility with future WP patterns.
Extra tips & best practices
-
Use editor_style and style keys in register_block_type() to keep editor and front-end styles separate.
-
Use attributes carefully — define types and sources to keep data serializable.
-
For complex blocks, use InspectorControls to add sidebar controls.
-
For localization, wrap strings with __() and load textdomain in PHP if you plan to translate.
Quick checklist before testing
If you want, I can:
-
Generate the exact plugin ZIP you can download and install, or
-
Convert the no-build JS to a modern @wordpress/scripts project with package.json and full src/ build files ready to npm install + npm run build.
Which next?