While working on my Gutenberg Development Course, one of the hardest things I found to research was how to add block templates to your WordPress theme or plugin.

Block templates are a way to have certain blocks show up by default for a new post, page or custom post type. You can also “lock” the template to prevent users from adding or removing blocks.
How Block Templates Work
Templates are added as a parameter when registering a post type in WordPress. Sometimes this is done for your own custom post type. But it can also be done for existing and native post types like Posts and Pages.
The block template setting itself is an array of blocks that you want included. There is also an additional setting called “template_lock” that can be set to true or false to lock down the template to users.
You can also add additional configurations like custom placeholder text for blocks or set the alignment.
An Example of Block Templates
You can add the code below to any plugin or theme to modify template setting for post types of your choice.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function mytheme_block_templates( $args, $post_type ) { | |
// Only add template to 'post' post type | |
// Change for your post type: eg 'page', 'event', 'product' | |
if ( 'post' == $post_type ) { | |
// Optionally lock templates from further changes | |
// Change to 'insert' to allow adding other blocks, but lock defined blocks | |
$args['template_lock'] = 'all'; | |
// Set the template | |
$args['template'] = [ | |
[ | |
// Example of including a core image block | |
// Optional alignment setting | |
'core/image', [ | |
'align' => 'left', | |
] | |
], | |
[ | |
// Example of including a core paragraph block | |
// Optional alignment placeholder setting | |
'core/paragraph', [ | |
'placeholder' => 'The only thing you can add', | |
'align' => 'right', | |
] | |
], | |
[ | |
// Example of including a custom block | |
// Optional placeholder setting | |
'custom/your-blocks', [ | |
'placeholder' => 'Custom placeholder', | |
] | |
] | |
]; | |
} | |
return $args; | |
} | |
// Hook function into post type arguments filter | |
add_filter( 'register_post_type_args', 'mytheme_block_templates', 20, 2 ); |
Some notes on this code:
- Notice the conditional statement determining what post type to apply this to. Can change for your own needs.
- The template_lock argument determines whether users can add or remove blocks with this post type.
- The name used for blocks is the name used when creating them. See a list here of all default blocks, which you can use to lookup (or guess) the programatic name for a block.
- You can add additional configurations like placeholder text, alignment, or other block attributes you want set by default.
Learn More About Gutenberg Development
To learn more about developing with blocks in WordPress, please check out my course Gutenberg Development Course.
Zac,
Thanks for this, I noticed the filter commented out in the course files and was instantly intrigued. Any chance this will be added to the Gutenberg course?
LikeLike
Yup! It is going in the first batch up course updates, which will drop very soon 🙂
LikeLiked by 2 people
Woow amazing short explanation.
btw the link is outdated and giving 404 now
LikeLike
Thanks! Just updated the link 🙂
LikeLike
Hi Zac,
I am using a python function to write directly to my blog, but for some reason the block templates only load when I add a new post manually.
Could it be because of the filter ‘register_post_type_args’ ?
If so, how could I change it so the templates always load ?
Thanks a lot for the tutorial,
LikeLike
Hmm, actually I’m not sure exactly how to do that but there was a discussion about template parts in block plugins in the JavaScript for WordPress #Gutenberg Slack channel you might want to checkout javascriptforwp.com/slack
LikeLike
Great tutorial Zac, but how would a create a block template for a specific page?
LikeLike
You would just add some conditional PHP to only add the template if the current page ID is the ID you’re looking for. Haven’t tested this but it should work.
LikeLike
Hi Zac, thanks for this. One thing I’m spinning my wheels on though – how to specify non-core blocks? If the core image block is ‘core/image’ how do I find out the equivalent for (say) Atomic Blocks or other plugin/custom blocks? I’ve hunted through endless help pages, codex etc and can’t find it anywhere. Thanks!
LikeLike
You either need to find their source code so you can look it up or ask the plugin.
The data API covered in my Advanced Gutenberg Course also shows how to get all registered block names with JavaScript but that is a but more complex.
LikeLike
Thanks Zac — yes, I had a look through their source code, but there’s quite a lot of it, and i didn’t know where to look 😦 I did found a script that was supposed to do that (might even have been yours – I think it was on StackExchange) but I couldn’t get it to work… sigh…
Meanwhile Atomic Blocks did get back to me quite quickly… with the registered name of that one block… but no help on how to find out the names of the others.
Since Gutenberg, instead of just messing with php (which I rather like), I fear I’m going to have to finally get my head properly around js (which I hate), to be able to hack anything usefully. In general, it all feels a bit polarising — a bit like electronics from the 1970s to now — great new functionality, but all the mechanism disappearing into impenetrable black boxes that it’s unwise to mess with unless you’re a serious developer…
LikeLike
The way I’ve been making templates is to add the blocks I want in the template, customise them as neccessary, and then switch to code editor view which shows all the block names and their properties.
For an Atomic button, it might look something like this:
“`
“`
The properties are within the braces, so the above would be declared like this in the template array:
“`
array(‘atomic-blocks/ab-button’, array(
‘buttonShape’ => ‘ab-button-shape-circular’,
‘buttonBackgroundColor’ => ‘#8c00a3’,
‘buttonSize’ => ‘ab-button-size-large’,
)),
“`
If there are better ways of doing it, I’d love to know how.
LikeLike
Minor tweak to your code above – I just discovered that template_lock => ‘insert’ does not allow insertion of additional blocks. From the Gutenberg Handbook, there are only two options:
Options:
all — prevents all operations. It is not possible to insert new blocks, move existing blocks, or delete blocks.
insert — prevents inserting or removing blocks, but allows moving existing blocks.
Even ‘insert’ seems excessively restrictive to me. As soon as that’s set, the user can’t even start a new paragraph!
Unless I’m missing something, the only way I can see to create a nested template that the user can create in but not break is by installing something quite heavy duty like Matt Watson’s plugin ‘Secure Blocks for Gutenberg’ which is way OTT for my purpose. Anway, hope the above is useful.
LikeLike
Thanks for sharing this tutorial. Can you also please guide me how can I create a block template? I am doing the same using this resource https://wpitech.com/create-wordpress-gutenberg-block-templates/ but it’s giving an error and I am having some programming lines in front end. This is the code
add_action( ‘init’, function() {
$args = array(
‘public’ => true,
‘label’ => ‘News’,
‘show_in_rest’ => true,
‘template_lock’ => ‘all’,
‘template’ => array(
array( ‘core/paragraph’, array(
‘placeholder’ => ‘Breaking News’,
LikeLike
Hi! You can learn all of this in my Theming with Gutenberg Course! gutenberg.courses
LikeLike