Using Block Patterns for new entries of a Custom Post Type

When developing projects, I often use Custom Post Types (CPT). In a new project, the content of the entries were build completely with core blocks. In the past, I typically used custom meta fields and a fixed page template. But as creating such a complex content of a CPT is quite a lot of work and error-prone, I wanted to use a template for new entries.

Creating a block pattern

The easiest way to create a pattern for a post type is by creating the content first using the block editor and then exporting the HTML markup using the “Copy all content” option:

Now you can use this markup to register a block pattern with the default content of new entries:

function cpt_register_block_pattern() {
	register_block_pattern(
		'my-cpt/my-cpt-pattern',
		array(
			'title'       => __( 'My CPT pattern', 'my-cpt' ),
			'description' => _x( 'The custom template for my_cpt', 'Block pattern description', 'my-cpt' ),
			'content'     => '
<!-- wp:paragraph {"placeholder":"Custom Post Type ..."} -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:columns -->
<div class="wp-block-columns"><!-- wp:column -->
<div class="wp-block-column"><!-- wp:image -->
<figure class="wp-block-image"><img alt=""/></figure>
<!-- /wp:image --></div>
<!-- /wp:column -->

<!-- wp:column -->
<div class="wp-block-column"><!-- wp:heading {"placeholder":"Name ..."} -->
<h2></h2>
<!-- /wp:heading -->

<!-- wp:paragraph {"placeholder":"Phone ..."} -->
<p></p>
<!-- /wp:paragraph --></div>
<!-- /wp:column --></div>
<!-- /wp:columns -->',
		)
	);
}
add_action( 'init', 'cpt_register_block_pattern' );

Creating a template for new entries

When registering a new CPT, you can can also create default content by passing a template argument with a multidimensional array defining the template:

function cpt_register_post_type() {
	register_post_type(
		'my_cpt',
		array(
			'label'                 => __( 'Custom Post Type', 'my-cpt' ),
			'supports'              => array( 'title', 'editor' ),
			'public'                => true,
			'show_ui'               => true,
			// ... other settings
			'has_archive'           => true,
			'show_in_rest'          => true,
			'template'              => array(
				array(
					'core/paragraph',
					array(
						'placeholder' => __( 'Custom Post Type ...', 'my-cpt' ),
					),
				),
				array(
					'core/columns',
					array(),
					array(
						array(
							'core/column',
							array(),
							array(
								array(
									'core/image',
								),
							),
						),
						array(
							'core/column',
							array(),
							array(
								array(
									'core/heading',
									array(
										'level'       => 2,
										'placeholder' => __( 'Name ...', 'my-cpt' ),
									),
								),
								array(
									'core/paragraph',
									array(
										'placeholder' => __( 'Phone ...', 'my-cpt' ),
									),
								),
							),
						),
					),
				),
			),
		)
	);
}
add_action( 'init', 'cpt_register_post_type' );

As you can see in this little example, the array can get very complex, unreadable and hard to maintain. You would also have to convert the Block Pattern HTML to this PHP array format. So any change to the pattern would require you to do the work twice, trying not to make any mistake.

Combining Block Patterns and Custom Post Types templates

As the solution with the PHP array was not really something I wanted to use (the actual template was a lot more complex than the one shown in the example), I first tried the following:

// ...
'template'              => array(
	array(
		'my-cpt/my-cpt-pattern',
	),
),
// ...

I thought, that maybe the template can also use Block Patterns in the array and not only blocks. But this didn’t work. When searching for a solution, I found multiple issues on GitHub. There I found the core/pattern block, which makes the task very easy:

'template'              => array(
	array(
		'core/pattern',
		array(
			'slug' => 'my-cpt/my-cpt-pattern',
		),
	),
),

Unfortunately, the core/pattern block is not available in WordPress 5.8, but you can already use it with the Gutenberg plugin installed and activated. I really hope that it’s going to be available with WordPress 5.9 expected next month.

Conclusion

Both Block Patterns and templates for new Custom Post Type entries are really helpful. Combining them with the new core/pattern block can really increase usability a lot.

Posted by

Bernhard is a full time web developer who likes to write WordPress plugins in his free time and is an active member of the WP Meetups in Berlin and Potsdam.

3 comments » Write a comment

  1. This is great and love the core/pattern solution, but unfortunately doesn’t seem to work with template_lock. Do you know if there is a way?

    • I don’t know if this is possible and I have not tried it out myself. Maybe when the feature get’s merged into WordPress 4.9 it would be posssible.

  2. Still works like a charm 18 months later. “Copy all content” is now called “Copy all blocks”.
    Thanks, Bernhard!

    P.S.: I had to escape some characters like quotation marks from a SyntaxHighlighter Evolved block with hello world code in it, which would have otherwise broken the string in ‘content’ => ‘markup string’.

Leave a Reply

Your email address will not be published. Required fields are marked *