Register a block pattern in a theme or plugin, using the WordPress 6.0+ file-based pattern system.
Register a new block pattern using WordPress's file-based pattern auto-loader (6.0+). Covers pattern file structure, category registration, and the conventions for naming and markup.
| Input | Required | Notes |
|---|---|---|
| Title | Yes | Human-readable name shown in the inserter, e.g. Hero with CTA |
| Slug | Yes | Machine name, e.g. hero-cta. The full pattern name will be {text-domain}/{slug} |
| Description | No | One sentence shown in the inserter tooltip |
| Category | Yes | Existing WP category (featured, text, gallery, etc.) or a new custom one |
| Target package |
| Yes |
Theme or plugin in packages/ |
| Keywords | No | Comma-separated terms to aid discoverability in the inserter |
| Block markup | Yes | The block content to scaffold — describe the layout if not provided |
If any required inputs are missing, ask for them before writing any code.
File-based patterns are auto-loaded by WordPress 6.0+ from a patterns/ directory at the root of a theme. For plugins, patterns must be registered programmatically (see Step 3 variant).
patterns/ directory exists (or create it).src/patterns/ and are registered via init.Create patterns/{slug}.php in the theme root. The file header comment registers the pattern — no PHP function call needed:
<?php
/**
* Title: Hero with CTA
* Slug: {text-domain}/{slug}
* Description: Full-width hero section with a heading, paragraph, and call-to-action button.
* Categories: featured, text
* Keywords: hero, banner, cta
* Viewport Width: 1280
* Block Types: core/cover
* Post Types: page
* Inserter: true
*/
?>
<!-- wp:cover {"minHeight":60,"minHeightUnit":"vh","align":"full"} -->
<div class="wp-block-cover alignfull">
<!-- wp:heading {"level":1} -->
<h1 class="wp-block-heading">Your headline here</h1>
<!-- /wp:heading -->
<!-- wp:buttons -->
<div class="wp-block-buttons">
<!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button">Call to action</a></div>
<!-- /wp:button -->
</div>
<!-- /wp:buttons -->
</div>
<!-- /wp:cover -->
Header field reference:
| Field | Required | Notes |
|---|---|---|
Title | Yes | Shown in the block inserter |
Slug | Yes | Must be {text-domain}/{slug} — unique across all patterns |
Categories | Yes | Comma-separated. Use existing WP categories where possible |
Keywords | No | Aids inserter search |
Viewport Width | No | Preview canvas width in pixels |
Block Types | No | Restricts the pattern to the inserter for those block types |
Post Types | No | Restricts to specific post type editors |
Inserter | No | Set to false to hide from the inserter (use as a template only) |
For plugins, register via register_block_pattern() in a hooks() method:
public function hooks(): void {
add_action( 'init', [ $this, 'register_patterns' ] );
}
public function register_patterns(): void {
\register_block_pattern(
'{plugin-slug}/{slug}',
[
'title' => __( 'Hero with CTA', '{plugin-slug}' ),
'description' => __( 'Full-width hero with heading and button.', '{plugin-slug}' ),
'categories' => [ 'featured' ],
'keywords' => [ 'hero', 'banner', 'cta' ],
'content' => '<!-- wp:cover -->...<!-- /wp:cover -->',
]
);
}
If the pattern uses a category that does not exist in WordPress core, register it via init before registering the pattern:
add_action( 'init', function (): void {
\register_block_pattern_category(
'{text-domain}-{category-slug}',
[ 'label' => __( 'Category Label', '{text-domain}' ) ]
);
} );
Built-in WP categories that do not require registration: featured, text, gallery, buttons, columns, query, portfolio, social, posts, banner, header, footer, media.
composer lint
composer lint-fix # if needed
composer lint # re-run to confirm clean
Verify in WordPress:
{text-domain}/{slug} — prefix prevents collisions with Core and other plugins.pot/.po files<!-- wp: --> comments, not rendered HTMLtheme.json (var(--wp--preset--color--primary))A patterns/{slug}.php file (theme) or a registered pattern via register_block_pattern() (plugin). The pattern is visible in the block inserter under its assigned category and inserts valid, linting-clean block markup.