Comando: cat projects/this-site.md
Este site
Um portfólio que funciona como uma sessão de terminal: cada página responde a um comando, e os comandos seguintes são links, então qualquer pessoa navega clicando. Quem prefere digitar tem um terminal de verdade e uma paleta de comandos, e o conteúdo inteiro se lê sem JavaScript. O próprio site é a evidência: o HTML, os headers e os comandos se conferem no navegador.
- Papel
- Concepção, arquitetura, desenvolvimento e conteúdo
- Período
- set/2026 – hoje
- O que eu fiz
Eu: Conceito, arquitetura, regras de segurança e de privacidade, conteúdo e cada decisão de design, do sistema de arquivos virtual à paleta de cores.
Diagrama
O conteúdo tipado é a única fonte. Dele saem as páginas HTML estáticas, que se leem sem JavaScript, o sistema de arquivos virtual com a saída dos comandos, em JSON, e as ações da paleta de comandos. O terminal roda um shell próprio sobre esses dados e desenha a saída em HTML semântico. O formulário de contato, uma das páginas, envia para a única função no servidor, que manda o e-mail pelo Resend.
Contexto e problema
Meu portfólio anterior só mostrava o conteúdo com JavaScript e não enviava headers de segurança. Para quem quer trabalhar com segurança, o próprio site é a primeira coisa que alguém vai testar.
Este site parte de outra premissa: ele é o meu ambiente de trabalho, uma janela de terminal, e cada página é a saída de um comando. Quem não usa terminal não precisa digitar nada: os comandos seguintes aparecem no fim de cada página e são links.
Arquitetura
- Uma fonte de conteúdo. O conteúdo tipado gera as páginas, o sistema de arquivos virtual, a saída dos comandos e as ações da paleta. Um teste confere que cada arquivo tem página e comando.
- Um shell de verdade por baixo. Comandos com opções no padrão GNU, mensagens de erro com o texto e o código de saída reais do zsh e do coreutils, manual gerado a partir da definição de cada comando e testes de contrato que rodam cada exemplo.
- Chuva de código feita de dados reais. O hash do build, os nomes dos comandos e os caminhos dos arquivos. Fica fora da janela de leitura, tem botão de pausa e começa desligada para quem pede menos movimento.
- Contato sem terceiros no navegador. Formulário que funciona sem JavaScript, com validação e proteção contra spam no servidor.
O que eu faria diferente
Escreveria a guarda de privacidade antes de ler qualquer repositório, e não logo depois. Foi o primeiro controle que eu quis ter e o último que pensei em construir.
Restrições
- Todo o conteúdo acessível sem digitar comandos e sem JavaScript.
- Uma única fonte de conteúdo para as páginas, o sistema de arquivos virtual e os comandos.
- Nenhum nome de cliente, empresa ou repositório privado em arquivo versionado sem autorização.
- WCAG 2.2 AA, com teclado e leitor de tela.
- Deploy só com o CI inteiro verde.
Decisões
Astro estático em vez de um framework de aplicação
- Contexto
- O conteúdo é estático e precisa ser lido sem JavaScript; o terminal, a paleta de comandos e a chuva são camadas por cima dele.
- Escolha
- Astro gerando HTML estático, com uma única função no servidor (o formulário de contato).
- Ganhos
- Nenhum framework no navegador para ler o conteúdo.
- CSP por hash em todas as páginas.
- Custos
- Recursos interativos exigem ilhas separadas e um cuidado extra com a CSP.
Comandos de terminal como dados, não como texto solto
- Contexto
- Queria que a metáfora de terminal fosse de verdade: comandos com opções, erros e códigos de saída reais, e não uma animação de digitação.
- Escolha
- Um núcleo de shell próprio (tokenizador no padrão POSIX, parser de opções no padrão GNU, mensagens do zsh e do coreutils) que gera saídas estruturadas, renderizadas como HTML semântico.
- Ganhos
- Acessível e indexável; cada comando tem manual e teste de contrato.
- Custos
- Mais código para manter do que um terminal de enfeite.
Guarda de privacidade com a lista de bloqueio fora do repositório
- Contexto
- O conteúdo veio da leitura de repositórios privados; nomes reais não podem vazar num commit.
- Escolha
- Hook de pre-commit e job de CI comparam os arquivos versionados com uma lista que fica fora do repositório (local e como secret do CI). O log aponta só o índice do termo, nunca o termo.
- Ganhos
- O repositório pode ser público sem expor os nomes que a guarda protege.
- Custos
- Depende de manter a lista atualizada.
Stack e por quê
- Astro 7 e Preact
- HTML estático por padrão e ilhas pequenas para o que é interativo.
- TypeScript estrito
- Contratos entre conteúdo, sistema de arquivos virtual e comandos.
- Vitest e Playwright
- Testes unitários do núcleo do shell, dos comandos, da sessão, do contato e da chuva; no navegador, cada página com e sem JavaScript, com checagem de acessibilidade.
- Resend
- Envio do formulário de contato validado no servidor.
- Vercel
- Hospedagem estática com uma função; deploy só pelo CI.
Resultados
Todo o conteúdo, inclusive os estudos de caso, o CV e o diário de segurança, se lê e se navega sem JavaScript.
link públicoO próprio site, com o JavaScript desligado(set/2026)Cada cor de texto dos dois temas é conferida contra cada fundo da janela por um teste que lê as cores do próprio código, e todos os pares passam no contraste AA da WCAG.
link públicoComo este site foi feito(set/2026)
Ângulo de segurança
Superfície de ataque
- Formulário de contato (a única função no servidor).
- Arquivos JSON estáticos com os dados dos comandos.
Controles implementados
- CSP por hash, frame-ancestors 'none' e headers de segurança.
- Nenhum HTML montado a partir de string, com regra de lint que reprova innerHTML e similares.
- Validação no servidor, honeypot, token de tempo, rate limit e orçamento diário no contato.
- Segredos só nas variáveis de ambiente do host; varredura de segredos no CI.
O que eu testaria hoje
- XSS por parâmetros de URL e pelo formulário.
- Abuso do formulário para esgotar a cota diária de e-mails.
- Clickjacking e contornos de CSP.
Evidências
- link públicoComo este site foi feito