In the early days of Gutenberg development, the goal was simple: make a block that looks like the frontend. But as WordPress has matured into an enterprise-grade CMS, the “one-off” block approach has revealed a fatal flaw: Inconsistency.
If you have 40 custom blocks, and each one has its own manually coded spacing controls, color pickers, and HTML structure, you don’t have a design system, you have a maintenance nightmare.
Today, we’re looking at a different architectural philosophy: The Registry Pattern. Using the wpTruss methodology found in high-end agency environments, we’ll explore how to build blocks that are configured by data, styled by tokens, and rendered dynamically.
1. The Core Philosophy: Save → Null
The most important technical decision in this system is found in index.js:
JavaScript
save: function () {
return null;
},
By returning null, we tell WordPress: “Don’t store HTML in the database. Just store the attributes.” Why? In standard Gutenberg development, if you change a <div> to a <section> in your code, every existing block on your site will throw a “Block Validation Error.” By rendering via render.php on the server, you can update the markup of 1,000 blocks instantly across a whole site without ever breaking the editor.
2. The “Panel Registry” Concept
In a typical block, index.js is bloated with hundreds of lines of InspectorControls. In the Registry pattern, we move that logic into a centralized system.
A standard block in this system looks like this in block.json:
JSON
{
"name": "wptruss/sample-registry",
"attributes": {
"blockPadding": { "type": "string", "default": "md" },
"spacingBottom": { "type": "string", "default": "md" }
}
}
Because this block is registered with the wpt-element-registry, the UI panels for Spacing, Visibility, and Structure are automatically injected. The developer doesn’t have to write the JS for the dropdowns; they just define the attributes.
3. The Power of Overrides (wptPanels)
What happens when one block needs to behave differently? For example, a Hero Block usually needs much larger default padding than a standard Text Block.
Instead of writing a new JavaScript “Hero” component, we use the wptPanels key in block.json to override the system defaults:
JSON
{
"name": "wptruss/sample-override",
"wptPanels": {
"spacing": {
"blockPadding": "3xl",
"spacingBottom": "xl"
}
}
}
The Registry reads this key and automatically sets the “Padding” dropdown to 3xl upon insertion. This allows for Infinite Variation with Zero Extra Code.
4. Design Tokens and CSS Variables
To maintain a strict design system, this approach forbids hardcoded values (hex codes or pixel widths) in the style.css. Everything is mapped to CSS Custom Properties (Variables).
CSS
.tp-sample-registry {
padding: var(--tp-block-padding, var(--wpt-spacing-md));
}
/* Modifier classes generated by the Registry */
.wpt-sample-registry--padding-3xl {
--tp-block-padding: var(--wpt-spacing-3xl) !important;
}
When a user selects “Large” in the editor, the Registry applies a BEM-style modifier class. This class updates the local variable, which updates the padding. If the brand’s “Large” spacing changes from 64px to 80px, you update one token, and the entire site scales accordingly.
5. Server-Side Intelligence
Because we use render.php, we can use powerful PHP logic to clean up our output. Notice the use of a helper function in the sample files:
PHP
$wrapper = get_block_wrapper_attributes( [
'class' => 'tp-sample-block ' . wptruss_resolve_classes( $attributes )
] );
The wptruss_resolve_classes function does the heavy lifting. It looks at the attributes (like hideOnMobile or blockPadding), compares them against the Registry defaults (or overrides), and returns the string of classes needed. This keeps the template files incredibly clean and readable.
6. Semantic Flexibility
A common SEO failure in Gutenberg is the “Hardcoded Heading.” A block might always use an <h2>, even if it’s placed under another <h2>.
This system mandates a headingLevel attribute:
PHP
<<?php echo esc_attr( $level ); ?> class="tp-block__heading">
<?php echo esc_html( $heading ); ?>
</<?php echo esc_attr( $level ); ?>>
The user can choose h1-h6 in the sidebar, ensuring the document outline remains perfect for accessibility and SEO.
Building for the Future
The wpTruss Registry Pattern isn’t about building a block; it’s about building a platform.
By moving UI configuration to block.json, rendering to PHP, and styling to CSS Variables, you create a system that is:
- Impenetrable: No block validation errors.
- Consistent: Every block follows the same spacing and color tokens.
- Scalable: One developer can manage dozens of blocks because the core logic is centralized in the Registry.
If you are tired of Gutenberg blocks feeling like “fragile puzzles,” it’s time to start thinking in Registries.