The WordPress template hierarchy is the system WordPress uses to decide which template file renders a given page. In classic themes, this meant PHP files like single.php, archive.php, and page.php. In block themes, the same hierarchy applies — but with HTML files, different override paths, and the Site Editor adding a new layer of customization.
Understanding how template resolution works in block themes is essential for building themes that behave predictably. This guide covers the complete hierarchy, the resolution order, custom templates, and how the Site Editor interacts with file-based templates.
If you are new to block themes, start with our block themes vs classic themes migration guide for the broader context.
How Template Resolution Works in Block Themes
When a visitor requests a page, WordPress follows a specific decision tree to find the right template. The process works in three layers:
- Database-stored templates — Custom templates created or modified in the Site Editor are saved in the
wp_templatepost type. These always take priority. - Theme file templates — HTML files in the theme’s
templates/directory. - Fallback chain — If no specific template matches, WordPress walks up the hierarchy to more general templates until it reaches
index.html.
This layered approach means users can customize templates in the Site Editor without touching theme files, while developers can provide sensible defaults through the file system.
The template hierarchy in block themes follows the same resolution logic as classic themes, but adds a powerful new layer: database-stored templates from the Site Editor always take priority over file-based templates, giving users full control without touching code.
The Complete Template Hierarchy
Here is the full resolution order for every major page type. WordPress starts at the most specific template and falls back through each level until it finds a match.
Single Posts
When a visitor views a single blog post:
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | single-post-{slug}.html |
Specific post by slug |
| 2 | single-post.html |
All posts |
| 3 | single.html |
Any single content type |
| 4 | singular.html |
Any single post or page |
| 5 | index.html |
Ultimate fallback |
Custom Post Types
For a custom post type like portfolio:
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | single-portfolio-{slug}.html |
Specific portfolio item by slug |
| 2 | single-portfolio.html |
All portfolio items |
| 3 | single.html |
Any single content type |
| 4 | singular.html |
Any single post or page |
| 5 | index.html |
Ultimate fallback |
Pages
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | page-{slug}.html |
Specific page by slug |
| 2 | page-{id}.html |
Specific page by ID |
| 3 | page.html |
All pages |
| 4 | singular.html |
Any single post or page |
| 5 | index.html |
Ultimate fallback |
Category Archives
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | category-{slug}.html |
Specific category by slug |
| 2 | category-{id}.html |
Specific category by ID |
| 3 | category.html |
All category archives |
| 4 | archive.html |
All archives |
| 5 | index.html |
Ultimate fallback |
Tag Archives
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | tag-{slug}.html |
Specific tag by slug |
| 2 | tag-{id}.html |
Specific tag by ID |
| 3 | tag.html |
All tag archives |
| 4 | archive.html |
All archives |
| 5 | index.html |
Ultimate fallback |
Custom Taxonomy Archives
For a taxonomy like genre:
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | taxonomy-genre-{term}.html |
Specific term in the taxonomy |
| 2 | taxonomy-genre.html |
All terms in the genre taxonomy |
| 3 | taxonomy.html |
All custom taxonomy archives |
| 4 | archive.html |
All archives |
| 5 | index.html |
Ultimate fallback |
Author Archives
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | author-{nicename}.html |
Specific author by nicename |
| 2 | author-{id}.html |
Specific author by ID |
| 3 | author.html |
All author archives |
| 4 | archive.html |
All archives |
| 5 | index.html |
Ultimate fallback |
Date Archives
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | date.html |
All date-based archives |
| 2 | archive.html |
All archives |
| 3 | index.html |
Ultimate fallback |
Search Results
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | search.html |
Search results page |
| 2 | index.html |
Ultimate fallback |
404 Page
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | 404.html |
Page not found |
| 2 | index.html |
Ultimate fallback |
Front Page
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | front-page.html |
Site front page (regardless of Settings > Reading) |
| 2 | home.html |
Blog posts page |
| 3 | page.html |
If front page is set to a static page |
| 4 | index.html |
Ultimate fallback |
Blog / Posts Page
| Priority | Template File | When It Matches |
|---|---|---|
| 1 | home.html |
Blog posts listing page |
| 2 | index.html |
Ultimate fallback |
Block Theme File Structure
In a block theme, templates live in the templates/ directory as HTML files containing block markup. Here is a typical structure:
my-theme/
├── templates/
│ ├── index.html
│ ├── single.html
│ ├── page.html
│ ├── archive.html
│ ├── search.html
│ ├── 404.html
│ ├── home.html
│ ├── front-page.html
│ ├── category.html
│ └── single-portfolio.html
├── parts/
│ ├── header.html
│ ├── footer.html
│ └── sidebar.html
├── patterns/
├── theme.json
└── style.css
Each HTML file contains WordPress block markup. For example, a minimal single.html:
<!-- wp:template-part {"slug":"header","area":"header"} /-->
<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
<!-- wp:post-title {"level":1} /-->
<!-- wp:post-date /-->
<!-- wp:post-content {"layout":{"type":"constrained"}} /-->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","area":"footer"} /-->
For a deep dive into the parts/ directory, see our template parts developer deep-dive.
Custom Templates in Block Themes
Block themes support custom page templates that users can assign to individual pages or posts through the editor. Register them in theme.json:
{
"customTemplates": [
{
"name": "page-no-title",
"title": "Page (No Title)",
"postTypes": ["page"]
},
{
"name": "page-wide",
"title": "Full Width Page",
"postTypes": ["page", "post"]
},
{
"name": "blank",
"title": "Blank Canvas",
"postTypes": ["page", "post"]
}
]
}
Then create the corresponding HTML files in the templates/ directory:
templates/page-no-title.htmltemplates/page-wide.htmltemplates/blank.html
When a user assigns a custom template to a page, it takes priority over the entire hierarchy — even over page-{slug}.html.
Site Editor vs File-Based Templates: Resolution Priority
The Site Editor introduces a critical override layer. Here is the exact resolution order when both file-based and Site Editor templates exist:
| Priority | Source | Description |
|---|---|---|
| 1 (highest) | User-assigned custom template | Template explicitly chosen by the user for a specific page/post |
| 2 | Database (Site Editor modifications) | Templates saved via Appearance > Editor |
| 3 | Child theme templates/ |
HTML files in the child theme |
| 4 | Parent theme templates/ |
HTML files in the parent theme |
| 5 (lowest) | WordPress core fallback | index.html or core default |
This means:
- A user can customize any template in the Site Editor, and their changes override the theme file
- If the user resets a template in the Site Editor, it falls back to the theme file version
- Child themes override parent themes at the file level, just like classic themes
Key Differences from Classic Theme Hierarchy
While the template hierarchy logic is the same, block themes have important differences:
| Aspect | Classic Themes | Block Themes |
|---|---|---|
| File format | .php files | .html files with block markup |
| Template directory | Theme root | templates/ subdirectory |
| Template parts | get_template_part() |
parts/ directory + <!-- wp:template-part --> |
| User overrides | Not possible without code | Site Editor saves to database |
| Custom templates | PHP comment header | theme.json customTemplates array |
| Conditional logic | PHP conditionals in templates | Block Visibility controls (WP 6.9+) |
| Dynamic content | PHP functions | Dynamic blocks + Query Loop block |
If you are migrating from a classic theme, the naming conventions are the same. Rename your .php files to .html, move them to templates/, and replace PHP code with block markup.
Practical Examples
Example 1: Different Layout for a Specific Category
To create a unique layout for the “tutorials” category, add templates/category-tutorials.html:
<!-- wp:template-part {"slug":"header","area":"header"} /-->
<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
<!-- wp:query-title {"type":"archive"} /-->
<!-- wp:term-description /-->
<!-- wp:query {"queryId":1,"query":{"perPage":12},"displayLayout":{"type":"flex","columns":3}} -->
<!-- wp:post-template -->
<!-- wp:post-featured-image {"isLink":true} /-->
<!-- wp:post-title {"isLink":true} /-->
<!-- wp:post-excerpt /-->
<!-- /wp:post-template -->
<!-- wp:query-pagination /-->
<!-- /wp:query -->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","area":"footer"} /-->
WordPress will use this template for the tutorials category archive, while all other categories fall back to category.html or archive.html.
Example 2: Custom Single Template for a CPT
For a portfolio custom post type, create templates/single-portfolio.html with a full-width layout and no sidebar.
Example 3: Custom 404 Page
Create templates/404.html with a search form and popular posts pattern to help visitors find what they need.
Debugging Template Resolution
When you are not sure which template WordPress is using, these tools help:
Query Monitor Plugin
Install Query Monitor and check the “Template” panel. It shows the exact template file being used, the template hierarchy for the current request, and the order WordPress checked.
Template Block Inspector
In the Site Editor, open any template and check the Template panel in the sidebar. It shows whether the template is from the theme file or has been customized in the database.
WP-CLI
wp post list --post_type=wp_template --fields=ID,post_name,post_status
This lists all database-stored templates. If a template appears here with status publish, it overrides the theme file version.
Best Practices for Block Theme Templates
- Always include
index.html— It is the only required template. Without it, WordPress does not recognize your theme as a block theme. - Use template parts for reusable sections — Headers, footers, and sidebars belong in
parts/. See our template parts guide for implementation details. - Register custom templates in theme.json — This makes them visible in the editor’s template selector. Do not rely on file naming alone.
- Use block patterns for content sections — Instead of creating many similar templates, create one template that references patterns for different content layouts.
- Style through theme.json global styles — Avoid adding inline styles in template HTML. Use theme.json for consistent design tokens.
- Keep templates minimal — Templates should define structure (header, content area, footer). Content styling should come from theme.json and CSS.
- Test with the Site Editor — Users will modify your templates. Make sure they look correct when blocks are rearranged or removed.
Frequently Asked Questions
Is the template hierarchy different for block themes compared to classic themes?
The resolution logic is identical. WordPress follows the same hierarchy (single-post-{slug} > single-post > single > singular > index). The difference is that block themes use .html files in a templates/ directory instead of .php files in the theme root, and users can override any template through the Site Editor.
What is the minimum template a block theme needs?
Only templates/index.html is required. WordPress uses it as the ultimate fallback for any page type that does not have a more specific template. In practice, most themes include at least index.html, single.html, page.html, archive.html, search.html, and 404.html.
Do Site Editor changes override theme files?
Yes. When a user customizes a template in the Site Editor, it is saved to the database as a wp_template post. Database templates always take priority over theme file templates. Users can reset to the theme version by clicking “Clear customizations” in the Site Editor.
Can I use PHP in block theme templates?
No. Block theme templates are HTML files containing block markup. Dynamic functionality is handled through dynamic blocks (like Query Loop, Post Title, Post Content) that execute PHP on the server when rendering. For truly custom logic, create a custom block or use the render_block filter.
How do custom templates fit into the hierarchy?
Custom templates registered in theme.json take the highest priority when assigned to a page or post. They override the entire hierarchy, including slug-specific templates. A user must explicitly assign a custom template through the page/post editor for it to take effect.
How do child themes work with block theme templates?
Child themes work the same way as classic themes. A template in the child theme’s templates/ directory overrides the same-named template in the parent theme. Database templates (Site Editor customizations) still override both child and parent theme files.
Where do template parts fit in the hierarchy?
Template parts are not part of the template hierarchy. They are reusable sections (header, footer, sidebar) included within templates using the wp:template-part block. Template parts live in the parts/ directory and follow their own resolution: database first, then child theme, then parent theme.
