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-
Block Attributes and Serialization
Master the attribute system — types, sources, defaults, and how block data round-trips between the editor, the database, and the front-end.
30 min
-
Building a Block Plugin
Package your block as a proper WordPress plugin — file structure, asset enqueueing, server-side render callbacks, plugin metadata.
35 min
-
Building Your First Custom Block
Replace the scaffolded placeholder with a real custom Callout block — editable title, body, and a type selector — using registerBlockType + edit/save.
45 min