Custom Gutenberg Blocks: React or PHP?

The WordPress block editor is written in React, so the official documentation assumes your custom blocks will be too. But most blocks on real websites don’t need a custom React interface: they need a few fields and some HTML. Here’s what each approach actually gives you.

What a block needs, technically

Every block has two sides:

  • The editor side: how the block appears and which settings it shows while editing. This always runs in the browser, inside the React-based editor.
  • The front end: the HTML visitors get. This can be saved as static HTML, or rendered by PHP on each request (a dynamic block).

So “React or PHP” really means: who writes the editor side, and who renders the front end?

The React approach

npx @wordpress/create-block gives you a plugin where edit.js defines the editor UI in React/JSX, and either save.js (static HTML) or render.php (dynamic) defines the output. You build it with webpack through @wordpress/scripts.

What you get:

  • Full control over the editor: custom toolbars, drag handles, live-editable text (RichText), media pickers wired exactly how you want.
  • Static blocks: output saved in the post, so it renders even without the plugin active.
  • The same stack as core, with the most examples and documentation.

What it costs:

  • Node.js and a build step for every change.
  • Two templates to keep in sync: the React preview and the front-end output.
  • A skill set many WordPress developers and agencies don’t use day to day.

The PHP approach

Here the front end is always a dynamic block rendered by PHP, and the editor shows a server-rendered preview of that same PHP. Settings appear in the sidebar as native WordPress controls.

What you get:

  • One template. The editor preview and the front end come from the same PHP, so they can’t drift apart.
  • No build step. Edit, save, refresh.
  • Easy dynamic data. Query posts, read post meta or ACF fields, check the current user: it’s just PHP.

What it costs:

  • Less inline editing. Content is edited in sidebar fields rather than typed directly into the block (unless you use nested blocks for the editable parts).
  • Rendered per request. Dynamic blocks run PHP on every page view, like any PHP template. Page caching handles this well.

A middle path: nested blocks

The “no inline editing” limit is smaller than it sounds. A PHP block can be a container: you render the wrapper and layout in PHP, and let editors type headings, paragraphs and buttons with normal core blocks inside it (InnerBlocks). You get a fixed design with a comfortable editing experience, still without React.

How to decide

Choose React when…Choose PHP when…
The editing UI itself is the product (drag-and-drop builders, complex interactions)The block is mostly layout + a few settings
You want static HTML saved in the postThe block shows dynamic data (posts, meta, users)
Your team already works in ReactYour team works in PHP, or hands sites to clients
You’re building for the WordPress.org block directoryYou want to ship blocks quickly for one site

For the PHP path, FanCoolo WP does the wiring for you: you write the PHP render, add fields in a visual attributes manager (they appear as native sidebar controls), enable nested blocks with a toggle, and FanCoolo generates block.json and the editor registration. Step by step: create a custom Gutenberg block without React.

Skip the React toolchain

Skip the React toolchain

Build native Gutenberg blocks in PHP with FanCoolo WP: visual fields, nested blocks, SCSS and hot reload.