Gutenberg Block Development for React Developers
My Journey Through WordPress Block Development
I still remember the day WordPress 5.0 dropped with this thing called "Gutenberg." Like many developers, I stared at my screen thinking, "Great, another thing to learn." Boy, was I wrong to be cynical! After years of wrestling with shortcodes and custom fields, Gutenberg has completely changed how I build WordPress sites. If you're coming from the React world like I did, you're actually at a huge advantage because—surprise!—Gutenberg is built with React under the hood. This happy coincidence means your React skills can transfer directly to creating custom blocks, which is what I want to share with you today based on my own stumbling journey into this brave new world of block-based editing.
What Even is a Gutenberg Block Anyway?
Think of blocks as LEGO pieces for your website. Each paragraph? That's a block. That image gallery you added? Another block. That fancy pricing table? You guessed it—a block. Before Gutenberg, making complex layouts in WordPress often meant either installing a page builder plugin (and praying it wouldn't break your site), or worse, trying to explain to clients how to use shortcodes (ugh, remember those days?). Now users can just drag and drop these independent content chunks, and voilà—they've built something impressive without touching a line of code! As a developer who's built countless sites for clients who inevitably break things, this modular approach has been nothing short of revolutionary for both my workflow and my sanity.
Getting Your Development Environment Ready (Without Losing Your Mind)
Let's be honest—setting up development environments can be a total pain. I've spent more late nights than I care to admit staring at terminal errors and questioning my life choices. But WordPress has actually made this surprisingly painless! You'll need Node.js and npm installed (if you're a React dev, you probably already have these), and then we'll use the official WordPress block scaffolding tool to save ourselves hours of setup headaches.
First things first—navigate to your WordPress plugins directory. I usually go with something like cd wp-content/plugins/
but your path might vary depending on your setup. Then run this magical little command:
npx @wordpress/create-block@latest my-block
When I first did this, I was honestly shocked at how much code it generated for me. It creates a whole directory called my-block
with all the files you need pre-configured. It's like ordering a pizza and getting free breadsticks, drinks, AND dessert! This scaffolding approach saves so much time that would otherwise be spent configuring webpack, setting up file structures, and all that boring stuff that makes you question your career choices at 2 AM.
Let's Actually Build Something! A Simple Message Block
Okay, so theory is fine and all, but I learn best by doing, and I bet you do too. Let's create something super simple but useful—a custom message block where users can enter and display text with some styling. I use something like this all the time for call-to-action boxes, notices, or highlighted quotes. It's simple enough to understand but actually useful in real projects.
Step 1: Setting Up the Block Attributes in block.json
First up, we need to define what our block actually IS in the block.json
file. This file is like the birth certificate for your block—it establishes its identity in the WordPress ecosystem. Here's what mine looks like:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"version": "1.0.0",
"name": "my-block/message-block",
"title": "Message Block",
"category": "widgets",
"icon": "text",
"description": "A block that displays a customizable message.",
"attributes": {
"message": {
"type": "string",
"default": "Hello, Gutenberg!"
}
},
"textdomain": "message-block",
"editorScript": "file:./build/index.js"
}
I spent way too long on my first block trying to figure out why things weren't working, only to realize I had a typo in this file. Triple-check your JSON syntax—those missing commas will haunt your dreams!
Step 2: Creating the Edit Experience in src/edit.js
Next up is the edit.js file, which controls how your block behaves in the editor. This is where your React skills really shine! We're using the useBlockProps
hook (which gives us all the proper block behavior) and RichText
for a nice editable text field. The cool thing is, if you've used React hooks before, this pattern will feel super familiar:
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function Edit({ attributes, setAttributes }) {
const { message } = attributes;
return (
<div {...useBlockProps()}>
<RichText
type="text"
value={message}
onChange={(value) => setAttributes({ message: value })}
placeholder={__('Enter your message...', 'message-block')}
/>
</div>
);
}
The first time I saw this pattern with the setAttributes function, it immediately clicked for me because it's basically just like useState in React. You're extracting the current value, then using a function to update it when changes happen. Same concept, just WordPress-flavored!
Step 3: Saving the Frontend Output in src/save.js
The save.js file defines what actually gets saved to the database and rendered on the frontend. It's important to understand that what happens in edit.js stays in the editor, while save.js determines what your visitors actually see:
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function Save({ attributes }) {
const { message } = attributes;
return (
<div {...useBlockProps.save()}>
<RichText.Content value={message} />
</div>
);
}
I had a moment of confusion my first time with this because I couldn't figure out why my styles looked different on the frontend. Turns out, you need to make sure your save component properly handles all the attributes you want to display! The useBlockProps.save() (note the .save() part!) is crucial here.
Step 4: Registering Everything in src/index.js
Now for the glue that holds it all together—the index.js file that registers your block with WordPress. This is like introducing your block to WordPress and saying "Hey, this is what I made, please add it to your block catalog!"
import { registerBlockType } from '@wordpress/blocks';
import Edit from './edit';
import Save from './save';
import metadata from './block.json';
registerBlockType(metadata.name, {
...metadata,
edit: Edit,
save: Save,
});
This part is pretty straightforward—we're just importing our edit and save components and registering them with WordPress using the metadata from our block.json file. The first time I did this, I accidentally imported the wrong components and spent an hour debugging. Don't be like me—double-check your imports!
Step 5: Building and Actually Using Your Creation
Time for the moment of truth! Run this command to build your block:
npm run build
Then head over to your WordPress dashboard and activate your plugin. If all goes well (fingers crossed!), you should see your new block available in the block inserter. The first time I saw my own custom block appear in that list, I felt like I'd just performed actual magic. There's something incredibly satisfying about creating a tool that seamlessly integrates with WordPress like it was always meant to be there.
I've found that clients absolutely love custom blocks that are tailored to their specific needs. Instead of teaching them complex shortcodes or how to piece together multiple blocks to achieve a certain layout, they can just use your custom block and get exactly what they need with minimal fuss. It's made my client handoff meetings so much smoother—less "how do I do this again?" and more "wow, this is exactly what I needed!"
As you get more comfortable, you'll start thinking of ways to expand your blocks with more features—maybe color pickers for background colors, toggles for different styles, or even integration with external APIs. The beauty of the block system is that you can start simple and gradually add complexity as you need it.
Building Gutenberg blocks has honestly rekindled my love for WordPress development. There's something incredibly satisfying about creating reusable components that make content creation easier for non-technical users. It bridges the gap between developer control and user friendliness in a way that the old WordPress editor never quite managed. So dive in, experiment, break things (in your development environment, not production—I learned that lesson the hard way!), and see what you can create. Your React skills are the perfect foundation for becoming a Gutenberg block wizard!