Hierarquia de templates para temas block-based modernos: guia prático
Entenda a hierarquia de templates no WordPress Full Site Editing. Domine templates, partes e padrões para criar temas block-based profissionais.
Imagine que você acabou de ativar um tema block-based recém-criado. A homepage carrega, mas a página de arquivo de categoria exibe o layout de blog genérico, ignorando o arquivo category-noticias.html que você criou com carinho. O header aparece duplicado porque o header.html foi incluído tanto no template quanto no pattern de página. E o theme.json insiste em aplicar espaçamentos globais que quebram seu design system. Esse cenário é mais comum do que parece: a hierarquia de templates no Full Site Editing (FSE) segue regras precisas, mas sutis, que pegam até desenvolvedores experientes de temas clássicos.
Diferente da hierarquia baseada em PHP (single.php, archive.php, category.php), o FSE usa arquivos HTML puros na pasta /templates e partes reutilizáveis em /parts. O WordPress percorre essa hierarquia na mesma ordem lógica — do mais específico para o mais genérico —, mas a forma de incluir partes, sobrescrever padrões e depurar falhas muda radicalmente. Dominar esse fluxo é o que separa um tema que “funciona” de um tema profissional, previsível e escalável.
Neste guia, você vai percorrer a hierarquia completa na prática, entender onde cada arquivo entra, como as template parts se encaixam, como o theme.json influencia (e não influencia) o carregamento, e quais armadilhas evitar no dia a dia de desenvolvimento.
A estrutura de pastas obrigatória
Todo tema block-based moderno nasce com duas pastas essenciais na raiz: /templates e /parts. A primeira guarda os templates de página completa — index.html, single.html, page.html, archive.html, search.html, 404.html e variações específicas. A segunda armazena trechos reutilizáveis: header.html, footer.html, sidebar.html, loop.html e o que mais seu design system exigir.
tema-exemplo/
├── templates/
│ ├── index.html # fallback final
│ ├── single.html # posts padrão
│ ├── single-projeto.html # CPT "projeto"
│ ├── page.html # páginas
│ ├── archive.html # arquivos genéricos
│ ├── category.html # categorias
│ ├── category-noticias.html # categoria "notícias"
│ ├── search.html # resultados de busca
│ └── 404.html # erro 404
├── parts/
│ ├── header.html
│ ├── footer.html
│ ├── sidebar.html
│ └── loop.html
├── theme.json
├── style.css
└── functions.php
O WordPress busca o template na pasta /templates do tema ativo. Se não encontra, cai no tema pai (se houver) e, por fim, no core. A ordem de prioridade segue a mesma lógica da hierarquia clássica, apenas com extensão .html e sem PHP.
Hierarquia detalhada por tipo de conteúdo
Posts e Custom Post Types
single-{post-type}-{slug}.html— ex.:single-projeto-meu-site.htmlsingle-{post-type}.html— ex.:single-projeto.htmlsingle.htmlsingular.html(fallback para qualquer singular)index.html
Páginas
page-{slug}.html— ex.:page-sobre.htmlpage-{id}.html— ex.:page-12.htmlpage.htmlsingular.htmlindex.html
Arquivos (categorias, tags, autores, datas, CPT archives)
category-{slug}.html/tag-{slug}.html/author-{nicename}.html/date-{type}.html/archive-{post-type}.htmlcategory.html/tag.html/author.html/date.html/archive.htmlindex.html
Busca e erro
-
search.html -
index.html -
404.html -
index.html
A tabela abaixo resume a prioridade para os casos mais comuns:
| Contexto | 1º (mais específico) | 2º | 3º | 4º | 5º (fallback) |
|---|---|---|---|---|---|
| Post padrão | single-post-{slug}.html |
single-post.html |
single.html |
singular.html |
index.html |
| CPT “projeto” | single-projeto-{slug}.html |
single-projeto.html |
single.html |
singular.html |
index.html |
| Página | page-{slug}.html |
page-{id}.html |
page.html |
singular.html |
index.html |
| Categoria | category-{slug}.html |
category.html |
archive.html |
index.html |
— |
| Busca | search.html |
index.html |
— | — | — |
| 404 | 404.html |
index.html |
— | — | — |
Template Parts: reutilização sem duplicação
Template parts resolvem o problema do header duplicado do cenário inicial. Em vez de repetir o markup do cabeçalho em single.html, page.html e archive.html, você cria parts/header.html e o inclui via bloco Template Part (<!-- wp:template-part {"slug":"header"} -->).
O registro no theme.json torna a part visível no Site Editor e permite definir área (header, footer, sidebar, uncategorized) e ícone:
"templateParts": [
{
"slug": "header",
"title": "Cabeçalho principal",
"area": "header",
"icon": "layout"
},
{
"slug": "footer",
"title": "Rodapé principal",
"area": "footer",
"icon": "layout"
},
{
"slug": "loop",
"title": "Loop de posts",
"area": "uncategorized",
"icon": "list-view"
}
]
Dentro de qualquer template, a inclusão é declarativa:
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:template-part {"slug":"loop","tagName":"main"} /-->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
O atributo tagName define o elemento HTML wrapper (header, main, footer, section, div). Isso mantém a semântica e acessibilidade sem CSS extra.
O papel do theme.json na hierarquia (e o que ele NÃO faz)
Muita gente confunde theme.json com definição de templates. Ele não controla qual template carrega — isso continua sendo a nomenclatura dos arquivos em /templates. O theme.json governa:
- Settings: paleta de cores, tipografia, espaçamentos, suporte a recursos (customSpacing, appearanceTools, etc.)
- Styles: valores padrão para blocos (cores, tipografia, bordas, espaçamentos)
- Custom Templates: registro de templates personalizados que aparecem no Site Editor (
customTemplates) - Template Parts: registro das parts para o editor (
templateParts)
Se você define um template customizado no theme.json:
"customTemplates": [
{
"name": "landing-page",
"title": "Landing Page",
"postTypes": ["page"],
"description": "Template para páginas de captura"
}
]
Ele aparece no seletor de template do editor de páginas, mas não cria o arquivo landing-page.html automaticamente. Você deve criá-lo em /templates. O theme.json apenas o registra na UI.
Sobrescrevendo templates de plugins e core
Plugins como WooCommerce, The Events Calendar ou Yoast registram seus próprios templates via PHP. No FSE, você sobrescreve colocando o arquivo com o mesmo nome na pasta /templates do seu tema. Exemplo: templates/product.html substitui o template de produto do WooCommerce.
Para templates registrados via filtro theme_templates (PHP), use o mesmo filtro no seu functions.php para remover ou substituir:
add_filter('theme_templates', function($templates) {
unset($templates['plugin-template-custom']);
$templates['meu-template-custom'] = [
'title' => 'Meu Template Custom',
'description' => 'Substitui o do plugin X',
];
return $templates;
});
A prioridade é: tema filho > tema pai > plugins > core. Isso vale tanto para templates HTML (FSE) quanto para templates PHP (classic/híbrido).
Depuração prática: descubra qual template está rodando
Quando o layout não bate com o esperado, a primeira pergunta é: “qual template o WordPress carregou?”. Três abordagens rápidas:
- Query Monitor → aba “Template” mostra o arquivo exato (
templates/category-noticias.html). - Debug no
functions.php:
add_filter('template_include', function($template) {
error_log('TEMPLATE CARREGADO: ' . $template);
return $template;
});
Acompanhe no debug.log ou no console do servidor.
- Site Editor nativo: abra o editor do site, clique no ícone de engrenagem (configurações) no canto superior direito → painel lateral mostra “Template: category-noticias” com link para editar direto.
Para template parts, o painel lateral do Site Editor lista todas as parts registradas e destaca a ativa na tela.
Armadilhas comuns e como evitar
| Armadilha | Sintoma | Solução |
|---|---|---|
Esquecer index.html |
Erro crítico “Theme is missing index.html” | Criar templates/index.html mínimo com header, loop, footer |
| Duplicar header no template e no pattern | Header aparece duas vezes | Usar apenas template part header.html nos templates; não incluir no pattern de página |
Nomear arquivo errado (category-noticias.php) |
Template ignorado, cai no archive.html |
Usar extensão .html e nomenclatura exata da hierarquia |
Registrar part no theme.json mas não criar arquivo |
Erro no Site Editor “Template part not found” | Criar parts/header.html antes de registrar |
Conflito de CSS global do theme.json com template específico |
Espaçamentos quebrados em um template só | Usar styles.blocks['core/group'] no theme.json ou sobrescrever no template com classes utilitárias |
Não testar fallback singular.html |
CPT novo sem template próprio herda layout errado | Criar singular.html genérico bem estruturado como base |
Boas práticas para equipes e manutenção
- Documente a hierarquia no README: liste todos os templates, parts e a prioridade de cada um. Novos devs entendem o mapa mental em minutos.
- Use
singular.htmlcomo base compartilhada:single.htmlepage.htmlpodem ser apenas includes dosingular.htmlcom pequenas variações (via blocoTemplate Partcondicional ou patterns). - Separe loop em
parts/loop.html: reutiliza emarchive.html,search.html,category.htmlesingle.html(related posts). - Versionamento de templates: ao alterar estrutura de um template, crie versão (
single-v2.html) e teste em staging antes de renomear. - Lint no CI: valide JSON do
theme.jsone HTML dos templates (w3c validator ou htmlhint) no pipeline.
Para aprofundar na criação de blocos dinâmicos que alimentam esses templates, veja como criar blocos Gutenberg dinâmicos com React. Se o foco é performance, eliminando recursos bloqueantes de renderização mostra como o FSE impacta Core Web Vitals. E para dados seguros em metaboxes que alimentam templates, consulte sanitização e validação de dados em metaboxes personalizados.
A hierarquia de templates no FSE não é mistério — é convenção sobre configuração aplicada a arquivos HTML. Quando você internaliza a ordem de prioridade, entende o papel das template parts e sabe depurar em segundos, o desenvolvimento de temas block-based deixa de ser tentativa e erro e vira engenharia previsível. Comece pelo index.html, registre suas parts no theme.json, teste cada nível da hierarquia com Query Monitor e documente tudo. Seu futuro eu (e sua equipe) vão agradecer.
Checklist prático
Perguntas frequentes
Qual a diferença entre template e template part na hierarquia do FSE?
Templates definem a estrutura completa de uma página (como single.html ou page.html), enquanto template parts são trechos reutilizáveis como header, footer ou sidebar. O WordPress carrega o template conforme a hierarquia e, dentro dele, incluem-se as parts via bloco Template Part.
O arquivo theme.json substitui a hierarquia de templates tradicional?
Não. O theme.json configura estilos globais, settings e customizações de blocos, mas não define qual template será carregado. A hierarquia continua baseada nos nomes dos arquivos HTML na pasta /templates, seguindo a nomenclatura padrão do WordPress.
Como criar um template exclusivo para uma categoria específica no FSE?
Crie um arquivo chamado category-{slug}.html ou category-{id}.html dentro da pasta /templates. O WordPress prioriza esse arquivo sobre o category.html genérico e o archive.html, seguindo a mesma lógica da hierarquia clássica.
Posso sobrescrever templates do core ou de plugins no meu tema block-based?
Sim. Coloque o arquivo com o mesmo nome na pasta /templates do seu tema. O WordPress prioriza o tema ativo em relação a plugins e core. Para templates de blocos registrados via PHP, use o filtro 'theme_templates' para substituí-los.
O que acontece se não existir nenhum template correspondente na hierarquia?
O WordPress cai no fallback final: index.html na raiz da pasta /templates. Se nem ele existir, o site exibe erro crítico. Por isso, todo tema block-based deve ter, no mínimo, index.html e os templates principais (single.html, page.html, archive.html, search.html, 404.html).
Como depurar qual template está sendo carregado em tempo real?
Use o plugin Query Monitor ou adicione `add_filter('template_include', function($t) { error_log('Template: ' . $t); return $t; });` no functions.php. No Site Editor, o painel lateral mostra o template ativo ao clicar no ícone de engrenagem da tela.