How to Create Custom Page Templates in a Full-Site Editing Theme
Custom page templates have always been a cornerstone of WordPress theme development. With Full-Site Editing (FSE), creating these templates has become more intuitive and powerful than ever. Instead of writing PHP files with mixed logic and presentation, you now work with visual blocks and clean HTML markup.
This guide will walk you through everything you need to know about creating custom page templates in FSE themes, from understanding the new template hierarchy to building complex layouts for specific use cases.
Table of Contents
- Template Hierarchy in FSE
- Creating Templates via Site Editor
- Code-Based Template Creation
- Template Parts Strategy
- Conditional Template Logic
- Portfolio and Landing Page Examples
Template Hierarchy in FSE
Understanding the New Hierarchy
FSE maintains WordPress's traditional template hierarchy but implements it through HTML files instead of PHP. Understanding this hierarchy is crucial for creating templates that WordPress will automatically use for specific content.
Template Priority Order
Single Post View:
1. templates/single-{post-type}-{slug}.html
2. templates/single-{post-type}.html
3. templates/single.html
4. templates/singular.html
5. templates/index.html
Page View:
1. templates/page-{slug}.html
2. templates/page-{id}.html
3. templates/page.html
4. templates/singular.html
5. templates/index.html
Archive View:
1. templates/category-{slug}.html
2. templates/category-{id}.html
3. templates/category.html
4. templates/archive.html
5. templates/index.html
File Structure for Templates
block-theme/
├── templates/
│ ├── index.html # Fallback template
│ ├── front-page.html # Homepage
│ ├── single.html # Single posts
│ ├── page.html # Static pages
│ ├── archive.html # Archive pages
│ ├── search.html # Search results
│ ├── 404.html # Error page
│ ├── single-product.html # Custom post type
│ └── page-custom.html # Custom page template
└── parts/
├── header.html
├── footer.html
└── sidebar.html
Template Registration in theme.json
{
"version": 2,
"customTemplates": [
{
"name": "page-no-title",
"title": "Page (No Title)",
"postTypes": ["page"]
},
{
"name": "page-sidebar",
"title": "Page with Sidebar",
"postTypes": ["page"]
},
{
"name": "page-full-width",
"title": "Full Width Page",
"postTypes": ["page", "post"]
},
{
"name": "portfolio-item",
"title": "Portfolio Item",
"postTypes": ["portfolio"]
}
]
}
Creating Templates via Site Editor
Step-by-Step Visual Creation
1. Access the Site Editor
Navigate to Appearance → Editor or use the admin bar when viewing your site.
2. Navigate to Templates
Click on Templates in the navigation sidebar to view all available templates.
3. Create New Template
Click Add New and choose: - Template type (Page, Post, Archive, etc.) - Specific page/post to create template for - Or create a generic template
4. Design Your Template
Basic Page Template Structure:
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
<!-- wp:post-title {"level":1} /-->
<!-- wp:post-content {"layout":{"type":"constrained"}} /-->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
Advanced Template Patterns
Hero Page Template
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:cover {"url":"featured-image","dimRatio":50,"minHeight":500,"align":"full"} -->
<div class="wp-block-cover alignfull" style="min-height:500px">
<div class="wp-block-cover__inner-container">
<!-- wp:post-title {"level":1,"textAlign":"center","style":{"color":{"text":"#ffffff"}}} /-->
</div>
</div>
<!-- /wp:cover -->
<!-- wp:group {"style":{"spacing":{"padding":{"top":"4rem","bottom":"4rem"}}}} -->
<div class="wp-block-group" style="padding-top:4rem;padding-bottom:4rem">
<!-- wp:post-content {"layout":{"type":"constrained"}} /-->
</div>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
Two-Column Layout Template
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:columns {"align":"wide","style":{"spacing":{"margin":{"top":"4rem","bottom":"4rem"}}}} -->
<div class="wp-block-columns alignwide" style="margin-top:4rem;margin-bottom:4rem">
<!-- wp:column {"width":"70%"} -->
<div class="wp-block-column" style="flex-basis:70%">
<!-- wp:post-title {"level":1} /-->
<!-- wp:post-content /-->
</div>
<!-- /wp:column -->
<!-- wp:column {"width":"30%"} -->
<div class="wp-block-column" style="flex-basis:30%">
<!-- wp:template-part {"slug":"sidebar"} /-->
</div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
Code-Based Template Creation
Creating Template Files Directly
Basic Template Structure
File: templates/page-landing.html
<!-- wp:template-part {"slug":"header-minimal","tagName":"header"} /-->
<!-- wp:group {"align":"full","layout":{"type":"default"}} -->
<div class="wp-block-group alignfull">
<!-- wp:pattern {"slug":"theme-name/hero-section"} /-->
<!-- wp:group {"style":{"spacing":{"padding":{"top":"0","bottom":"0"}}}} -->
<div class="wp-block-group" style="padding-top:0;padding-bottom:0">
<!-- wp:post-content {"layout":{"type":"constrained"}} /-->
</div>
<!-- /wp:group -->
<!-- wp:pattern {"slug":"theme-name/cta-section"} /-->
</div>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer-minimal","tagName":"footer"} /-->
Dynamic Content Templates
Portfolio Grid Template
File: templates/archive-portfolio.html
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:group {"tagName":"main","style":{"spacing":{"padding":{"top":"4rem","bottom":"4rem"}}}} -->
<main class="wp-block-group" style="padding-top:4rem;padding-bottom:4rem">
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:heading {"textAlign":"center","level":1} -->
<h1 class="has-text-align-center">Our Portfolio</h1>
<!-- /wp:heading -->
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">Explore our latest projects and creative work</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
<!-- wp:query {"queryId":1,"query":{"perPage":9,"postType":"portfolio","order":"desc","orderBy":"date"},"displayLayout":{"type":"flex","columns":3},"align":"wide"} -->
<div class="wp-block-query alignwide">
<!-- wp:post-template -->
<!-- wp:group {"style":{"spacing":{"padding":"0"}},"className":"portfolio-item"} -->
<div class="wp-block-group portfolio-item" style="padding:0">
<!-- wp:post-featured-image {"isLink":true,"aspectRatio":"16/9"} /-->
<!-- wp:group {"style":{"spacing":{"padding":"1rem"}}} -->
<div class="wp-block-group" style="padding:1rem">
<!-- wp:post-title {"level":3,"isLink":true} /-->
<!-- wp:post-excerpt {"moreText":"View Project →"} /-->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
<!-- /wp:post-template -->
<!-- wp:query-pagination {"layout":{"type":"flex","justifyContent":"center"}} -->
<!-- wp:query-pagination-previous /-->
<!-- wp:query-pagination-numbers /-->
<!-- wp:query-pagination-next /-->
<!-- /wp:query-pagination -->
</div>
<!-- /wp:query -->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
Template with Custom Blocks
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:group {"tagName":"main"} -->
<main class="wp-block-group">
<!-- wp:acf/hero-block {
"name": "acf/hero-block",
"data": {
"field_hero_title": "",
"field_hero_subtitle": "",
"_field_hero_title": "field_123456",
"_field_hero_subtitle": "field_789012"
}
} /-->
<!-- wp:post-content {"layout":{"type":"constrained"}} /-->
<!-- wp:my-plugin/related-posts {
"numberOfPosts": 3,
"displayFeaturedImage": true
} /-->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
Template Parts Strategy
Creating Reusable Template Parts
Header Variations
File: parts/header-minimal.html
<!-- wp:group {"style":{"spacing":{"padding":{"top":"1rem","bottom":"1rem"}}},"backgroundColor":"white","className":"header-minimal"} -->
<div class="wp-block-group header-minimal has-white-background-color has-background" style="padding-top:1rem;padding-bottom:1rem">
<!-- wp:group {"layout":{"type":"flex","justifyContent":"space-between"},"align":"wide"} -->
<div class="wp-block-group alignwide">
<!-- wp:site-logo {"width":120} /-->
<!-- wp:navigation {"layout":{"type":"flex","justifyContent":"right"},"style":{"spacing":{"blockGap":"2rem"}}} /-->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
File: parts/header-centered.html
<!-- wp:group {"style":{"spacing":{"padding":{"top":"2rem","bottom":"2rem"}}},"className":"header-centered"} -->
<div class="wp-block-group header-centered" style="padding-top:2rem;padding-bottom:2rem">
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:site-logo {"width":150,"align":"center"} /-->
<!-- wp:site-title {"textAlign":"center","style":{"spacing":{"margin":{"top":"1rem"}}}} /-->
<!-- wp:site-tagline {"textAlign":"center"} /-->
<!-- wp:navigation {"layout":{"type":"flex","justifyContent":"center"},"style":{"spacing":{"margin":{"top":"2rem"}}}} /-->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
Conditional Template Parts
While FSE doesn't support PHP conditions directly, you can create variations:
Different Headers for Different Templates
In theme.json:
{
"templateParts": [
{
"area": "header",
"name": "header",
"title": "Header Default"
},
{
"area": "header",
"name": "header-minimal",
"title": "Header Minimal"
},
{
"area": "header",
"name": "header-transparent",
"title": "Header Transparent"
}
]
}
Then use specific headers in different templates:
<!-- For landing pages -->
<!-- wp:template-part {"slug":"header-minimal","tagName":"header"} /-->
<!-- For regular pages -->
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
Conditional Template Logic
Working Around PHP Limitations
Since FSE templates are HTML-based, traditional PHP conditionals aren't available. Here are strategies to achieve conditional behavior:
1. Query Block Conditions
<!-- Show content only if posts exist -->
<!-- wp:query {"query":{"perPage":1,"postType":"announcement"}} -->
<div class="wp-block-query">
<!-- wp:post-template -->
<!-- wp:group {"style":{"spacing":{"padding":"1rem"}},"backgroundColor":"accent"} -->
<div class="wp-block-group has-accent-background-color has-background" style="padding:1rem">
<!-- wp:heading {"level":4} -->
<h4>Latest Announcement</h4>
<!-- /wp:heading -->
<!-- wp:post-title {"isLink":true} /-->
</div>
<!-- /wp:group -->
<!-- /wp:post-template -->
</div>
<!-- /wp:query -->
2. Block Visibility Controls
Use plugins or block supports for conditional display:
<!-- wp:group {"metadata":{"showOnlyOn":"desktop"}} -->
<div class="wp-block-group">
<!-- Desktop-only content -->
</div>
<!-- /wp:group -->
3. Custom Block Solutions
Create a custom block for complex conditions:
register_block_type('mytheme/conditional-content', array(
'render_callback' => function($attributes) {
if (is_user_logged_in()) {
return $attributes['loggedInContent'];
}
return $attributes['loggedOutContent'];
}
));
Portfolio and Landing Page Examples
Complete Portfolio Template
File: templates/single-portfolio.html
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:group {"tagName":"main","align":"full"} -->
<main class="wp-block-group alignfull">
<!-- Hero Section with Featured Image -->
<!-- wp:cover {"useFeaturedImage":true,"dimRatio":30,"minHeight":600,"align":"full"} -->
<div class="wp-block-cover alignfull" style="min-height:600px">
<div class="wp-block-cover__inner-container">
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:post-title {"level":1,"textAlign":"center","style":{"color":{"text":"#ffffff"}}} /-->
<!-- wp:group {"layout":{"type":"flex","justifyContent":"center"},"style":{"spacing":{"margin":{"top":"2rem"}}}} -->
<div class="wp-block-group" style="margin-top:2rem">
<!-- wp:post-terms {"term":"portfolio-category","style":{"color":{"text":"#ffffff"}}} /-->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
</div>
</div>
<!-- /wp:cover -->
<!-- Project Details -->
<!-- wp:group {"style":{"spacing":{"padding":{"top":"4rem","bottom":"2rem"}}}} -->
<div class="wp-block-group" style="padding-top:4rem;padding-bottom:2rem">
<!-- wp:columns {"align":"wide"} -->
<div class="wp-block-columns alignwide">
<!-- wp:column {"width":"30%"} -->
<div class="wp-block-column" style="flex-basis:30%">
<!-- wp:heading {"level":3} -->
<h3>Project Details</h3>
<!-- /wp:heading -->
<!-- wp:group {"className":"project-meta"} -->
<div class="wp-block-group project-meta">
<!-- Custom fields would go here -->
<!-- Client, Date, Technologies, etc. -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:column -->
<!-- wp:column {"width":"70%"} -->
<div class="wp-block-column" style="flex-basis:70%">
<!-- wp:post-content /-->
</div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->
</div>
<!-- /wp:group -->
<!-- Related Projects -->
<!-- wp:group {"style":{"spacing":{"padding":{"top":"4rem","bottom":"4rem"}}},"backgroundColor":"light-gray"} -->
<div class="wp-block-group has-light-gray-background-color has-background" style="padding-top:4rem;padding-bottom:4rem">
<!-- wp:heading {"textAlign":"center"} -->
<h2 class="has-text-align-center">Related Projects</h2>
<!-- /wp:heading -->
<!-- wp:query {"queryId":2,"query":{"perPage":3,"postType":"portfolio","exclude":[0],"orderBy":"rand"}} -->
<div class="wp-block-query">
<!-- Query content here -->
</div>
<!-- /wp:query -->
</div>
<!-- /wp:group -->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
Landing Page Template
File: templates/page-landing.html
<!-- wp:template-part {"slug":"header-transparent","tagName":"header","className":"site-header-transparent"} /-->
<!-- wp:group {"tagName":"main","align":"full","className":"landing-page"} -->
<main class="wp-block-group alignfull landing-page">
<!-- Hero Section -->
<!-- wp:pattern {"slug":"mytheme/hero-landing"} /-->
<!-- Features Section -->
<!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"5rem","bottom":"5rem"}}}} -->
<div class="wp-block-group alignfull" style="padding-top:5rem;padding-bottom:5rem">
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:heading {"textAlign":"center"} -->
<h2 class="has-text-align-center">Why Choose Us</h2>
<!-- /wp:heading -->
<!-- wp:columns {"align":"wide","style":{"spacing":{"margin":{"top":"3rem"}}}} -->
<div class="wp-block-columns alignwide" style="margin-top:3rem">
<!-- Feature columns -->
</div>
<!-- /wp:columns -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
<!-- Testimonials -->
<!-- wp:pattern {"slug":"mytheme/testimonials-carousel"} /-->
<!-- CTA Section -->
<!-- wp:pattern {"slug":"mytheme/cta-download"} /-->
<!-- Content Section -->
<!-- wp:group {"style":{"spacing":{"padding":{"top":"4rem","bottom":"4rem"}}}} -->
<div class="wp-block-group" style="padding-top:4rem;padding-bottom:4rem">
<!-- wp:post-content {"layout":{"type":"constrained"}} /-->
</div>
<!-- /wp:group -->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer-minimal","tagName":"footer"} /-->
Best Practices for Custom Templates
1. Template Organization
templates/
├── Core Templates/
│ ├── index.html
│ ├── single.html
│ └── page.html
├── Custom Page Templates/
│ ├── page-no-title.html
│ ├── page-sidebar.html
│ └── page-landing.html
└── Post Type Templates/
├── single-portfolio.html
└── archive-portfolio.html
2. Naming Conventions
- Use descriptive names:
page-contact-form.html
- Follow WordPress conventions:
single-{post-type}.html
- Group related templates:
page-landing-*.html
3. Performance Optimization
<!-- Optimize images -->
<!-- wp:post-featured-image {"sizeSlug":"large","isLink":false} /-->
<!-- Lazy load content below fold -->
<!-- wp:group {"metadata":{"loading":"lazy"}} -->
<!-- Use constrained layouts -->
<!-- wp:post-content {"layout":{"type":"constrained"}} /-->
4. Accessibility Considerations
<!-- Proper heading hierarchy -->
<!-- wp:post-title {"level":1} /-->
<!-- Semantic HTML -->
<!-- wp:group {"tagName":"main"} -->
<!-- wp:group {"tagName":"article"} -->
<!-- Skip links in header -->
<!-- wp:skip-link {"target":"main"} /-->
Conclusion
Creating custom page templates in FSE represents a significant evolution in WordPress theme development. The visual approach combined with clean markup makes template creation more accessible while maintaining the flexibility developers need.
Key takeaways: - Understand the template hierarchy for automatic template selection - Use the Site Editor for quick visual template creation - Leverage template parts for reusable components - Create multiple template variations for different use cases - Optimize for performance and accessibility
As you become comfortable with FSE templates, you'll find that complex layouts that once required extensive PHP can now be created visually, making WordPress development faster and more enjoyable.
Want to learn more about modern WordPress development? Check out our comprehensive Ultimate Guide to Gutenberg and Full-Site Editing for advanced techniques and best practices.