Patterns differ from blocks and variations: they’re block compositions — multiple blocks pre-arranged that get inserted as a unit. Users can then edit each block independently.
Registering a pattern (PHP)
Patterns are registered server-side via register_block_pattern(). Add to your plugin file:
init · priority 10 add_action('init', function() {
register_block_pattern(
'my-first-block/callout-trio',
[
'title' => __('Callout Trio', 'my-first-block'),
'description' => __('Three callouts side-by-side: tip, warning, error.', 'my-first-block'),
'categories' => ['callout'],
'keywords' => ['callout', 'trio', 'columns'],
'content' => '<!-- wp:columns -->
<div class="wp-block-columns">
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:my-first-block/callout {"calloutType":"tip","title":"Tip"} -->
<div class="wp-block-my-first-block-callout my-callout my-callout-tip">
<h4 class="my-callout-title">Tip</h4>
<!-- wp:paragraph --><p>Use callouts for emphasis.</p><!-- /wp:paragraph -->
</div>
<!-- /wp:my-first-block/callout -->
</div>
<!-- /wp:column -->
<!-- (two more columns with warning + error callouts) -->
</div>
<!-- /wp:columns -->',
]
);
}); Registering a pattern category
Categories group related patterns in the inserter. Register one if a default doesn’t fit:
register_block_pattern_category(
'callout',
['label' => __('Callouts', 'my-first-block')]
);
Alternative: file-based pattern registration
For larger patterns, define them in PHP files inside a patterns/ directory. Each file’s docblock specifies the metadata:
<?php
/**
* Title: Callout Trio
* Slug: my-first-block/callout-trio
* Categories: callout
* Keywords: callout, trio, columns
* Description: Three callouts side-by-side.
*/
?>
<!-- wp:columns -->
...block markup here...
<!-- /wp:columns -->
WordPress auto-registers any file in wp-content/themes/{theme}/patterns/ or wp-content/plugins/{plugin}/patterns/. Much cleaner than escaping HTML in PHP strings.
Patterns vs variations vs templates
| Patterns | Variations | Templates | |
|---|---|---|---|
| Scope | Multiple blocks | Single block | Initial editor state |
| User edits after insert | Yes, each block independently | Yes, attributes only | Yes, but template can lock |
| Registered via | register_block_pattern() | registerBlockVariation() | core/template-part or block.json template |
| Best for | Page sections (hero, FAQ, testimonials) | Preset configurations of one block | Default content in container blocks |
Use patterns to ship “starter content”
A common pattern (no pun) for plugin authors: ship 5-10 well-designed patterns showcasing your block. Users insert one, see how it composes, then customize. This dramatically lowers the “what do I do with this?” friction for new users.
What’s next
Part 9 moves beyond your own block — we use WordPress filters and hooks to extend OTHER blocks. Adding a “lock” toggle to every paragraph, an extra sidebar panel for images, that kind of thing.
Get the next one in your inbox. Practical tips, no fluff.
More tutorials
View all- WordPress
How to Prepare Your Plugin or Theme for WordPress 7.0
A step-by-step compatibility process for shipping a WordPress 7.0-ready release — set up a test site, audit your blocks, fix the breaking changes, and ship with confidence.
22 min
- WordPress
WordPress 7.0 for Block Developers: Breaking Changes
WordPress 7.0 enforces the iframed editor, broadens contentOnly mode, and drops PHP 7.3. Here are the breaking changes block and plugin developers must fix before users upgrade.
25 min
- WordPress
WordPress 7.0 AI: Client, Abilities & Connectors
The headline feature of WordPress 7.0 is native AI in Core. Here is what the WP AI Client, the Abilities API, and the Connectors system actually mean for plugin developers.
25 min