Building Custom Block Theme Templates: A Plugin Developer’s Guide
A user of my lesser-known plugin, WebberZone Knowledge Base, reported an issue with the page header not displaying when using it with the Twenty Twenty-Four or any other block theme.
The Problem
The error message I got: File Theme without header.php is deprecated since version 3.0.0 with no alternative available. Please include a header.php template in your theme. With a similar message for footer.php.
Since I haven’t used block themes personally, I didn’t realise that they don’t have a header.php or footer.php file. Instead, WordPress block themes introduce a new way of handling templates through the Full Site Editing (FSE) system. They use block templates which are simple HTML files with the necessary blocks that are processed on the fly when the site is rendered. That also means that you can’t use the template_include hook as you do with classic themes.
To make matters worse, plugins cannot register custom templates for themes in WordPress versions 6.6 and earlier. However, WordPress 6.7 will be released in a month and will introduce the function register_block_template(). This new feature will greatly simplify the process for plugins to register their block templates.
If you’re a plugin author, and you need to support any version before 6.7, you’ll need to programmatically override these templates for your custom post types and taxonomies. In this guide, I’ll walk you through the steps for overriding templates in a WordPress Block Theme to use custom ones. This is particularly useful when developing custom post types, custom taxonomies, or unique page structures that standard WordPress templates don’t cover.
Using code that I use in my Knowledge Base plugin, we will cover:
- Register custom templates for different views (archive, single, taxonomy, search)
- Override default WordPress templates with your own block-based templates
- Handle template hierarchy properly
- Support shortcode placeholders in templates
I’m going to assume that you have a basic understanding of PHP, WordPress and plugin development. You would have already created custom post types.
Step 1: Create the Template Handler Class
This class manages how WordPress selects the custom templates for our custom post types and taxonomies. Here’s a breakdown of how it works.
- Filter
get_block_templatesOpens in a new window: This is the most important part of the code below. It registers a callback that we will use to “insert” our block template on the fly. - Filter Template Hierarchy: The constructor registers a filter for each of the template types (e.g., archive, single, taxonomy). This filter allows WordPress to recognise the custom templates and assign them based on the current context.
- Function Mapping: We map each template type to a callback function, which processes and assigns a specific template from the theme or plugin directory.
Here’s the initial setup for the Template_Handler class:
The registration of the {$type}_template_hierarchyOpens in a new window was needed because Query Monitor kept throwing up warnings. It’s also good practice as we tell WordPress to include our templates within the hierarchy.
Possible hook names include:
404_template_hierarchyarchive_template_hierarchyattachment_template_hierarchyauthor_template_hierarchycategory_template_hierarchydate_template_hierarchyembed_template_hierarchyfrontpage_template_hierarchyhome_template_hierarchyindex_template_hierarchypage_template_hierarchypaged_template_hierarchyprivacypolicy_template_hierarchysearch_template_hierarchysingle_template_hierarchysingular_template_hierarchytag_template_hierarchytaxonomy_template_hierarchy
For my Knowledge Base plugin, I needed the five as specified above in $template_types.
Step 3: Manage Block Templates
The manage_block_templates method in the Template_Handler class dynamically assigns a block template based on the custom post type or taxonomy.
Here’s how the function works:
- Check Template Type:
- Ensures the function runs only when
$template_typeiswp_template.
- Ensures the function runs only when
- Post Type Validation:
- Check if
$postexists globally. - Verifies the
$post->post_typematcheswz_knowledgebase, skipping if not. Change this to your custom post type name.
- Check if
- Identify Template Name:
- Determines the template file name based on the current page context:
single-wz_knowledgebasefor single pages.archive-wz_knowledgebasefor archives.taxonomy-wzkb_categoryfor category archives.wzkb-searchfor search results specific to the post type.
- Determines the template file name based on the current page context:
- Template Source and Path:
- Attempts to load the template from the theme’s
templatesdirectory, defaulting to the plugin’stemplatesdirectory if unavailable. This allows a theme to override the templates included in the plugin.
- Attempts to load the template from the theme’s
- Create WP_Block_Template Object:
- This is the most important part of the code as we create a new block template object on the fly.
- Builds a new block template object with details like
theme,slug,title, andsource. Modify the various properties to fit your custom post type. - Populates
contentwith template file contents, including any custom shortcode processing.
- Update Query Results:
- Appends the new template object to
$query_resultand returns it.
- Appends the new template object to
Step 3: Define Custom Template Loading Methods
For each template type, define a function to load a specific template when relevant conditions are met. Here are examples of archive, single, and taxonomy templates.
The add_custom_template function updates the template hierarchy based on custom conditions. For example, if viewing a taxonomy page, it’ll use taxonomy-wzkb_category.html if available.
Step 4: Replacing Placeholders with Shortcodes (optional)
This additional step allows dynamic shortcodes in block templates by finding placeholders and converting them to shortcodes. In my case, I needed to process shortcodes to display the custom search form and the knowledge base.
The above function uses regex to find the shortcodes with their parameters and then process them using do_shortcode.
Step 5: An example template
You’ll need to create the various block templates to display the archive, single post, etc. I used the Twenty Twenty Four templatesOpens in a new window as a base as I wanted to support this out of the box.
Here’s a basic block template you can use. It includes placeholders that our function will swap out with dynamic shortcode output.
I found creating the template the most complex part especially as the plugin needs to support multiple themes.
Step 6: Initialise the Template Handler
Either in the same class file or somewhere else in your plugin initialise the Template Handler.
Closing words
This tutorial demonstrates how to integrate custom templates into WordPress block themes. While template handling will be simplified in WordPress 6.7, this approach remains valuable for plugins needing to provide custom layouts while supporting modern WordPress features.
The code showcases how easily you can hook into WordPress’s templating system and extend it with your custom templates. Adapt these patterns to match your specific project requirements.
Check out the plugin’s GitHub repository for a complete implementation, including the full Template_Handler classOpens in a new window and corresponding templatesOpens in a new window.

