Since the introduction of the Gutenberg editor in WordPress 5.0, the concept of blocks has revolutionized content creation and theme development. Blocks provide a modular, visual, and consistent way to build websites—making WordPress more like a true page builder.
In this guide, we’ll cover:
- What blocks are
- Why they matter
- How to build custom blocks using React
- The role of
@wordpress/scripts
- How you can use any JavaScript framework—not just React
Let’s dive in.
🔸 What Are WordPress Blocks?
Blocks are the fundamental building units of content in the WordPress block editor (Gutenberg). Each piece of content—paragraphs, images, videos, buttons, widgets—is a block that users can drag, edit, rearrange, and customize visually.
🧱 Examples of Core Blocks:
- Paragraph
- Image
- Heading
- Quote
- List
- Button
- Gallery
- Columns
- Embed (YouTube, Twitter, Spotify, etc.)
These blocks are saved in post_content
as structured HTML and rendered seamlessly on the front end.
🚀 Why Block Development Matters
Custom blocks empower developers to:
- Build tailored content elements for clients
- Reduce reliance on shortcodes or meta fields
- Offer better editorial experience via WYSIWYG
- Align design components with branding and UX goals
If you build custom themes or plugins, block development is the future of WordPress customization.
🧱 Anatomy of a Block
Every custom block consists of:
-
block.json
: Metadata and block config - JavaScript: UI logic, typically using React
- Optional PHP (for dynamic blocks)
- Stylesheets: Editor and front-end CSS
Let’s break this down with a real example.
block.json
{
"apiVersion": 2,
"name": "myplugin/notice",
"title": "Notice Block",
"icon": "megaphone",
"category": "widgets",
"description": "A custom notice block.",
"editorScript": "file:./index.js",
"style": "file:./style.css"
}
index.js
– Editor Logic
import { registerBlockType } from '@wordpress/blocks';
import { RichText } from '@wordpress/block-editor';
registerBlockType('myplugin/notice', {
attributes: {
content: {
type: 'string',
source: 'html',
selector: 'p'
}
},
edit: ({ attributes, setAttributes }) => (
<RichText
tagName="p"
value={attributes.content}
onChange={(content) => setAttributes({ content })}
placeholder="Enter notice text"
/>
),
save: ({ attributes }) => (
<RichText.Content tagName="p" value={attributes.content} />
)
});
style.css
.wp-block-myplugin-notice {
padding: 1em;
border-left: 4px solid #0073aa;
background-color: #f0f8ff;
}
⚛️ Using React in WordPress Blocks
WordPress blocks use React under the hood, but the experience is simplified thanks to the Gutenberg framework and @wordpress/element
, which is a thin wrapper around React.
You can use familiar JSX syntax, state, props, and even React hooks:
import { useState } from '@wordpress/element';
const Edit = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times.</p>
<button onClick={() => setCount(count + 1)}>Click Me</button>
</div>
);
};
This React integration is possible thanks to
@wordpress/scripts
, which compiles modern JS automatically.
🛠 What is @wordpress/scripts
?
The @wordpress/scripts
package gives you a zero-config development environment for building Gutenberg blocks. It includes:
- Webpack for bundling
- Babel for JSX/ESNext
- PostCSS + Autoprefixer
- Built-in support for SCSS, JS, JSON
- React support via
@wordpress/element
Installation:
npm install --save-dev @wordpress/scripts
In package.json
:
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start"
}
You can now write modern JavaScript and JSX out of the box without setting up Webpack or Babel manually.
⚙️ You're Not Limited to React
Although Gutenberg uses React by default, you can build blocks using:
- Plain JavaScript (no JSX)
- Vue.js or Svelte (with custom Webpack)
- TypeScript
- Custom frontend frameworks
🔹 Vanilla JS Example (no JSX):
registerBlockType('myplugin/vanilla', {
edit: function () {
return wp.element.createElement('p', null, 'Hello from Vanilla JS!');
},
save: function () {
return wp.element.createElement('p', null, 'Saved content from Vanilla JS');
}
});
🔹 Using Vue or Svelte:
To use Vue or Svelte:
- Set up a custom Webpack config
- Bundle your framework
- Mount to a container inside the block
- Communicate via
setAttributes()
to save data
These setups offer more flexibility but don’t have native Gutenberg integration like React does.
🔄 Dynamic Blocks (with PHP)
You can render content using PHP if your block needs to fetch data or generate output dynamically.
Example:
register_block_type(__DIR__ . '/block.json', [
'render_callback' => 'render_notice_block',
]);
function render_notice_block($attributes) {
return '<div class="dynamic-notice">' . esc_html($attributes['content']) . '</div>';
}
This is great for:
- Contact forms
- Query loops
- Conditional logic
- Server-side content like post metadata
🔗 Additional Block Features
Once you're comfortable, explore these advanced options:
- InnerBlocks – Allow nesting child blocks
- Block Variations – Preconfigured block versions
- Block Patterns – Reusable design templates
- InspectorControls – Add settings to the sidebar
- useSelect / useDispatch – Access global data from the store
📚 Resources
✅ Final Thoughts
WordPress blocks are the future of WordPress development. With React and @wordpress/scripts, developers get a modern JavaScript experience inside a familiar CMS. But you're not locked in—you can use any JS framework, from Vue to plain ES5.
Learning block development gives you complete control over the editor experience and content architecture of your sites.
Want a live example repo? Or a walk-through of converting a shortcode to a block? I can help set it up—just ask!
Would you like this article exported as Markdown or formatted for your WordPress blog (with headings, code blocks, and featured image included)?
Top comments (0)