Capítulo 46
Gerador estático
7 min de leitura 1.231 palavras 2 gravuras
Este capítulo explica a ideia de um gerador de site estático sem obrigar Jekyll nem Ruby no Windows. A Oficina Costeira é um coletivo fictício de design em João Pessoa. Este volume tem 52 capítulos. Esta é a 46.
O exemplo está em exemplos/46-gerador-estatico/. O caminho que você usa de verdade é copiar cabeçalho e rodapé entre as páginas, com cuidado. Ciclo: ler, copiar, mudar uma coisa, prever, recarregar, conferir.
O que você vai aprender
- Entender o problema: o mesmo
headerem cinco HTML. - Separar a ideia de gerador da ferramenta famosa de um sistema.
- Trabalhar no Windows sem instalar Ruby.
- Manter includes manuais (copiar e colar com conferência).
- Conhecer Eleventy só como extra opcional.
- Servir o resultado em
127.0.0.1, nunca como publicação.
O problema que o gerador quer resolver
A Oficina Costeira tem Início, Projetos, Equipe, Agenda e Contato. Cada arquivo repete skip-link, cabeçalho, menu e rodapé. Se o menu ganha um item, você edita cinco vezes. Se esquecer uma, o site mente.
Um gerador estático lê pedaços (miolo + molde) e escreve HTML pronto. O navegador recebe arquivos comuns. Não há PHP neste volume. Não há banco. O resultado ainda é página estática.
A ideia vale. A ferramenta obrigatória, neste volume, não vale. Jekyll nasceu em Ruby, comum em macOS de laboratório antigo. No Windows do aluno isso vira instalação longa, versão de Ruby, e um erro de gem que não ensina HTML.
Você sai deste capítulo sabendo o problema e um método que já funciona: arquivo de referência do cabeçalho + copiar com conferência.
Erro comum: achar que “site estático” precisa de gerador. Cinco HTML copiados com cuidado já são um site estático.
Windows primeiro: o que você não instala
Neste volume você não precisa de:
- Ruby;
- Jekyll;
- Bundler;
- GitHub Pages como único caminho;
- terminal Unix para “o site existir”.
Você precisa de:
- editor;
- pasta do exemplo;
- navegador;
- se quiser testar caminhos como na Web, Python com servidor em
127.0.0.1.
python -m http.server 8769 --bind 127.0.0.1 --directory curso
Visite http://127.0.0.1:8769/exemplos/46-gerador-estatico/. Encerre com Ctrl+C. Não use 0.0.0.0.
Se um tutorial mandar gem install jekyll como passo zero da Oficina Costeira, ignore. É outro recorte. A origem deste volume falava de Jekyll. A reescrita didática, no Windows, troca a obrigação por entendimento.
Mude só a porta para 8771 no comando, se 8769 estiver ocupada. Preveja a URL nova. Recarregue o endereço certo. Confira a home. Depois anote a porta no README da pasta.
Erro comum: seguir um guia de Mac e travar no “Command Line Tools”. Isso não é requisito do capítulo 46.
Include manual: o caminho do aluno
Include é um pedaço reutilizado. No gerador, um arquivo _includes/cabecalho.html entra no molde. Na Oficina Costeira, o include é um recorte que você cola.
Trabalhe com um arquivo de referência. Pode ser um comentário no topo de index.html ou um cabecalho.recorte.html dentro de .trabalho — nesta entrega o recorte vive nas próprias páginas do exemplo, iguais entre si.
Quando o menu mudar, a ordem é:
- Edite
index.html. - Copie o bloco
headerinteiro. - Cole em
projetos.html,equipe.html,agenda.html,contato.html. - Ajuste
aria-current="page"só no link da página atual. - Abra cada página e clique o menu.
<nav aria-label="Principal">
<ul class="menu">
<li><a href="index.html">Início</a></li>
<li><a href="projetos.html" aria-current="page">Projetos</a></li>
<li><a href="equipe.html">Equipe</a></li>
<li><a href="agenda.html">Agenda</a></li>
<li><a href="contato.html">Contato</a></li>
</ul>
</nav>
aria-current não se copia cego. Cada arquivo aponta para si.
Mude só o texto do link Projetos para Trabalhos em index.html. Preveja: as outras páginas ainda dizem Projetos. Recarregue cada uma. Confira. Depois propague a palavra ou desfaça. O exercício é sentir o custo da repetição.
Erro comum: copiar aria-current="page" junto com o menu para todas as páginas. O leitor de tela anuncia a página errada como atual.
Molde mental: miolo no meio
Mesmo sem gerador, pense em três faixas:
- Começo igual (doctype,
html lang="pt-BR",head, skip-link,header). - Miolo diferente (
main). - Fim igual (
footer,</body></html>).
O head também se parece, mas o title e a description mudam por página. Não copie o título da home em projetos.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Equipe — Oficina Costeira</title>
<meta name="description" content="Personagens fictícios da Oficina Costeira em João Pessoa.">
<link rel="stylesheet" href="assets/stylesheets/main.css">
</head>
<body>
<!-- cabeçalho igual, aria-current neste arquivo: Equipe -->
<main id="conteudo" class="wrap">
<h1>Equipe</h1>
<ul>
<li>Lina Vasconcelos — direção de arte (personagem fictícia).</li>
</ul>
</main>
<!-- rodapé igual -->
</body>
</html>
Mude só o title de equipe para o da home. Preveja duas abas iguais. Recarregue. Confira. Devolva Equipe — Oficina Costeira.
Erro comum: um único index.html com todas as seções e sem páginas internas, “para não copiar”. O volume treina várias URLs. O gerador, quando existir, também gera várias URLs.

Jekyll existe; Eleventy é opcional; nenhum é prova
Jekyll lê Markdown, YAML e moldes e escreve uma pasta _site. É um gerador clássico. Ele pede Ruby. Não é obrigatório instalar para concluir a Oficina Costeira.
Eleventy (11ty) é outro gerador, em JavaScript. Também é opcional. Só faça se você já tiver Node por outro motivo e quiser experimentar depois do volume. Não é exercício deste capítulo.
O que importa é a frase: HTML final, sem servidor de linguagem de página, com pedaços reutilizados. Copiar cabeçalho é a versão manual. Gerador é a versão automática. Os dois produzem o mesmo tipo de arquivo que o navegador já abre.
Não hospede no GitHub Pages “para ver o Jekyll funcionar”. Publicação está fora. Teste local em 127.0.0.1.
Mude só o rodapé em contato.html para incluir a palavra estudo. Preveja rodapé diferente só nessa página. Recarregue as outras. Confira. Unifique se quiser consistência. Você acabou de simular um include quebrado.
Erro comum: medir o volume pelo “bundler install deu certo”. O critério é o menu igual, o aria-current certo e a página abrindo.
Conferência das cinco páginas
Abra as cinco internas do exemplo. Clique todos os itens do menu. O destino deve existir. A página atual deve ter aria-current. O rodapé deve dizer que o conteúdo é fictício e que nada é enviado.
Formulário de contato: o apoio pronto cancela o envio após a validação. action="#" e method="get" sozinhos não impedem um pedido. Não grave dado. Não aponte para um e-mail real.
Lista de checagem quando o cabeçalho mudar:
lang="pt-BR"em todos;- skip-link;
- mesmo conjunto de links;
titlepróprio;- CSS no mesmo caminho
assets/stylesheets/main.css.
Isso é o gerador humano. Cansa. Ensina. Quando um gerador aparecer na sua vida profissional, você já sabe o que ele está tentando poupar.
Não publique a Oficina Costeira como portfólio pessoal com seu nome verdadeiro neste exercício.

Atividades
- Qual problema o gerador estático quer evitar na Oficina Costeira?
- Por que este volume não pede para instalar Jekyll no Windows?
- Depois de colar o menu, o que você ajusta em cada arquivo?
- Eleventy é obrigatório para entregar este volume?
- O HTML gerado (ou copiado) ainda precisa de
lang="pt-BR"? Por quê?
Respostas comentadas
- A repetição de cabeçalho, menu e rodapé em várias páginas, e o risco de uma delas ficar velha.
- Jekyll pede Ruby e uma instalação que não ensina HTML. No Windows o aluno segue com HTML copiado e conferido.
- O
aria-current="page"no link daquela página, e otitledoheadse você tiver colado oheadinteiro. - Não. É extra opcional, depois, se você já tiver o ambiente. O caminho do volume é o include manual.
- Sim. Cada documento HTML é uma página. O gerador não tira a obrigação do idioma.
Referências
O arquivo completo
Referência do exemplo 46-gerador-estatico, reproduzida aqui para que você possa conferir sem sair da página.
assets/javascript/simulacao.js
const form=document.querySelector("#simulacao");if(form){form.querySelector("button[type=submit]").disabled=false;form.addEventListener("submit",event=>{event.preventDefault();document.querySelector("#retorno").textContent="Simulação concluída. Nada foi enviado ou guardado.";});}