---
title: "WordPress 7.0 finally lets you build a block without writing JavaScript"
locale: "en"
url: "https://irz.fr/en/articles/wordpress-php-only-block-registration-en"
markdown_url: "https://irz.fr/en/articles/wordpress-php-only-block-registration-en.md"
category: "tech"
tags: ["WordPress", "Gutenberg", "PHP", "JavaScript", "blocks", "WordPress 7.0"]
published_at: "2026-08-31T11:25:00.000Z"
author: "Camille Morel"
translation: "https://irz.fr/fr/articles/wordpress-php-only-block-registration-fr.md"
---

# WordPress 7.0 finally lets you build a block without writing JavaScript

With autoRegister, WordPress 7.0 can expose a PHP-rendered block in the editor automatically. The developer loses the JavaScript registration layer, not Gutenberg’s JavaScript.

A WordPress block could be tiny as a product feature and oddly oversized as a toolchain.

Take three lines calculated in PHP. The server already knows how to produce the HTML. Gutenberg still wanted a client presence: register the block in the browser, load `@wordpress/blocks`, provide `edit`, and often build the JavaScript. A lot of machinery to say a second time that the block exists.[2](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/)[6](https://css-tricks.com/getting-started-with-wordpress-block-development/)

Since WordPress 7.0, that detour is no longer mandatory for the simplest case.

Declare `supports.autoRegister`, provide a `render_callback`, and a server-rendered block can **appear in the editor without your own JavaScript registration**.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)[2](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/)

The new option is almost a one-line change. For some blocks, that is enough to keep the useful definition in PHP.

```php
register_block_type(
    'irz/server-note',
    [
        'title' => 'Server note',
        'attributes' => [
            'text' => [
                'type'    => 'string',
                'default' => 'Hello',
            ],
        ],
        'render_callback' => function ( $attributes ) {
            return '<p>' . esc_html( $attributes['text'] ) . '</p>';
        },
        'supports' => [
            'autoRegister' => true,
        ],
    ]
);
```

That declaration is enough for the minimal case documented by WordPress.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)

It does not mean Gutenberg has become a PHP application.

## What actually disappears

Before WordPress 7.0, the documentation normally recommended registering blocks **on the server and on the client**. Server registration enables dynamic rendering, Block Supports, Block Hooks, style variations and other features that depend on the PHP registry. Client registration, through `registerBlockType()`, gives the Block Editor its definition of the block and its editing interface.[2](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/)

A dynamic block could end up with two entry points:

```php
register_block_type(
    'irz/server-note',
    [
        'render_callback' => 'irz_render_note',
    ]
);
```

and then in the browser:

```js
import { registerBlockType } from '@wordpress/blocks';

registerBlockType('irz/server-note', {
    edit: Edit,
});
```

Around those two calls you would often find `block.json`, imports, `@wordpress/scripts`, dependencies and compiled output. The older CSS-Tricks tutorial captures the exact moment a modest block walks into “React and JSX land”.[6](https://css-tricks.com/getting-started-with-wordpress-block-development/)

For a genuinely rich editing UI, that was reasonable. For one server-calculated value and two Inspector settings, the plumbing could become larger than the feature.

> **WordPress 7.0 removes a duplicate, not Gutenberg**
> Comparison between an older dynamic block with PHP and JavaScript registration and a WordPress 7.0 PHP auto-registered block
> - BEFORE: TWO REGISTRATIONS · WP 7.0: ONE SERVER SOURCE
> - BEFORE
> - PHP : register_block_type
+
JS : registerBlockType
> - WORDPRESS 7.0
> - PHP : register_block_type
+ autoRegister
+ render_callback
> - The browser still exists. What disappears is your client registration code for this simple case.
> autoRegister removes the second registration point for simple server-rendered blocks. It does not rewrite Gutenberg in PHP.

## PHP-only means your PHP

The most important nuance is hidden in the feature's name.

WordPress calls it **PHP-only block registration**, not a JavaScript-free editor.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)

When `autoRegister` is true, Core sends the block definition to the client. The WordPress 7.0 Field Guide says these blocks are exposed client-side through a JavaScript global variable.[4](https://make.wordpress.org/core/2026/05/14/wordpress-7-0-field-guide/) The Block Supports documentation says the editor then registers them automatically and uses `ServerSideRender` for their preview.[3](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/)

In practice, the developer can remove several pieces:

- you no longer write `registerBlockType()`;
- you do not need an `edit.js` file for the minimal case;
- you can avoid a JavaScript build chain if the plugin has no other reason to need one;
- **WordPress still runs JavaScript to make the editor work**.

This is not WordPress going back to pure PHP. Core is simply removing manual synchronization when the server already knows enough.

## The editor invents the controls it can

An auto-registered block would not save much if Gutenberg could only show an inert rectangle.

WordPress 7.0 then tries to build Inspector controls from the attributes registered in PHP.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)[4](https://make.wordpress.org/core/2026/05/14/wordpress-7-0-field-guide/)

The official example includes `string`, `integer`, `boolean` and an enumerated string. When the attribute type is supported, the editor can turn that metadata into standard fields.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)

The registry begins to act like a small data schema.

```php
'attributes' => [
    'title' => [
        'label'   => 'Title',
        'type'    => 'string',
        'default' => 'Hello World',
    ],
    'count' => [
        'label'   => 'Count',
        'type'    => 'integer',
        'default' => 5,
    ],
],
```

You describe values. WordPress supplies conventional UI when it knows how.

The “when” matters. The dev note explicitly says controls **are not generated for attributes with the `local` role or for unsupported attribute types**.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)

This is not a universal interface generator.

> **autoRegister works while the block stays describable**
> Diagram moving from simple PHP attributes to generated controls and server rendering, then showing custom interfaces still requiring client code
> - THE MORE SPECIFIC THE UI, THE MORE JAVASCRIPT RETURNS
> - PHP ATTRIBUTES
text · number
boolean · enum
> - INSPECTOR
generated
controls
> - SERVER
PHP
RENDER
> - Once editing needs bespoke UI, RichText, complex interactions or custom client logic, the JavaScript path becomes relevant again.
> The biggest gain comes when metadata, standard controls and server rendering are enough. autoRegister is not trying to reproduce every client-block capability.

## Rendering stays dynamic

An auto-registered block must provide a `render_callback`.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)[3](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/)

That requirement immediately tells us where the boundary sits.

The final HTML still comes from the server and the current attributes; it is not frozen by a JavaScript `save()` function. This remains the familiar **dynamic block** model.

That is enough for plenty of ordinary components:

- a list calculated from database data;
- a panel whose content depends on site state;
- business data already available in PHP;
- a block integrating a server-side plugin;
- a simple component in a classic theme beginning to adopt Gutenberg.

The dev note specifically names classic themes and server-driven workflows as likely beneficiaries.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)

For this sort of code, requiring React just to provide a basic editor presence often felt less like an interface requirement and more like an entry fee into the block ecosystem.

`autoRegister` lowers that fee.

## What it does not replace

WordPress leaves little suspense here: the API **is not meant to replace the client-side paradigm and is not intended to become equally featureful**.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)

That is the boundary worth keeping visible.

If your block needs:

- sophisticated direct editing in the canvas;
- rich interactions between several elements;
- a bespoke React component;
- client behaviour that cannot be described as a few attributes;
- a deeply customized editing workflow;

then a real client-side `edit` implementation remains the right abstraction.

There is no PHP-versus-React victory here. **WordPress simply stops forcing the simple case to resemble the complex one**.

That matters more than the number of files saved.

## One less maintenance surface

Put ten small dynamic blocks in one plugin and the maintenance difference stops being theoretical.

Previously, each could have a server definition and a client definition that needed to stay aligned: name, attributes, supports and sometimes preview behaviour. `block.json` had already reduced some duplication by acting as shared metadata.[2](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/)

`autoRegister` goes further for the subset that does not need custom client code.

Business logic can stay in PHP; you describe attributes and rendering, while Core manufactures the minimum editor presence.

The useful saving is not necessarily JavaScript weight. It is the number of **places that can drift out of sync**.

One registry instead of two. One less toolchain when it adds no value. One environment to debug for the business rendering.

That does not make Gutenberg simple.

It finally allows a simple block to remain simple.

## The question is no longer “do I have to learn React?”

Gutenberg often turned a small product question into a stack decision.

“I want to add one small component to the editor” quickly became “do I need Node, JSX, WordPress packages and a bundle?”

For many blocks, yes. A rich extension of the editor still needs rich client-side APIs.

What changed is that there is finally an exit before you get that far.

If your requirement fits simple attributes and a `render_callback`, you can stay in PHP.[1](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)[5](https://fr.wordpress.org/2026/05/15/guide-des-changements-techniques-de-wordpress-7-0/)

If the editing experience becomes more ambitious, move to the client.

This is not a return to pre-Gutenberg WordPress.

It is Gutenberg finally learning that a trivial component does not need to pretend it is an application.

## References

1. [Make WordPress Core — PHP-only block registration, March 3, 2026](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)
2. [WordPress Developer Resources — Registration of a block](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/)
3. [WordPress Developer Resources — Block Supports / autoRegister](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/)
4. [WordPress 7.0 Field Guide — PHP Only Block Registration](https://make.wordpress.org/core/2026/05/14/wordpress-7-0-field-guide/)
5. [WordPress.org Français — WordPress 7.0 technical changes guide, May 15, 2026](https://fr.wordpress.org/2026/05/15/guide-des-changements-techniques-de-wordpress-7-0/)
6. [CSS-Tricks — Getting Started With WordPress Block Development](https://css-tricks.com/getting-started-with-wordpress-block-development/)
