Temas E Arquitetura

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

  1. single-{post-type}-{slug}.html — ex.: single-projeto-meu-site.html
  2. single-{post-type}.html — ex.: single-projeto.html
  3. single.html
  4. singular.html (fallback para qualquer singular)
  5. index.html

Páginas

  1. page-{slug}.html — ex.: page-sobre.html
  2. page-{id}.html — ex.: page-12.html
  3. page.html
  4. singular.html
  5. index.html

Arquivos (categorias, tags, autores, datas, CPT archives)

  1. category-{slug}.html / tag-{slug}.html / author-{nicename}.html / date-{type}.html / archive-{post-type}.html
  2. category.html / tag.html / author.html / date.html / archive.html
  3. index.html

Busca e erro

  1. search.html

  2. index.html

  3. 404.html

  4. 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:

  1. Query Monitor → aba “Template” mostra o arquivo exato (templates/category-noticias.html).
  2. 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.

  1. 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

  1. Documente a hierarquia no README: liste todos os templates, parts e a prioridade de cada um. Novos devs entendem o mapa mental em minutos.
  2. Use singular.html como base compartilhada: single.html e page.html podem ser apenas includes do singular.html com pequenas variações (via bloco Template Part condicional ou patterns).
  3. Separe loop em parts/loop.html: reutiliza em archive.html, search.html, category.html e single.html (related posts).
  4. Versionamento de templates: ao alterar estrutura de um template, crie versão (single-v2.html) e teste em staging antes de renomear.
  5. Lint no CI: valide JSON do theme.json e 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

0 de 9 concluídos

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.