The default advice for custom blocks is @wordpress/create-block, a build step and a JavaScript bundle per block. That’s the right call for a product or a block library. For a typical client site with a handful of bespoke sections, it’s a toolchain you’ll be maintaining long after the project ships. There’s a lighter path.

When you don’t need a build step

If your blocks render server-side, use standard controls, and are styled by the theme, you can register them in PHP with no bundler at all. That covers most “content section” blocks: a call-to-action, a stats row, a feature grid.

Dynamic blocks render in PHP

Register the block with a render_callback and the front-end markup is just a PHP function: the same mental model as a template part.

register_block_type( 'ru/cta', [
    'api_version'     => 3,
    'attributes'      => [
        'heading' => [ 'type' => 'string' ],
        'url'     => [ 'type' => 'string' ],
    ],
    'render_callback' => function ( $attr ) {
        $heading = esc_html( $attr['heading'] ?? '' );
        $url     = esc_url( $attr['url'] ?? '#' );
        return "<a class='ru-cta' href='{$url}'>{$heading}</a>";
    },
] );

No bundle to ship, no hydration, and the output is exactly the HTML you wrote.

Keep the edit UI simple

For the editor side, ACF blocks or the core InnerBlocks approach give you a usable interface without writing React. Reserve a full JavaScript block for the cases that genuinely need custom editor interaction: a live-previewing chart, or a complex repeater with drag-and-drop.

Style with the theme, not the block

Put block styles in the theme stylesheet, scoped to the block’s class. One place to look, one place to change, and the block inherits your design tokens for free. A block that ships its own CSS file is a block that will drift from the rest of the site.

When to reach for a build step

Add the toolchain when you’re shipping blocks to multiple sites, need rich in-editor interaction, or want to distribute a plugin. For a single site’s custom sections, PHP-rendered blocks keep the output clean, the editors happy and the toolchain small enough to hand over without a README the size of a novel.