Projeto 02 · espeledata.com

Regra de escrita
virou teste.

Site bilíngue, sem framework e sem dependência, onde o padrão editorial não é recomendação em documento. É asserção que quebra o build.

32 páginas publicadas, 16 em dois idiomas
28 asserções de CI por build
0 dependências de terceiros
1 arquivo-fonte por página, nos dois idiomas

Como esses números são contados: 32 saídas é o que o validador reporta a cada build, 16 páginas listadas no pipeline vezes dois idiomas. 28 asserções é a contagem de checagens no script de validação, incluindo idioma, SEO por URL, estrutura e regra de escrita. Zero dependência é literal: não existe package.json no repositório, o build roda só com os módulos nativos do Node. Um arquivo por página é o desenho do sistema, PT e EN convivem no mesmo fonte e se separam no deploy.

Narrativa
01
Problema

Eu tinha um portfólio para manter em português e inglês. As duas opções óbvias eram ruins. Manter dois arquivos por página significa que uma correção feita num lado esquece o outro, e a divergência aparece meses depois. Adotar um framework de i18n significa carregar build, dependência e atualização de segurança para um site de dez páginas.

02
Decisão

Um arquivo por página, com os dois idiomas dentro, marcados por classe. No deploy, um script apaga o idioma oposto e escreve duas versões, PT na raiz e EN em /en/, com canonical e hreflang corretos e sitemap bilíngue. Editar é editar um arquivo só, e é impossível corrigir um idioma e esquecer o outro, porque eles estão na mesma linha.

03
Execução

Junto do separador veio um validador que roda depois do build e reprova o deploy. Ele confere um idioma por URL, canonical, hreflang e og:locale por página, um único h1, ativo compartilhado em caminho absoluto, formulário e currículo na língua certa, sitemap bilíngue. E confere também uma regra minha de escrita: travessão é proibido no site inteiro. Se aparecer um, o build falha.

04
Aprendizado

O sistema me pegou. Uma página nova entrou com classe composta, o separador procurava a string exata e não removeu nada, e a versão em português passou a exibir o inglês inteiro. O validador não acusou, porque ele procurava a mesma string exata. Consertei os dois para tratar classe como lista de palavras, que é o que ela sempre foi.

Se o teste e o alvo compartilham o mesmo ponto cego, o teste passa e o erro vai ao ar.

Auditoria de leitura

A queixa era subjetiva: o texto parecia pequeno. Em vez de aumentar no olho, medi o site inteiro e montei a tabela de tamanhos por papel de texto. O diagnóstico ficou objetivo: o corpo de leitura puro estava correto em 16px, mas o texto argumentativo dos cases, que é onde mora o raciocínio, rodava entre 13,6px e 14,1px. Ele estava tipograficamente tratado como legenda, sendo o conteúdo principal da página.

A correção subiu o texto de leitura para cerca de 15,7px e tirou as notas de fonte e rodapé da faixa de 9,6px, onde estavam, para cerca de 11,5px. O rótulo de campo do formulário, que é instrução funcional e não decoração, saiu de 9,28px.

Como foi feito

HTML, CSS e JavaScript escritos à mão, sem framework, com o CSS e o JS embutidos em cada página. O pipeline é um script de separação de idioma, um de build e um validador, todos em Node puro. Versionamento em Git, publicação automática no Netlify a cada push na branch principal.

A construção foi feita em par com um agente de codificação, o Claude Code, e vale dizer isso com clareza porque é parte do método e não um detalhe. A divisão que funcionou é a mesma que eu defendo em CRM: o modelo lê, propõe e escreve; o código calcula e verifica; a decisão de o que vai ao ar é minha. O validador existe justamente para que essa última parte não dependa de confiança, e sim de checagem.

Stack