Meu Glossário

Termos de desenvolvimento, banco de dados, infraestrutura e web — anotados à medida que aparecem.

setembro de 2026

Classe do verbete

Termos sublinhados em pontilhado levam ao próprio verbete. O selo 2 sentidos marca palavra que significa coisas diferentes conforme o contexto — os dois vêm listados, porque o engano costuma ser justamente supor que só há um.

Nenhum verbete encontrado.

1. Versionamento

Como o código guarda memória de si mesmo.

Git ferr.

Sistema de controle de versão. Não guarda “o arquivo atual”: guarda uma sequência de fotos do projeto inteiro (commits), cada uma apontando para a anterior. Disso vêm três capacidades — histórico (“o que essa linha era em agosto?”), reversão e ramificação (branch).

Git é a ferramenta; GitHub é um site que hospeda repositórios Git. Dá para usar Git a vida inteira sem GitHub.

Repo conc.

Abreviação de repositório: a pasta de um projeto sob Git. Contém os arquivos e o histórico — quem mudou o quê, quando, e o diff. “Repo local” existe só na máquina; “com remote” é espelhado num servidor.

Commit conc. 2 sentidos

1 · versionamento

Uma foto do projeto num instante, com mensagem explicando a mudança. É a unidade do histórico: tudo em Git — reverter, comparar, ramificar — opera sobre commits.

2 · banco de dados

Confirmar uma transação: até o COMMIT, as mudanças são provisórias e invisíveis para os outros; depois dele, são definitivas. O oposto é ROLLBACK, que desfaz tudo. É o que garante que duas operações aconteçam ambas ou nenhuma — daí Delta Lake existir para dar isso a arquivos soltos.

Os dois sentidos partilham a ideia de “tornar definitivo o que estava em rascunho”, e nasceram independentes.

Branch conc. 2 sentidos

1 · versionamento

Uma linha paralela de commits. Serve para trabalhar numa versão alternativa sem afetar a principal (main). Juntar de volta é o merge.

2 · banco de dados

Uma cópia temporária do banco — esquema e dados — para testar uma mudança sem tocar em produção, com merge depois. O Supabase tem isso. A metáfora é a mesma do Git, mas o que se ramifica é o banco, não o código.

Merge conc.

Juntar uma branch na outra. Quando as duas mexeram nas mesmas linhas, dá conflito: o Git para e pede que um humano decida qual versão fica.

Remote conc.

Uma cópia do repo em outro lugar — tipicamente no GitHub. push manda os commits locais para lá; pull traz os de lá para cá.

Diff conc.

A diferença entre duas versões de um arquivo, linha a linha: - o que saiu, + o que entrou.

- const limite = 100;
+ const limite = 250;

É a razão prática de ter repo mesmo sem GitHub: sem diff, “o que eu mudei ontem?” não tem resposta.

GitHub serv.

Site que hospeda repositórios Git e acrescenta trabalho em equipe: pull requests (propor e revisar mudanças antes do merge), issues, automação e GitHub Pages. Concorrentes: GitLab, Bitbucket, Codeberg.

.gitignore arq.

Lista de padrões dizendo ao Git o que não versionar.

node_modules/
dist/
.env
!.env.example

Fica de fora o que é regenerável (node_modules/, dist/), o que é segredo (.env) e o que é lixo do sistema (Thumbs.db).

Três armadilhas: (1) ignorar não apaga o que já foi commitado — chave que entrou no histórico se rotaciona, não se esconde; (2) ! nega um padrão, mas um .gitignore mais profundo vence a negação da raiz; (3) vale conferir nas duas direções — o que não pode entrar, e o que precisa entrar e não está.

2. Terminal e linha de comando

Falar com a máquina digitando — o que é scriptável e repetível.

CLI conc.

Command Line Interface: programa que se opera digitando comandos. git, npm, curl. A vantagem sobre a GUI é ser automatizável — o que você faz uma vez, você repete mil.

GUI conc.

Graphical User Interface: a versão com janelas e botões. O painel de um serviço é GUI; o comando equivalente é CLI. Quase toda ferramenta séria tem as duas, e a CLI costuma receber as novidades primeiro.

IDE ferr.

Integrated Development Environment: um editor de texto mais as ferramentas em volta, sabendo umas das outras. Um editor comum abre e salva arquivo; um IDE sabe o que o arquivo significa — completa nomes, pula para onde a função foi definida, acusa erro enquanto você digita, renomeia os 40 usos de uma função (e só os usos, não as ocorrências do mesmo texto), depura parando numa linha, e traz terminal e Git embutidos.

A fronteira com “editor” deixou de existir, e o que a dissolveu tem nome: LSP (Language Server Protocol, Microsoft, 2016). A inteligência saiu de dentro do editor e virou um programa separado — o language server. O editor pergunta “o que completa aqui?”, “onde isso foi definido?”, e o servidor responde.

editor ──LSP──> language server   (tsserver, pyright, rust-analyzer…)

Escreve-se o suporte a uma linguagem uma vez, e todo editor ganha — por isso VS Code, Neovim e Zed entendem TypeScript igualmente bem: é o mesmo tsserver por trás dos três. É a mesma forma do PostgREST e do harness: separar quem decide de quem apresenta, com um protocolo entre os dois.

A armadilha: “no meu editor não dá erro” não prova nada. O IDE roda a sua cópia das ferramentas — o VS Code usa o TypeScript embutido nele, não o do seu package.json, a menos que você mande usar o do workspace; o ESLint dele pode ler outra configuração; e ele tem plugins que o servidor não tem. A verdade é o que o comando diz: npm run build, tsc --noEmit. O editor é conveniência; o terminal é o árbitro.

Shell ferr.

O programa que lê o que você digita no terminal e executa. O terminal é a janela; o shell é quem interpreta lá dentro. Bash, zsh e PowerShell são shells diferentes, com sintaxes diferentes.

O que o torna mais que um lançador de programas é o pipe — por isso os comandos são pequenos e combináveis.

Bash ling.

O shell padrão de Linux e Mac, e também uma linguagem de script (arquivos .sh). No Windows o equivalente nativo é o PowerShell, que faz o mesmo com outra sintaxe. Importa porque quase toda documentação e toda automação assumem Bash.

Pipe conc.

O operador |: a saída de um comando vira a entrada do próximo.

cat vendas.csv | grep "2026-09" | wc -l

“Leia o arquivo → fique só com as linhas de setembro → conte quantas são.” É a ideia central do shell: ferramentas pequenas, encadeadas.

Heredoc conc.

Here-document: sintaxe do shell para entregar um texto de várias linhas à entrada de um comando, sem criar arquivo temporário. O nome diz que o documento está aqui, no próprio script.

git commit -F - <<'MSG'
Acrescenta RPC

Entra pelo contraste com REST.
MSG

As aspas no delimitador decidem tudo: <<'EOF' é literal — $HOME continua $HOME e nada executa; <<EOF expande variáveis e executa o que estiver entre crases. Aspas em 90% dos casos: mensagem de commit, bloco de SQL, script de outra linguagem.

Variantes: <<-EOF remove tabulações do início das linhas, para indentar o bloco dentro de um if — só tab, não espaço; e a here-string <<<, de uma linha só.

A armadilha: o delimitador de fechamento precisa estar sozinho, no começo da linha — um espaço antes e o shell nunca acha o fim. O erro não menciona isso: diz unexpected EOF while looking for matching quote, apontando para um lugar sem relação com o problema, porque o shell seguiu lendo e tropeçou na primeira aspa que encontrou. No PowerShell o equivalente é @'…'@, e lá o fechamento precisa estar na coluna zero.

ls cmd.

Lista os arquivos da pasta. Em PowerShell, Get-ChildItem — que também atende por ls.

cat cmd.

Despeja o conteúdo de um arquivo na tela. O nome vem de concatenate, porque também junta vários. Em PowerShell, Get-Content.

grep cmd.

Filtra linhas que casam com um padrão. É o comando que responde “onde no código isso é usado?” em um segundo:

grep -rn "STRIPE_SECRET_KEY" src/

O nome vem de g/re/p, um comando do editor ed — globally search a regular expression and print. Aceita regex. Em PowerShell, Select-String.

Regex ling.

Expressão regular: um mini-idioma para descrever padrões de texto. ^\d{3}\.\d{3} descreve “começa com três dígitos, ponto, três dígitos”. Aparece em grep, em todo editor e em praticamente toda linguagem. Um dos investimentos de melhor retorno por hora estudada.

curl cmd.

Faz uma requisição HTTP e imprime a resposta. É o navegador sem navegador — e, por isso, a forma mais honesta de medir a web: mostra o que chegou antes de qualquer JavaScript rodar.

  • -s silencia a barra de progresso
  • -L segue redirecionamentos
  • -I mostra só os cabeçalhos
  • -H envia um cabeçalho
  • -A finge ser outro cliente (User-Agent)

SSH prot.

Secure Shell: o protocolo para abrir um shell numa máquina remota, com o tráfego criptografado. É como se administra um VPS.

ssh usuario@203.0.113.10

A partir daí, ls, cat e tudo mais rodam lá, e você vê a saída aqui. Serve também para copiar arquivos (scp, rsync) e para túneis.

Autenticação por chave, não por senha. Você gera um par: a privada fica na sua máquina e nunca sai; a pública vai para o servidor. Quem tiver a privada entra — por isso ela é protegida por passphrase, e por isso senha via SSH costuma ser desabilitada. É a mesma lógica do mTLS: provar identidade com chave, não com segredo compartilhado.

O Git usa SSH como uma das formas de falar com o remote — daí URLs no formato git@github.com:usuario/repo.git, alternativa ao HTTPS.

SSH e SSL/TLS são coisas diferentes, apesar das siglas parecidas: ambos criptografam, mas SSH é acesso remoto a máquina e tem seu próprio sistema de confiança — sem autoridade certificadora. Daí o aviso de “host key” na primeira conexão: você é quem confirma.

Cron ferr.

Agendador de tarefas, e por extensão a sintaxe dele: cinco campos — minuto, hora, dia, mês, dia da semana. 0 3 * * * é “todo dia às 3h”.

Ponto importante: um cron que dispara uma função serverless não contradiz o modelo dela. O relógio está fora; para a função, é uma requisição como outra qualquer. Veja stateless.

3. Linguagens, módulos e pacotes

Em que se escreve, e como um arquivo usa o outro.

JavaScript ling.

A única linguagem que o navegador executa nativamente — acidente histórico, não escolha de engenharia, mas um fato duro: comportamento que precisa acontecer na máquina do usuário acaba em JS. Com o Node.js ela também roda no servidor, onde não tem vantagem nenhuma sobre Python, Go ou C# além da conveniência de ser a mesma dos dois lados.

.tsx arq.

TypeScript com JSX permitido dentro. Regra prática: arquivo que desenha tela é .tsx; arquivo de lógica pura é .ts.

.mjs arq.

JavaScript marcado explicitamente como módulo ESM. Existe porque o Node convive com dois sistemas de módulo, e a extensão vence a configuração do projeto. Por isso um vite.config.mjs funciona em qualquer lugar. O oposto é .cjs, sempre CommonJS.

ESM pad.

ECMAScript Modules: o padrão oficial da linguagem para um arquivo usar outro, e o único que o navegador entende nativamente.

import fs from 'fs';
export { minhaFuncao };

A diferença que importa em relação ao CommonJS não é a escrita, é quando: import é estático — as dependências são declaradas no topo e podem ser conhecidas antes de rodar. É isso que torna o tree-shaking possível.

CommonJS pad.

O sistema de módulos antigo do Node (2009): require() e module.exports. Como require é uma chamada de função comum, pode estar dentro de um if e ter o caminho montado em tempo de execução — flexível, e por isso não analisável estaticamente.

Hoje escreva ESM. CommonJS aparece em código legado e em erros como “require is not defined in ES module scope”, que é sempre essa fronteira sendo cruzada.

Node.js ferr.

O motor que roda JavaScript fora do navegador. É o que permite JS no servidor, e é o que executa npm, o build do Vite e o Next.js. Quando um projeto pede “Node 20”, é a versão desse motor.

Não confundir com nó (node) no sentido de elemento de uma árvore ou grafo — “um nó do DOM”, “um nó do cluster”. Mesma palavra em inglês, assunto diferente.

npm ferr.

Node Package Manager. Faz duas coisas: instala dependências (npm install react baixa e anota no package.json) e roda scripts (npm run dev, npm run build).

O package-lock.json fixa as versões exatas que funcionaram, e entra no repo. Alternativas com o mesmo papel: pnpm, yarn, bun.

node_modules/ arq.

A pasta onde o npm despeja o código baixado das dependências. Enorme e inteiramente regenerável a partir do package.json — por isso vai no .gitignore e nunca entra no repo.

PHP ling.

Linguagem de servidor, de 1995. Roda no servidor e gera o HTML que vai ao navegador. Importa por um motivo: WordPress é PHP, e por isso exige hospedagem tradicional com banco e disco.

O modelo clássico é o oposto do stack moderno — cada requisição executa o arquivo do zero e devolve a página pronta, sem build e sem front separado. Carrega má fama das versões antigas; o PHP 8 é rápido, e o Laravel é um framework bem resolvido.

SQL ling.

A linguagem dos bancos relacionais: você descreve qual resultado quer, e o banco decide como obtê-lo (é declarativa). Todo Postgres — tabelas, políticas de acesso, funções, gatilhos — é SQL.

WebAssembly pad.

Formato binário que permite rodar no navegador código compilado de Rust, C++ ou Go, com desempenho perto do nativo. Usado no que é pesado: edição de vídeo, jogos, planilhas, Figma.

Não substitui o JavaScript: não toca o DOM diretamente, e precisa de JS para isso. É um motor, não uma alternativa.

4. A página no navegador

As três camadas — e o erro de tratá-las como alternativas.

HTML ling.

A camada de estrutura e conteúdo: “isto é um título, isto é um parágrafo, isto é um campo de e-mail”. É o que existe.

Não é alternativa ao CSS nem ao JavaScript — são três camadas da mesma página. Sem HTML não há página; uma página só com HTML funciona, feia.

CSS ling.

A camada de aparência: cor, tamanho, posição, espaçamento, o que muda no celular, o tema escuro. É como aquilo se parece.

Muita coisa que se fazia com JS hoje é CSS — menu, animação, layout responsivo. Sendo declarativo e executado pelo motor do navegador, é mais rápido e quebra menos que o equivalente em script.

Padding (e box model) conc. 2 sentidos

1 · layout (CSS)

Em CSS, todo elemento é uma caixa com quatro anéis: conteúdo, padding, borda e margin.

  • padding — espaço por dentro da borda. É o que dá respiro a um botão.
  • margin — espaço por fora. Afasta o elemento dos vizinhos.

Quase todo layout torto é um destes trocado pelo outro. No Tailwind: p-6 é padding, m-6 é margin.

2 · criptografia

Completar uma mensagem com bytes extras até o tamanho de bloco exigido pelo algoritmo. Sentido não relacionado ao primeiro — mas é o que aparece em mensagens como padding error ao manipular certificados, e que faria procurar no lugar errado.

DOM conc.

Document Object Model: a representação do HTML em memória, como árvore de objetos que o JavaScript lê e modifica. O arquivo HTML é texto; ao carregá-lo, o navegador o parseia e constrói o DOM.

O DOM é a página. Mudou o DOM, a tela muda na hora — o arquivo original não é consultado de novo. Daí “ver código-fonte” mostrar uma coisa e o inspetor mostrar outra.

Três consequências: é por aí que o React trabalha; é por isso que CSR atrapalha o SEO; e é por isso que dá window is not defined no servidor, onde não há navegador nem DOM.

JSX ling.

Sintaxe que deixa escrever um pedaço de tela parecido com HTML dentro do JavaScript:

function Saudacao({ nome }) {
  return <h1>Olá, {nome}</h1>;
}

O navegador não entende: o build converte para chamadas de função comuns. É açúcar sintático, e as chaves {} são a fronteira — dentro delas é JavaScript de verdade. Daí a extensão .tsx.

React fram.

Biblioteca de interface. Em vez de mandar o navegador “mude este texto, esconda aquele botão”, você descreve como a tela deve ser dado o estado atual:

tela = f(estado)

Mudou o estado, o React recalcula e aplica só a diferença no DOM — comparando com uma cópia leve da árvore, o virtual DOM. Você para de manipular a tela e passa a manipular dados. A unidade é o componente: uma função que devolve um pedaço de tela, com estado próprio. Ver hook e declarativo.

SPA conc.

Single-Page Application. Depois da primeira carga, navegar entre telas não recarrega a página — o JavaScript troca o conteúdo na hora. Navegação instantânea, ao custo de precisar reconstruir à mão o que o navegador dava de graça: rotas, botão de voltar, recarregar sem perder o lugar, e SEO.

Imperativo × declarativo conc.

“Pegue o rótulo e mude o texto” é imperativo — você dá os passos. “O rótulo mostra o nome do usuário” é declarativo — você descreve o resultado e o sistema descobre os passos.

A indústria inteira foi do primeiro para o segundo: React, SwiftUI e Jetpack Compose são o mesmo movimento em três plataformas, e CSS e SQL já eram declarativos. É a distinção conceitual que mais se reaproveita.

5. Build e ferramentas de projeto

Do código que você escreve ao pacote que de fato roda.

Build conc.

A etapa que transforma o código que você escreve no pacote que roda. Existe porque os dois são diferentes: você escreve para ser legível; o navegador quer algo pequeno e em JavaScript puro. Em ordem:

Um projeto sem build é aquele em que o arquivo que você escreve já é o arquivo que roda. Não confundir com deploy, que é publicar o resultado.

A palavra serve de verbo e de substantivo: “rodar o build” é a etapa; “o build de ontem quebrou” é o resultado daquela execução — o conteúdo do dist/. O contexto separa.

Transpilar conc.

Traduzir entre duas linguagens de alto nível — TypeScript para JavaScript, sintaxe nova para sintaxe compatível. Diferente de compilar, que traduz para linguagem de máquina (C, Rust, Go). O build da web transpila; não compila nesse sentido.

Bundle conc.

Juntar milhares de arquivos-fonte em poucos arquivos de saída, porque cada arquivo seria uma ida à rede. O resultado é o que o usuário baixa — daí “o bundle está grande” ser uma queixa de desempenho.

Tree-shaking conc.

“Sacudir a árvore”: descartar do bundle o código importado e não usado. Só é possível porque ESM é estático — a ferramenta sabe, lendo o arquivo, o que é de fato usado.

Minificar conc.

Apagar espaços e comentários e encurtar nomes internos, deixando o comportamento igual. Reduz o que trafega; torna o resultado ilegível para humanos, o que é irrelevante porque ninguém lê o dist/.

dist/ arq.

De distribution: a pasta onde o build cospe o resultado pronto. Alguns projetos chamam de build/; o Next usa .next/. Três regras: ninguém edita (é gerada), não entra no repo, e é o que vai para a hospedagem.

Framework × biblioteca conc.

A diferença é a direção do controle, e ela decide quanto do desenho do seu projeto já vem decidido.

  • Biblioteca — você chama ela, quando quiser. Uma função de formatar data, um cliente de HTTP. Você manda; ela responde.
  • Framework — ela chama você. Você preenche os lugares que ela reservou, e ela decide quando executá-los. É a inversão de controle: Next.js decide quando sua página roda, e você não o chama.

Daí a troca: framework dá muito pronto e cobra que você aceite o formato dele; biblioteca dá pouco e não impõe nada. E daí a dificuldade de trocar de framework depois — a forma do projeto é a do framework.

O React se chama biblioteca e na prática funciona como framework: ele decide quando seu componente é chamado. A fronteira é menos nítida do que os rótulos sugerem — o que importa é a pergunta “quem chama quem?”. Ver harness e runtime.

Runtime conc.

Duas coisas, e as duas aparecem toda hora.

O programa que executa: Node, Deno, Bun, o motor do navegador, a máquina virtual do Java. Só executa — não chama seu código de volta como um framework, nem o observa como um harness. Quando uma plataforma diz “runtime: nodejs20”, é disto que fala.

O momento: em tempo de execução, por oposição a em tempo de compilação ou de build. “Erro de runtime” é o que só aparece rodando — e é exatamente o que a análise estática não pega. Os tipos do TypeScript somem antes do runtime; por isso dado vindo de uma API pode desmentir o tipo declarado sem ninguém avisar.

Fixture conc.

O estado de partida que um harness monta antes de rodar um teste: as linhas no banco, o arquivo em disco, a sessão autenticada, o relógio congelado numa data. O nome vem do laboratório — o suporte que segura a peça na posição certa para a medição.

A regra que evita a maior parte da dor: cada teste recebe a sua, e desfaz ao sair. Fixture compartilhada faz testes passarem na ordem certa e falharem na ordem trocada — um defeito que some quando você vai investigar.

No Brasil quase ninguém traduz; se traduzir, é “massa de teste”. Não confundir com mock, que substitui uma dependência por uma falsa: a fixture é o dado, o mock é o vizinho.

Vite ferr.

Duas ferramentas num pacote. Em desenvolvimento sobe um servidor local com HMR; em produção faz o build e produz o dist/. Um app Vite + React é servido como arquivos estáticos e renderizado no navegador (CSR).

HMR conc.

Hot Module Replacement: você salva o arquivo e a tela atualiza só aquele pedaço, sem recarregar e sem perder o estado da aplicação. É o que torna o desenvolvimento em Vite ou Next tolerável.

Cache busting prát.

Pôr um hash no nome do arquivo gerado (index-a3f9c1.js) para que conteúdo novo produza nome novo. Assim o navegador pode guardar o arquivo para sempre sem risco. Sem isso, você publica a correção e o usuário continua vendo a versão velha — um clássico de deploy.

Tailwind CSS fram.

Framework de CSS utilitário: em vez de escrever regras num arquivo à parte, você compõe a aparência com classes pequenas e de propósito único, direto no elemento.

<div class="flex items-center gap-4 rounded-lg p-6 dark:bg-slate-800">

Ganha: não inventa nomes (metade do trabalho de CSS), vê a aparência sem trocar de arquivo, valores vindos de uma escala fixa, e o CSS final é minúsculo porque o build gera só o que foi usado. Perde: o HTML fica verborrágico, e mudança global depende de disciplina ou de script.

Lint / ESLint ferr.

Programa que lê o código sem executá-lo e aponta problemas — o nome vem de lint, a fiapagem da roupa. Pega erro provável (variável não usada, await esquecido, hook dentro de um if), estilo, e regras próprias do projeto. Em JS/TS o padrão é o ESLint.

Formatter / Prettier ferr.

Não opina sobre correção: só reescreve o layout do código segundo uma regra fixa. Acaba com discussão de estilo, e ninguém indenta à mão. Vizinho do lint, com papel diferente.

Type checker ferr.

Verifica se os tipos batem (tsc, do TypeScript). É mais fundo que lint, e é a razão principal de usar TypeScript. Junto com lint e formatter, forma a análise estática — encontrar problema antes de rodar. O teste é o complemento que só pega o que aparece rodando.

6. Renderização e rotas

Onde e quando o HTML nasce — o eixo que decide desempenho e SEO.

Renderização conc.

Transformar dados e código em HTML pronto para exibir. Isso sempre acontece; a pergunta é onde e quando — SSG, SSR ou CSR.

“Estático” descreve o primeiro caso (o HTML já existia antes de alguém pedir). O oposto de estático é dinâmico, não “renderizado”. E um mesmo projeto Next.js mistura os três, página a página.

A regra por trás: renderizar cedo é mais rápido e barato; renderizar tarde é mais fresco e personalizado. Empurre para o build tudo que for igual para todo mundo.

CSR conc. 2 sentidos

1 · renderização

Client-Side Rendering. O servidor manda um HTML praticamente vazio (<div id="root"></div>) mais um bundle; o navegador executa, busca os dados e desenha. É o modelo do Vite + React, e produz uma SPA.

Note que os arquivos continuam estáticos — o que é dinâmico é o conteúdo. Custo: primeira tela em branco, SEO prejudicado e cards de compartilhamento vazios.

2 · certificados

Certificate Signing Request. O arquivo que você gera para pedir um certificado a uma autoridade: contém a chave pública e a identidade, assinado pela chave privada — que não vai junto e não sai do seu lado. Ver TLS e OpenSSL.

Colisão infeliz, e os dois sentidos convivem no mesmo projeto: um artigo sobre “CSR” pode estar falando de front-end ou de infraestrutura. O contexto separa — renderização ou certificado.

SSR conc.

Server-Side Rendering. O servidor executa o React, busca os dados e manda o HTML já pronto. O navegador exibe imediatamente e depois hidrata — anexa o JavaScript ao HTML existente para torná-lo interativo.

Ganha primeira tela e SEO; paga com servidor rodando e com o código vivendo em dois ambientes (daí window is not defined).

SSG conc.

Static Site Generation. O HTML é gerado uma vez, no build, e servido como arquivo. Você escreve em Markdown ou lê de um banco, e saem 200 páginas prontas.

É o melhor dos mundos quando o conteúdo é igual para todos e muda pouco: rápido, barato, indexável. Ferramentas: Astro, Next, Hugo, Jekyll.

Astro fram.

Framework voltado a sites de conteúdo: gera HTML estático por padrão e só manda JavaScript onde há interatividade. Para blog, documentação ou catálogo de receitas indexável, costuma ser a escolha mais direta.

Rota conc.

O mapeamento de uma URL para uma tela. Ter rota “de verdade” significa que /receitas/482 existe sozinha: abre colada na barra, recarrega sem perder o lugar, e o botão de voltar funciona.

Numa SPA isso é construído à mão e costuma ficar incompleto; em Next vem de graça. E sem rota não há o que indexar — SEO nem começa.

7. Hospedagem e execução

Onde o código roda — e a distinção que decide tudo: existe entre as requisições, ou não?

Deploy conc.

Publicar o resultado do build. São etapas separadas — build produz, deploy leva — ainda que plataformas como a Vercel façam as duas em sequência.

Vercel serv.

Hospedagem que acrescenta cinco coisas a “um servidor com arquivos”: build automático a cada push, CDN, HTTPS e domínio, deploy atômico com rollback, e funções serverless para o que precisa de servidor.

Alternativas: Netlify, Cloudflare Pages, Render; GitHub Pages para o que é só estático; S3 + CloudFront montado à mão; VPS para controle total.

CDN conc.

Content Delivery Network: uma rede de servidores espalhados pelo mundo que guardam cópias dos seus arquivos e entregam a partir do ponto mais próximo de quem pediu. Resolve um problema físico — ver latência —, e nenhuma otimização de código compete com isso.

Cada ponto da rede é um PoP (point of presence), também chamado de edge — a mesma borda das edge functions. Cada PoP é um cache:

visitante → PoP mais próximo ─┬─ tem cópia? entrega          (cache HIT)
                              └─ não tem? busca na origem,
                                 guarda e entrega            (cache MISS)

A origem é onde o arquivo de verdade mora. O primeiro visitante de cada região paga a viagem longa; os seguintes, não — por isso conteúdo estático é tão barato de servir: a origem é consultada uma vez por região, não uma vez por visitante.

O que cacheia bem: HTML estático, JS, CSS, imagens, vídeo, fontes — ou seja, todo o dist/ de um app Vite e todo site SSG. Mal ou nada: resposta personalizada por usuário, qualquer coisa atrás de login, consulta de API que depende de quem pergunta. Um banco como o Supabase não fica atrás de CDN nesse sentido: a CDN acelera a casca do app, não os dados.

Costuma vir junto, e é metade do valor: TLS terminado na borda (o handshake acontece perto), compressão automática, proteção contra DDoS — o ataque bate na rede e não na sua origem — e o IP da origem escondido.

Quem faz: Cloudflare, Fastly, Akamai, CloudFront. Vercel, Netlify e GitHub Pages já vêm com uma embutida.

A parte difícil é a invalidação. Cache rápido é fácil; cache correto é o problema. Cada resposta carrega um TTL (time to live) no cabeçalho Cache-Control dizendo por quanto tempo pode ser reaproveitada — alto é rápido e arriscado, baixo é fresco e caro —, e existe o purge, que manda esquecer um arquivo agora. A saída elegante é a que o build já dá: conteúdo imutável com nome único. index-a3f9c1.js pode ter TTL de um ano, porque conteúdo novo gera nome novo; só o HTML, que aponta para esses nomes, fica com TTL curto. Ver cache busting.

São três caches independentes, e confundi-los custa tempo de diagnóstico: o do navegador (no disco do usuário; limpa com recarga forçada ou nome de arquivo novo), o da CDN (nos PoPs; limpa por TTL ou purge) e a origem (limpa no deploy). Quando o navegador mostra uma versão e o curl mostra outra, no mesmo instante, é quase sempre o primeiro — curl não tem cache, é processo novo a cada execução.

TTFB conc.

Time To First Byte: o tempo entre o navegador começar a pedir uma página e o primeiro byte da resposta chegar. É uma soma de etapas:

DNS → handshake TCP → handshake TLS → pedido viaja →
                          servidor processa → 1º byte volta
└───────────────────────── TTFB ──────────────────────────┘

Fica de fora: baixar o resto, parsear o HTML, buscar CSS e JS, desenhar. TTFB é só a largada.

Duas metades, e diagnosticar é saber qual delas: rede (DNS, os dois handshakes, a viagem — é latência pura, resolvida com CDN) e servidor (consulta ao banco, renderização, cold start — resolvida com código e cache). Otimizar a metade errada não move o número.

O curl decompõe, e cada valor é acumulado desde o início:

curl -o /dev/null -s -w "dns:  %{time_namelookup}\ntcp:  %{time_connect}\ntls:  %{time_appconnect}\nttfb: %{time_starttransfer}\ntotal:%{time_total}\n" https://seusite.com.br/

Se tls já é 0,4 s, o problema é distância. Se tls é 0,05 s e ttfb é 0,9 s, o servidor passou 850 ms pensando. Referências grosseiras: abaixo de 200 ms é bom, acima de 800 ms incomoda.

A armadilha: TTFB engana numa SPA. Um app CSR tem TTFB excelente — o servidor devolve na hora um HTML praticamente vazio —, mas o usuário não vê nada: falta baixar o bundle, executá-lo, buscar os dados e desenhar. Primeiro byte em 80 ms, primeira palavra legível em 2,5 s. Já um app SSR tem TTFB pior — consultou o banco antes de responder — e mostra conteúdo antes. Entre CSR e SSR, o TTFB anda na direção oposta da experiência, e comparar os dois por ele leva à conclusão errada.

Daí as métricas de referência serem outras: FCP (primeiro pixel de conteúdo), LCP (o elemento principal ficar visível), INP (resposta à primeira interação) e CLS (o quanto a página pula enquanto carrega). LCP, INP e CLS são os Core Web Vitals, sinal de ranqueamento do Google; TTFB não é um deles — é diagnóstico, serve para explicar um LCP ruim, não para substituí-lo.

TTFB é o piso: nada aparece antes dele, então 1,5 s condena o LCP — mas um TTFB ótimo não garante nada. No seu stack: SSG + CDN dá o melhor possível (arquivo pronto, servido do PoP mais próximo); SSR inclui a consulta ao banco, e é o caminho mais curto entre índice faltando e página lenta; serverless soma o cold start inteiro, e é por isso que a primeira visita depois de um período parado parece quebrada e a segunda parece rápida.

Core Web Vitals pad.

O conjunto de três métricas que o Google elegeu como medida de experiência e usa como sinal de ranqueamento: LCP, INP e CLS. Cada uma cobre uma pergunta diferente:

  • LCP — carregou? (o conteúdo principal ficou visível)
  • INP — responde? (a interação teve retorno rápido)
  • CLS — fica quieto? (a página não pula durante o carregamento)

TTFB e FCP não são Core Web Vitals — são diagnóstico, servem para explicar um LCP ruim. É uma distinção que economiza trabalho: otimizar TTFB num app que já tem TTFB bom não move o ranqueamento.

Duas medições, e elas discordam. Lab é o teste sintético (Lighthouse, PageSpeed) — reprodutível, e não é o que o Google usa. Field é o CrUX, coletado de usuários reais no Chrome, e considera o percentil 75: passar significa que 75% das visitas passaram, com aparelho fraco e rede ruim incluídos. Site que vai bem no Lighthouse e mal no relatório do Search Console está batendo nessa diferença.

O peso no ranqueamento é real, mas modesto: serve de desempate entre páginas de relevância parecida, não substitui conteúdo. Ver SEO.

FCP conc.

First Contentful Paint: quando o primeiro conteúdo aparece — qualquer texto, imagem ou desenho, ainda que não seja o que a pessoa veio ver. É o instante em que a tela deixa de estar em branco.

Vem depois do TTFB e antes do LCP. Bom até ~1,8 s. Não é Core Web Vital: um FCP ótimo com LCP péssimo é comum — a barra de navegação apareceu depressa e o conteúdo demorou.

LCP conc.

Largest Contentful Paint: quando o maior elemento de conteúdo visível termina de ser desenhado — normalmente a imagem de destaque ou o bloco de texto principal. É a melhor aproximação automática de “a página carregou” do ponto de vista de quem olha.

Bom até 2,5 s; acima de 4 s é ruim. É o Core Web Vital mais importante e o mais fácil de piorar sem perceber.

As causas mais comuns, em ordem: TTFB alto (é o piso — nada aparece antes), imagem grande sem otimizar, fonte que bloqueia o texto, e CSR — porque o conteúdo só existe depois de baixar e executar o bundle e buscar os dados.

INP conc.

Interaction to Next Paint: quanto tempo a página leva para mostrar resposta visual a um clique, toque ou tecla. Mede a interação mais lenta da visita, não a média — o que torna a métrica honesta.

Bom até 200 ms; acima de 500 ms é ruim. Substituiu o FID em 2024, que media só o atraso da primeira interação e por isso quase sempre passava.

A causa quase sempre é JavaScript ocupando a thread principal: um recálculo pesado, uma lista enorme redesenhando, ou o próprio custo de hidratação num app SSR — a página parece pronta e ainda não responde.

CLS conc.

Cumulative Layout Shift: o quanto a página pula enquanto carrega. É a métrica da irritação de clicar num botão e ele se mover no instante do clique. Não é tempo: é uma pontuação, boa até 0,1 e ruim acima de 0,25.

As causas são poucas e todas evitáveis: imagem sem width e height declarados (o navegador não reserva o espaço), banner ou aviso inserido no topo depois, fonte que troca e muda a altura do texto, e conteúdo que chega por API e empurra o que já estava na tela.

É o mais barato de consertar dos três, e o único que depende quase só de CSS disciplinado — reservar espaço antes de saber o que vai ocupá-lo.

Latência conc.

O tempo que um pedido leva para ir e voltar, independentemente de quanto dado trafega. Não confundir com banda, que é quanto cabe por segundo: banda larga com latência alta continua parecendo lenta, porque a espera acontece antes de o primeiro byte chegar.

É um limite físico, não um problema de congestionamento. Um sinal não passa da velocidade da luz, e na fibra vai a uns dois terços disso. São Paulo → Virgínia são cerca de 7.500 km: ~40 ms de ida no melhor caso teórico, ~80 ms de ida e volta, e 120 a 200 ms na prática, com os roteadores do caminho.

O que piora é que raramente é uma ida e volta. Abrir uma página pede o handshake TCP, depois o handshake TLS, depois o HTML, depois o CSS e o JS que o HTML referencia. Cinco idas e voltas a 150 ms são 750 ms antes de aparecer qualquer coisa — e nada disso é culpa do seu código.

Daí três coisas deste glossário existirem: a CDN (encurta a distância), as edge functions (encurtam a distância do código) e o bundle (reduz o número de idas). E daí a regra de ouro de desempenho na web: reduzir o número de viagens rende mais que reduzir o tamanho de cada uma.

GitHub Pages serv.

Hospedagem gratuita de arquivos estáticos direto de um repo do GitHub. Sem build sofisticado e sem funções — e exatamente suficiente para uma página como esta.

VPS serv.

Virtual Private Server: uma máquina Linux virtual que é sua, com IP e root. De uns US$5/mês (DigitalOcean, Hetzner, Linode).

A conta real não é o aluguel, é a manutenção. Um VPS envelhece: pacote desatualizado, disco que enche, certificado que expira, SSH mal configurado. É trabalho recorrente para sempre, e raramente vale para um produto só.

Serverless conc.

Modelo em que chega uma requisição, a plataforma acorda uma instância do seu código, ela responde e morre. Entre requisições, nada seu está rodando — por isso é barato: paga-se por milissegundo, não por máquina ligada.

As restrições: nada sobrevive entre chamadas, teto de tempo por requisição, cold start, disco efêmero, e nenhum acesso à camada de socket (o que inviabiliza mTLS e WebSocket).

Cuidado com um mal-entendido comum: trabalho agendado funciona em serverless — o cron está fora e chama a função. O que não funciona é guardar estado entre invocações. Ver stateless.

Edge function conc.

Uma função serverless que roda na borda da rede — no ponto da CDN mais próximo de quem chamou — em vez de numa única região. Ganha latência: a função executa a 30 ms do usuário, não a 200 ms.

Borda (edge) é o termo geral para “o mais perto possível de quem acessa”. A mesma ideia que faz a CDN servir arquivos rápido, aplicada a código.

O preço é um ambiente mais restrito que o de um servidor comum: tempo de execução curto, menos memória, e um subconjunto das bibliotecas — várias que dependem de recursos de sistema não funcionam. E, sendo serverless, herda tudo daquele modelo: nada persiste entre chamadas, cold start, e nenhum acesso à camada de socket.

Onde aparece: Edge Functions do Supabase (Deno), Edge Functions da Vercel, Cloudflare Workers. São bons para autenticação, redirecionamento, personalização leve e webhook — e ruins para trabalho longo ou que precise de processo.

Medir antes de supor: é comum ouvir que esse ambiente “não fala com a internet”. Vale testar com mais de um destino antes de aceitar — um destino que falha não prova “qualquer destino”. Ver medir antes de afirmar.

Cold start conc.

O atraso da primeira chamada a uma função serverless depois de um período parado: a plataforma precisa carregar o ambiente antes de executar. As seguintes são rápidas, enquanto a instância seguir viva.

Stateless × stateful conc.

Stateless: cada execução carrega tudo o que precisa e não lembra da anterior. É o modelo do HTTP, do REST e do serverless — todo estado mora fora (banco, fila, storage) e é recarregado.

Stateful: algo persiste em memória entre um momento e o próximo — uma sessão autenticada, uma conexão aberta, uma fila sendo consumida. Isso exige processo de longa duração.

A pergunta que decide a arquitetura: seu código precisa existir também quando ninguém está pedindo nada?

Processo de longa duração conc.

Programa que sobe e fica ligado, decidindo o que fazer: mantém memória, conexões abertas e disco que persiste. Paga-se pela máquina, ocupada ou não.

Necessário quando há estado em memória entre execuções, conexão persistente (WebSocket, mTLS), ou trabalho longo que precisa de ritmo. Hospeda-se em Fly.io, Render, Railway ou VPS.

Worker conc. 3 sentidos

1 · servidor (modo worker)

Um processo que não escuta porta nenhuma e não tem URL: fica ligado consumindo uma fila. Distingue-se do web service, que recebe HTTP e responde.

usuário → web service → põe na fila → responde "recebi" na hora
                            ↓
                       worker processa devagar, grava o resultado

Existe porque o usuário não pode esperar três minutos numa requisição HTTP.

2 · navegador (Web Worker)

Um script que roda numa thread separada, para não travar a interface enquanto processa algo pesado. Não enxerga o DOM — comunica-se com a página por mensagens. O Service Worker é um primo que intercepta requisições e viabiliza funcionamento offline; é a peça central do MV3.

3 · plataforma (Cloudflare Workers)

Nome comercial de um produto serverless — que, apesar do nome, é o oposto do sentido 1: acorda por requisição e morre. Confusão fácil, e cara, ao escolher onde hospedar um processo.

Fila conc.

Lista de trabalhos pendentes que alguém vai processar depois. Dá três coisas: resposta imediata ao usuário, ritmo controlado (útil quando o destino bloqueia excesso de chamadas) e repetição automática em caso de falha. Consumida por um worker.

Preview deployment conc.

URL pública que plataformas como a Vercel geram para cada deploy, do tipo projeto-3f9a2b.vercel.app. Útil para revisar antes de publicar.

Risco: são acessíveis e podem ser indexadas, fazendo o app aparecer no Google em vários endereços, um deles com código velho. Confira o cabeçalho:

curl -sI https://SEU-PREVIEW.vercel.app/ | grep -i robots

Deve vir noindex.

Electron / Tauri fram.

Empacotam um navegador dentro de um aplicativo de desktop — VS Code, Slack, Discord, Figma são isso. Ganha-se reaproveitar time e código da web; paga-se em memória e tamanho. O Tauri ataca esse custo usando o navegador que o sistema já tem e escrevendo o núcleo em Rust.

Fora do navegador, o papel do JavaScript cabe à linguagem da plataforma — C# com WPF/XAML, Swift com SwiftUI, Kotlin com Compose. O que é universal é o laço de eventos: espera → acontece algo → código roda → estado muda → tela é redesenhada.

8. Dados, banco e formatos

Onde a informação mora, e em que forma ela viaja.

Postgres ferr.

Banco de dados relacional open-source, e o que está embaixo do Supabase. Guarda tabelas, executa SQL, garante transações e aplica as regras de integridade e de acesso. É um processo que escuta na porta 5432 e fala um protocolo binário próprio — não HTTP.

Tudo o que o Supabase faz — políticas de acesso, migrations, funções, gatilhos — é Postgres puro com uma camada de conveniência por cima.

A grafia: é PostgreSQL, com “gre”. Não PostgresSQL nem PostsSQL. O banco se chamava POSTGRES (de post-Ingres, o sucessor de um banco chamado Ingres, em Berkeley, nos anos 1980) e, ao ganhar SQL em 1996, virou PostgreSQL — o “SQL” substituiu as últimas letras de “Postgres” em vez de se somar a elas. Postgres é o apelido corrente e significa exatamente a mesma coisa.

Não confundir com PostgREST, que é outro programa, de outro autor, e cujo nome difere por duas letras.

Supabase serv.

Plataforma que entrega um Postgres gerenciado mais o que costuma vir junto: autenticação, API automática (PostgREST), armazenamento de arquivos, tempo real por WebSocket e funções. O ponto é não ser uma caixa-preta: por baixo é Postgres, e você pode descer até o SQL.

DDL (e DML, DCL, TCL) conc.

Data Definition Language: a fatia do SQL que mexe na estrutura do banco, não nos dados. O SQL se divide em quatro famílias, e as siglas aparecem em documentação o tempo todo:

  • DDL — define a estrutura: CREATE, ALTER, DROP, TRUNCATE
  • DML — mexe nos dados: INSERT, UPDATE, DELETE (e SELECT, que alguns separam como DQL)
  • DCL — controla o acesso: GRANT, REVOKE
  • TCL — controla a transação: BEGIN, COMMIT, ROLLBACK

A divisão parece escolástica e tem três consequências concretas.

1. Uma migration é exatamente isso: uma sequência de comandos DDL, versionada. Por isso é perigosa de um jeito próprio — DROP COLUMN não tem desfazer, enquanto um DELETE errado ainda tem backup da linha.

2. No Postgres, DDL é transacional — e isso é raro. Dá para envolver CREATE TABLE, ALTER TABLE e CREATE INDEX num BEGIN … COMMIT e, se o último passo falhar, tudo volta atrás. No MySQL cada DDL confirma sozinho, e uma migration que quebra no meio deixa o banco num estado híbrido para consertar à mão. É das razões técnicas mais fortes para preferir Postgres.

3. É o gancho de um event trigger. on ddl_command_end dispara ao fim de qualquer comando DDL, o que permite reagir a um CREATE FUNCTION que ninguém previu — inclusive escrito por outra sessão, meses depois.

E a separação entre as famílias é o que torna esse problema possível: CREATE FUNCTION é DDL, mas a concessão que abre a função nova a um papel público é DCL — e vem de configuração padrão, sem comando nenhum. Não há DCL para interceptar; o gatilho precisa se pendurar no DDL e desfazer o que veio de brinde.

CRUD conc.

Create, Read, Update, Delete — as quatro operações básicas sobre um registro. “Uma tela de CRUD” é uma tela que lista, cria, edita e apaga. É o vocabulário para dizer “essa parte não tem nada de especial”. Mapeia direto nos verbos do REST.

Parse / parser conc.

Parsear é ler um texto bruto e transformar em estrutura que o programa entende; o parser é o código que faz isso. Um leitor de nota fiscal é essencialmente um parser: pega o HTML da página e extrai itens, valores e CNPJ. “Erro de parsing” significa que o texto veio num formato diferente do esperado.

O navegador parseia HTML para construir o DOM.

JSON form.

JavaScript Object Notation: o formato padrão de troca de dados entre sistemas. Texto, legível, com objetos, listas, números, strings e booleanos — e nada mais (sem data nativa, sem comentários).

{ "titulo": "Parquet", "ano": 2013, "colunar": true }

YAML form.

Formato de configuração legível, onde a indentação define a estrutura em vez de chaves. É o formato de GitHub Actions, docker-compose e afins.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: npm ci

Três armadilhas: tab é proibido (só espaço); recuo inconsistente quebra; e valores sem aspas podem virar outra coisa — no e off viram booleano, 1.20 vira número. Na dúvida, aspas.

Indentação conc.

O espaço em branco no começo da linha, usado para mostrar hierarquia. Na maioria das linguagens é cosmética — o JavaScript usa chaves para delimitar blocos, e mal indentado roda igual.

Em YAML e Python, não: a indentação é a sintaxe, e mudar o recuo muda o significado — às vezes para outro significado válido, o que é pior, porque não dá erro. Em Makefile, ao contrário de tudo, o tab é obrigatório.

Parquet form.

Formato de arquivo para dados tabulares, colunar. Num CSV o arquivo é linha 1 inteira, linha 2 inteira; no Parquet é toda a coluna A, depois toda a coluna B.

  • SUM(valor) lê só aquela coluna — as outras nem saem do disco
  • comprime muito melhor (valores do mesmo tipo, repetidos): 5 a 10× menor que o CSV
  • tem tipos e esquema embutidos — CNPJ não perde o zero à esquerda

O preço: ilegível por humano, e ruim para escrever uma linha por vez. É formato de análise (Spark, DuckDB, pandas), não de aplicação transacional.

Delta format form. 2 sentidos

Depende do contexto, e valem os dois sentidos.

Delta Lake: um monte de arquivos Parquet mais um log de transações dizendo quais deles formam a versão atual da tabela. O Parquet guarda os dados; o log acrescenta transação, UPDATE/DELETE e histórico.

Delta genérico: guardar só a diferença em vez do estado inteiro — é o que o Git faz, e o que uma API faz em “sincronização incremental”. O fio comum: delta é a mudança, não o todo.

9. APIs, protocolos e rede

Como dois programas conversam.

API conc.

Application Programming Interface: o conjunto de operações que um sistema oferece para outro programa usar. Não é tela, é contrato.

O termo é amplo — uma biblioteca tem API sem rede nenhuma envolvida. Quando se diz “a API do sistema X”, quase sempre se fala da fatia que acontece por rede, sobre HTTP. E aí ainda há uma escolha de estilo:

API  ⊃  API web  ⊃  { REST, GraphQL, gRPC, tRPC, SOAP, … }

REST é um desses estilos, não sinônimo de API nem um protocolo à parte: é uma convenção sobre como usar o HTTP que já existe. Ver GraphQL / gRPC.

HTTP prot.

O protocolo da web. É stateless e sempre iniciado pelo cliente: você pede, o servidor responde, acabou — o servidor não tem como falar primeiro (daí WebSocket).

Cada resposta traz um status, que faz parte do contrato: 200 ok, 201 criado, 400 pedido malformado, 401 sem credencial, 403 credencial válida mas sem permissão, 404 não existe, 500 erro do servidor. HTTPS é o mesmo protocolo dentro de TLS.

REST pad. 2 sentidos

Sim, é sigla — REpresentational State Transfer —, e ela não ajuda. É um estilo de API, um entre vários, e a palavra é usada em dois sentidos bem diferentes:

1 · o sentido estrito

O da tese de doutorado de Roy Fielding, de 2000: um conjunto de restrições arquiteturais, entre elas a hipermídia — a resposta deve dizer ao cliente quais ações são possíveis a seguir, como links numa página. O que trafega não é o objeto, é uma representação do estado dele. Quase ninguém implementa isso.

2 · o sentido corrente

O que “API REST” significa na prática, em 2026: uma API sobre HTTP em que a URL identifica uma coisa e o verbo diz o que fazer com ela, trocando JSON. É este que você vai encontrar.

GET    /receitas/482   → me dá
PATCH  /receitas/482   → altera
DELETE /receitas/482   → apaga
POST   /receitas       → cria

O contraste é com o que existia antes — tudo POST, a ação escondida num parâmetro (?action=deleteRecipe), cada API com suas convenções. REST padronizou: o verbo já está no HTTP, use-o. Daí sair de graça o cache e o fato de você adivinhar uma API que nunca viu. Mapeia no CRUD.

Daí uma discussão recorrente e pouco útil: alguém aponta que sua API “não é REST de verdade”. No sentido 1, quase nenhuma é.

PostgREST ferr.

Um programa separado — de outro autor, escrito em Haskell — que fica na frente de um banco Postgres e o expõe como API REST. O nome é trocadilho: Postgres + REST.

navegador ──HTTP/JSON──> PostgREST ──SQL──> PostgreSQL

Você não escreve nenhum endpoint. Ele lê o esquema do banco — tabelas, colunas, tipos, chaves estrangeiras, funções — e gera a API sozinho. Criou uma tabela? Existe a rota, com filtro, ordenação, paginação e relacionamentos, sem uma linha de código de servidor. Criou uma coluna? Aparece no mesmo instante — não há camada intermediária para atualizar, e por isso ela não tem como sair de sincronia.

GET /receitas?tempo=lt.30&select=nome&order=nome
    ↓
select nome from receitas where tempo < 30 order by nome;

É o que está por baixo do cliente do Supabase: supabase.from('x').select() não fala com o banco — monta uma URL e chama /rest/v1/…, visível no painel de rede do navegador.

Como a autorização funciona, que é a peça engenhosa: o PostgREST conecta com um papel authenticator que sozinho quase nada pode. A cada requisição ele lê o JWT, extrai o papel (anon sem login, authenticated com) e o ID do usuário, executa SET LOCAL ROLE e publica o ID em variáveis de sessão — só então roda o SQL. É daí que auth.uid() tira o valor dentro de uma política.

A autorização acontece dentro do Postgres, não aqui. O PostgREST só entrega ao banco a identidade de quem pergunta. Três consequências: tabela sem RLS habilitada fica aberta, porque não há camada de servidor para barrar; revoke … from public não fecha nada, porque anon é concessão à parte; e um grant execute a anon expõe a função à internet mesmo que nenhuma tela a chame.

Duas pegadinhas do dia a dia. O limite de linhas — o Supabase configura um teto por resposta, e ele não avisa nem dá erro: devolve o teto, e quem esperava mais conclui que o banco tem menos. Só aparece quando o dado cresce. E os erros vêm do Postgres, atravessando o PostgREST: depurar API do Supabase é depurar SQL e RLS, não a camada HTTP.

RPC conc.

Remote Procedure Call: fazer uma chamada a outra máquina parecer uma chamada de função local. Você chama pelo nome, passa argumentos, recebe um retorno — e o fato de aquilo ter atravessado a rede fica escondido.

O contraste com REST é o que esclarece, porque são duas maneiras de pensar uma API:

  • REST — a URL nomeia uma coisa, e o verbo HTTP diz o que fazer: DELETE /receitas/482.
  • RPC — o endpoint nomeia uma ação: POST /apagarReceita com {id: 482}.

Nenhum é melhor em geral; cada um cabe num tipo de problema. REST é excelente quando a API é CRUD sobre recursos. RPC é melhor quando a operação não é CRUD e não corresponde a recurso nenhum — “recalcular o rateio do mês”, “enviar o convite”, “gerar o PDF”. Forçar isso em REST produz substantivos inventados para descrever verbos. Quase toda API real é híbrida.

Onde aparece sem o nome: o rpc() do Supabase chama uma função do Postgres — é RPC dentro de uma API REST, e o PostgREST reserva o caminho /rpc/ exatamente como válvula de escape para o que não é recurso.

supabase.rpc('calcular_rateio', { mes: '2026-09' })
    ↓
POST /rest/v1/rpc/calcular_rateio

Consequência de segurança: a função é um endpoint público se estiver concedida a um papel público — daí o peso de um grant execute a anon. E a chamada casa por nome e parâmetros: errar um nome de parâmetro devolve “função não existe”, não “parâmetro errado”, porque assinatura diferente é outra função.

A família: gRPC (binário, com contrato em .proto), tRPC (tipos compartilhados em TypeScript), e os antecessores SOAP e XML-RPC, verbosos e em XML — SOAP ainda aparece em sistema público brasileiro.

A abstração é deliberadamente vazada, e a crítica clássica é de 1994 (A Note on Distributed Computing): fazer o remoto parecer local esconde justamente o que não se pode esquecer. Função local não tem latência, não falha por rede, e ou executa ou não executa. Chamada remota pode demorar, pode falhar depois de já ter executado do outro lado — e então repetir não é seguro — e pode nunca responder. Quem trata RPC como função comum esquece timeout, repetição e idempotência, e descobre em produção.

GraphQL / gRPC pad.

Alternativas ao REST. GraphQL: o cliente pede exatamente os campos que quer, numa URL só — resolve o excesso e a falta de dados de APIs REST, ao custo de complexidade no servidor. gRPC: binário e rápido, para serviço falando com serviço. tRPC: tipos compartilhados entre front e back em TypeScript.

Webhook conc.

Uma URL sua que um serviço externo chama quando acontece um evento — é como um provedor de pagamento avisa seu sistema de que a cobrança passou. Inverte o sentido da API: em vez de você perguntar (polling), ele avisa.

Detalhe que só aparece depois de publicado: endpoint de webhook costuma ser por conta, não por produto. Se dois apps usam a mesma conta, cada rota recebe os eventos do outro — e deve responder 200 quando o evento não é dela, e não erro, ou o serviço retenta por dias.

Hook conc. 3 sentidos

“Gancho”: um ponto onde o sistema chama um código seu automaticamente quando algo acontece. Três usos bem diferentes:

  • Git hook — script que roda antes do commit, por exemplo para rodar lint.
  • Webhook — chamada vinda de um serviço externo.
  • React hook — useState, useEffect e os seus próprios: funções que engancham estado e ciclo de vida num componente do React. Sentido bem distinto dos outros dois.

DNS prot.

Domain Name System: a lista telefônica da internet. Traduz um nome (seusite.com.br) no endereço IP da máquina que responde por ele — porque o roteamento funciona por número, não por nome.

É a primeira etapa de qualquer acesso, e por isso entra inteira no TTFB. Costuma ser rápida por causa do cache em várias camadas (navegador, sistema, provedor), e a primeira consulta a um domínio novo é a que custa.

Os registros que aparecem na prática: A aponta para um IPv4, AAAA para IPv6, CNAME aponta um nome para outro nome (é como se liga um domínio à Vercel ou ao GitHub Pages), MX diz quem recebe e-mail, e TXT guarda texto — usado para provar posse do domínio e para SPF e DKIM.

Cada registro tem TTL, como um cache. Por isso mudança de DNS não é instantânea: o mundo continua usando o valor antigo até o TTL expirar. Baixar o TTL antes de uma migração é o truque que evita horas de espera — e precisa ser feito com antecedência, porque o TTL antigo ainda vale.

TCP/IP prot.

A base sobre a qual tudo o mais roda. IP entrega pacotes de uma máquina a outra, sem garantia: podem sumir, chegar fora de ordem ou duplicados. TCP constrói em cima disso uma conexão confiável — numera os pacotes, confirma o recebimento, reenvia o que faltou e entrega tudo na ordem certa.

HTTP, TLS, SSH e a conexão com o Postgres são todos TCP por baixo. Um socket é a ponta dessa conexão.

A conexão começa pelo handshake de três passos, que custa uma ida e volta antes de qualquer dado — somada à do TLS, são duas antes do primeiro byte útil. É a razão de reaproveitar conexões importar, e parte do que o TTFB mede.

O primo é o UDP, que só dispara pacotes sem confirmar nada — mais rápido e sem garantia, usado em vídeo ao vivo, jogos e DNS. O HTTP/3 roda sobre QUIC, que é confiabilidade reconstruída em cima de UDP, justamente para eliminar uma das idas e voltas.

Socket conc.

A abstração do sistema operacional para uma conexão de rede: um canal por onde entram e saem bytes. Tudo em rede é socket lá no fundo.

Socket cru (raw socket) é usar esse canal sem protocolo de aplicação por cima — você manda os bytes que quiser. Aparece em protocolos que não são HTTP, em equipamento industrial, e quando é preciso controlar a camada TLS, como no mTLS. É a camada que plataformas serverless não expõem.

WebSocket prot.

Mantém uma conexão aberta e de mão dupla entre navegador e servidor. Começa como uma requisição HTTP pedindo “faça upgrade”; aceito, a mesma conexão fica aberta e os dois lados mandam mensagem a qualquer momento. A URL muda para wss://.

Resolve o que o HTTP não faz: o servidor falar primeiro — chat, notificação, cotação, edição simultânea. É o que está por trás do tempo real do Supabase. E, por manter conexão viva, exige processo, não serverless.

Beacon conc. 3 sentidos

Farol. O nome descreve o mecanismo: um sinal curto, de mão única, disparado para anunciar presença ou registrar que algo aconteceu — sem esperar resposta útil. Ninguém responde ao farol; ele só precisa ser visto.

1 · telemetria na web

O problema: quando a pessoa fecha a aba, o navegador cancela as requisições em voo — um fetch() disparado no fim da visita não chega. É por isso que métrica de saída é a mais difícil de coletar: o evento acontece exatamente quando o canal morre.

navigator.sendBeacon('/eventos', JSON.stringify(dados))

Isso entrega o pacote ao navegador, não ao servidor: ele se encarrega de enviá-lo mesmo depois de a página deixar de existir. Em troca, só POST, sem cabeçalhos próprios, com teto de tamanho, e você nunca lê a resposta. A alternativa moderna com mais controle é fetch(url, { keepalive: true }).

2 · rádio, proximidade

Um transmissor que emite um identificador a cada fração de segundo, e nada mais — iBeacon (Apple) e Eddystone (Google), para localização dentro de prédios, onde o GPS não chega. O mesmo nome vale no Wi-Fi: o roteador emite beacon frames anunciando a rede, e é assim que o nome dela aparece na lista antes de qualquer conexão.

3 · segurança

Beaconing: um programa instalado numa máquina que chama de volta quem o pôs lá, em intervalos regulares, perguntando se há ordem nova. O sinal que o denuncia é a regularidade — tráfego humano é irregular; beaconing tem período.

Duas armadilhas no sentido 1. Um beacon que falha falha em silêncio, por construção — aceitável para o evento de saída, péssimo como único caminho de toda a telemetria. E o gatilho: o reflexo é usar beforeunload, mas no celular esses eventos muitas vezes nunca acontecem (a aba é congelada, ou o app é morto). O confiável é visibilitychange quando o estado vira hidden — o último instante garantido.

INP e CLS só têm valor final quando a visita acaba — o INP é a interação mais lenta da visita inteira, o CLS soma os pulos até o fim. Por isso toda biblioteca de Core Web Vitals reporta por beacon.

Polling prát.

Perguntar repetidamente “tem novidade?” — a gambiarra pré-WebSocket. Desperdiça chamadas e atrasa a notícia. O long polling ameniza fazendo o servidor segurar a resposta até ter algo.

User-Agent conc.

Cabeçalho HTTP em que o cliente diz quem é — navegador, robô, ou o que ele quiser alegar. Serviços usam isso para liberar ou bloquear.

Pode virar incompatibilidade real: um mesmo sistema pode precisar de um User-Agent de navegador para um destino e ser recusado por ele em outro. Testa-se com curl -A. Ver curl.

Proxy conc. 2 sentidos

Um intermediário por onde a conexão passa. O nome é o mesmo para duas coisas que ficam em lados opostos.

1 · de saída (forward)

Fica do lado do cliente e fala com a internet em nome dele. É o que o navegador usa quando se configura “proxy” nas opções ou por PAC. Para HTTPS, o navegador manda CONNECT host:443 e o proxy vira um túnel cego — ele sabe para onde, não o quê. Só vê o conteúdo se fizer bridging.

2 · reverso

Fica do lado do servidor e recebe em nome dele: nginx na frente de uma aplicação, o CDN na frente do site, a Vercel na frente da sua função. O cliente nem sabe que ele existe.

Um proxy de saída pode autenticar quem o usa: responde 407 Proxy Authentication Required e o cliente reenvia com Proxy-Authorization. Uma extensão de Chrome preenche isso sozinha por onAuthRequired. Se o PAC apontar para HTTPS proxy:443 em vez de PROXY, o próprio CONNECT vai cifrado.

PAC arq.

Proxy Auto-Config: um arquivo JavaScript de uma função só, FindProxyForURL(url, host), que o navegador chama a cada requisição para decidir se ela vai direto (DIRECT) ou por um proxy (PROXY host:porta ou HTTPS host:porta). É o jeito de rotear só alguns domínios por um proxy e deixar o resto em paz.

“Instalar” um PAC é dizer ao navegador onde ele está — nas configurações do sistema, por política de empresa, ou por uma extensão com a permissão proxy, que o entrega por chrome.proxy.settings.set. Neste último caso, o PAC pode ser gerado por pessoa e trocado a qualquer momento sem ninguém instalar nada: a extensão baixa a lista, monta a função, aplica. É configuração do navegador, não do computador — outro navegador, outro perfil ou outra máquina não o veem.

10. Segredos, certificados e segurança

O que não pode vazar, e onde guardar.

.env arq.

Arquivo de variáveis de ambiente — chaves de API, senhas, URLs de projeto — mantido fora do repo pelo .gitignore. O costume é versionar um .env.example com os nomes das variáveis e nenhum valor, para quem clonar saber o que precisa preencher.

Numa SPA, variável embutida no bundle não é segredo — está no navegador do usuário. Segredo de verdade só existe do lado do servidor.

Vault ferr.

Cofre de segredos: guarda muitos segredos de tipos variados, criptografados, com política de quem lê o quê e registro de cada leitura — e te devolve o valor. É o modelo, não uma falha: em algum momento o segredo entra na memória da aplicação.

Existe embutido no Supabase e como produto autônomo (HashiCorp Vault). Complementar ao HSM, não alternativo.

HSM ferr.

Hardware Security Module: uma caixa física ou chip que guarda a chave privada e nunca a entrega. Você manda o dado, ele devolve assinado. Não há operação que exporte a chave — nem para você.

A diferença para o Vault: o Vault devolve o segredo, o HSM devolve só o resultado. Se o servidor for comprometido, o atacante assina enquanto tiver acesso, mas não leva a chave. Um token A3 é um HSM pequeno.

Composição clássica: o HSM guarda a chave-mestra, e o Vault usa essa chave para criptografar todo o resto.

OpenSSL ferr.

A biblioteca (e a CLI) que faz o trabalho de criptografia na maior parte da internet: gerar chaves, criar e inspecionar certificados, converter formatos, abrir um .pfx/.p12. É a ferramenta de quem mexe com certificado digital.

Certificado A1 / A3 conc.

No padrão brasileiro de certificação digital: A1 é um arquivo (.pfx) protegido por senha, que pode ser copiado e instalado — validade de um ano. A3 vive num token ou cartão, é um HSM pequeno, e a chave não sai de lá — validade maior.

A diferença prática é exatamente a de Vault e HSM: o A1 é conveniente e copiável; o A3 é seguro e não automatizável sem o dispositivo presente.

TLS prot.

Transport Layer Security (sucessor do SSL): a camada que criptografa a conexão. HTTP dentro de TLS é HTTPS. Dá três garantias: sigilo, integridade, e autenticidade do servidor — ele prova quem é, com um certificado assinado por uma autoridade que o navegador reconhece.

mTLS prot.

Mutual TLS: os dois lados provam quem são. Além do servidor, o cliente apresenta um certificado durante o handshake. É autenticação por certificado, não por senha.

Consequência arquitetural: isso acontece na camada de conexão, antes de qualquer HTTP. Exige controle sobre o socket — carregar a chave privada, montar o contexto TLS, negociar —, e plataformas serverless não expõem esse nível. Não é limitação de cota: a peça não existe. Por isso esse tipo de sistema pede processo.

Handshake conc. 2 sentidos

“Aperto de mão”: a negociação inicial de uma conexão, antes de qualquer dado útil. São dois, em camadas, e acontecem nesta ordem:

1 · TCP

O de três passos (SYN, SYN-ACK, ACK) que estabelece a conexão bruta entre duas máquinas. É a base de todo socket, e onde falham problemas de rede, porta fechada ou firewall.

2 · TLS

Em cima do anterior: acerta a versão do protocolo e o algoritmo de criptografia, verifica o certificado do servidor (e, em mTLS, o do cliente) e estabelece a chave da sessão. Ver TLS.

Distinguir os dois é diagnóstico puro: connection refused é o primeiro; erro de certificado é o segundo — e ambos acontecem antes de existir requisição HTTP. É também a etapa que custa tempo, e o motivo de reaproveitar conexões importar.

JWT pad.

JSON Web Token (fala-se “djót”): um token de acesso que carrega dentro de si quem é o portador, em vez de ser um código que o servidor precisa consultar num banco. São três partes separadas por ponto — cabeçalho, dados e assinatura — em JSON codificado:

eyJhbGciOi…  .  eyJzdWIiOiIxMjMiLCJyb2xlIjoiYXV0aGVudGljYXRlZCJ9  .  SflKxwRJ…
  cabeçalho             dados (sub, role, exp…)                    assinatura

A assinatura é o mecanismo inteiro. Quem tem a chave secreta consegue verificar, em memória e sem consultar nada, que aquele conteúdo não foi alterado. É isso que permite ao PostgREST saber quem está perguntando sem ida ao banco, e é o que torna o modelo stateless.

O que quase todo mundo erra: os dados não são secretos. Estão apenas codificados em base64, não criptografados — qualquer pessoa cola o token num site e lê o conteúdo. A assinatura garante que ninguém alterou, não que ninguém leu. Nunca ponha em JWT nada que não possa ser lido pelo portador.

A contrapartida do stateless: um JWT válido não pode ser cancelado, porque ninguém o consulta em lugar nenhum. Daí a validade curta (minutos ou uma hora) somada a um refresh token, este sim guardado e revogável. Logout não invalida o JWT que já saiu — ele apenas expira.

Token conc. 2 sentidos

1 · segurança

Uma referência opaca que substitui um dado sensível. O caso clássico é o cartão de crédito: o número vai do navegador direto ao processador de pagamento, e o que volta para você é um token que só serve para cobrar naquela conta — e não vale nada se vazar. Ver PCI DSS.

Também se usa para credenciais de acesso (token de sessão ou de API), com a mesma ideia: algo revogável e de escopo limitado, em vez da senha real.

2 · modelos de linguagem

A unidade em que uma IA lê e escreve: um pedaço de palavra, não uma letra nem uma palavra inteira. “Glossário” pode ser dois ou três tokens; em português eles rendem menos que em inglês. É a unidade de cobrança das APIs de IA e a medida da janela de contexto — quanto o modelo consegue considerar de uma vez.

Um terceiro sentido existe em compiladores: o parser quebra o código em tokens antes de entendê-lo. Os três compartilham a ideia de “unidade mínima que representa outra coisa”.

PCI DSS pad.

Payment Card Industry Data Security Standard: a norma que as bandeiras impõem a quem toca dados de cartão. Não é lei, é contrato — descumprir custa multa e, no limite, o direito de aceitar cartão. Exige rede segmentada, criptografia, log de tudo, varredura trimestral e auditoria: um programa contínuo.

A conclusão prática é uma só: você não quer estar no escopo. Basta que o número do cartão nunca toque seu servidor — usando o formulário hospedado do provedor (um iframe dele, ou redirecionamento) e recebendo de volta um token.

O jeito de estragar é específico: construir o próprio formulário de cartão e mandar os dados ao seu back-end. Nesse instante você entra no escopo inteiro.

CA conc. 2 sentidos

Certificate Authority, autoridade certificadora: quem assina certificados e, com isso, garante que aquela chave pública pertence àquele nome. Confiar numa CA é confiar em tudo que ela assinar.

1 · pública

Let's Encrypt, DigiCert, GlobalSign — e, no Brasil, as credenciadas na ICP-Brasil (Serasa, Certisign, Soluti). Já vêm na lista de confiança de todo navegador e sistema operacional, o trust store. É por isso que um site com certificado delas abre sem aviso.

2 · interna

Uma CA criada por você, com openssl, que só vale onde você a instalar. Serve para redes de empresa, ambientes de teste e para um proxy que faz bridging. Instalá-la numa máquina é dar a quem tem a chave dela o poder de se passar por qualquer site — a menos que o certificado da CA traga name constraints, que limitam os domínios para os quais ela pode emitir.

Trust store conc.

A lista de CAs em que um programa confia. Não é uma só por máquina: o Windows tem a dele (e o Chrome e o Edge a usam), o Firefox tem a própria, o Java tem o cacerts, e o Node traz a da Mozilla embutida — no Node 24, --use-system-ca faz ele usar a do sistema.

Consequência prática: “instalar a CA” significa acrescentá-la a uma dessas listas. No Windows, certutil -user -addstore Root ca.pem faz isso para o usuário atual, sem administrador; sem -user, para a máquina inteira. Cada programa com lista própria é um passo de instalação a mais. Ver certificado folha.

Cadeia de certificação conc.

Ninguém confia direto no certificado de um site. Confia-se numa CA raiz, que assina uma CA intermediária, que assina o certificado do site — o folha. Validar é percorrer essa corrente até chegar numa raiz que esteja no trust store.

O servidor deve mandar a cadeia inteira, menos a raiz. Quando manda só a folha, o navegador ainda abre a página, porque busca o intermediário sozinho pelo AIA; um programa que use OpenSSL não busca, e falha com unable to verify the first certificate. O openssl s_client mostra a cadeia recebida nas linhas s: (sujeito) e i: (emissor).

Certificado folha conc.

Leaf certificate: o último elo da cadeia, o certificado do site em si (ou da pessoa, ou da empresa). É o único que não assina outros — a árvore termina nele, daí o nome. Todo o resto acima dele é CA.

Num proxy de bridging, é o que se emite na hora, um por domínio, assinado pela CA interna: precisa trazer o nome do site em subjectAltName, ou o Chrome recusa. E um certificado folha sem ponto de revogação (CRL ou OCSP) é aceito pelo Chrome mas recusado pelo Schannel do Windows (PowerShell, .NET, curl.exe) com revocation status is unknown.

AIA conc.

Authority Information Access: um campo dentro do certificado que diz onde baixar o certificado de quem o emitiu. É o que permite ao navegador completar uma cadeia que o servidor mandou incompleta — Chrome, Edge e Windows fazem essa busca; OpenSSL, Node e Go não.

Efeito colateral: um site mal configurado “funciona no navegador” e falha na automação, e a culpa parece ser do seu código. A saída é embarcar as intermediárias que faltam no ca da conexão.

PEM e PFX form.

Dois jeitos de guardar a mesma coisa — chave e certificado — em arquivo.

PEM é texto: blocos -----BEGIN CERTIFICATE----- em base64, um item por bloco, sem senha por padrão. É o que openssl, Node e Go leem sem esforço.

PFX (ou .p12, formato PKCS#12) é binário: chave, certificado e cadeia num pacote só, cifrado com senha. É como o certificado A1 é entregue no Brasil. Os antigos, exportados de Windows velho, usam RC2-40 e 3DES, que o OpenSSL 3 recusa por padrão (Unsupported PKCS12 PFX data) — no Node, --openssl-legacy-provider resolve. Por isso um sistema que recebe .pfx costuma abri-lo uma vez e guardar em PEM cifrado com chave própria: o resto do sistema nunca mais lida com o formato.

TLS bridging conc.

Um proxy que termina o TLS do cliente com um certificado próprio e abre outro TLS com o destino — duas conexões cifradas com o proxy no meio, copiando bytes de uma para a outra. É o mecanismo de todo antivírus e firewall corporativo que “inspeciona HTTPS”, e também o de um serviço que apresenta um certificado de cliente (mTLS) em nome de quem não o tem.

Exige duas coisas: uma CA interna instalada no cliente, e os dois lados falando a mesma versão de HTTP — o proxy copia bytes, então se o navegador negociar HTTP/2 e o destino HTTP/1.1, nada funciona; prende-se o ALPN em http/1.1 dos dois lados. Do lado do cliente, o cadeado mostra a CA interna, não o site: é o sinal de que o proxy está no caminho.

11. Verificação e qualidade

Como saber que funciona — e como não quebrar ao tentar.

Smoke test prát.

Também teste de fumaça. O teste mínimo que responde “isso está de pé?”. O nome vem da eletrônica: liga e vê se sai fumaça.

Não checa se está correto, checa se não está morto — abre a home, faz login, salva um registro. É o que se roda logo depois de um deploy.

Dry run prát.

Rodar “a seco”: o programa executa e diz o que faria, sem fazer. rsync --dry-run, terraform plan, npm publish --dry-run. É a defesa padrão antes de qualquer operação destrutiva ou em massa.

Harness conc.

Literalmente arreio, a correia que liga o cavalo à carroça — e a metáfora é precisa: o arreio não puxa nada; conecta, direciona e limita a força de quem puxa. Em software, é o andaime que envolve um código para executá-lo em condições controladas, sem fazer parte dele.

O uso clássico é o test harness: prepara o estado inicial (as fixtures), chama o código sob teste isolando um do outro, coleta o que aconteceu e compara com o esperado, limpa o que criou e relata. Jest, Vitest e pytest são harnesses; um script de conferência escrito à mão também é.

O uso que apareceu com IA é o agent harness: um modelo de linguagem sozinho só produz texto — não lê arquivo, não roda comando, não lembra de ontem. O harness é o programa em volta que monta o contexto, chama o modelo, lê o que ele pediu, verifica permissão, executa a ferramenta e devolve o resultado, em laço. Ferramentas disponíveis, regras de permissão e compactação de contexto são dele, não do modelo — o que importa ao diagnosticar: um limite do harness se resolve por outro caminho, não insistindo no mesmo pedido.

Não confundir: um framework chama o seu código (React, Next) — nele você é o conteúdo; um runtime apenas executa (Node, o motor do navegador). No harness, seu código é o objeto de estudo. A diferença é a direção do controle.

Um harness fraco engana: se a camada de verificação aceita só “falhou”, o teste passa com qualquer erro — inclusive um que ninguém previu. Distinguir “falhou como eu esperava” de “falhou de um jeito novo” é trabalho do harness, não do teste. Ver medir antes de afirmar.

Medir antes de afirmar prát.

Hábito, não ferramenta: checar a hipótese em vez de deduzi-la. Duas armadilhas que aparecem sempre:

  • amostra de um não prova “qualquer”. Um destino que falha não autoriza concluir “nenhum destino funciona”.
  • medir com controle. Para saber se uma coluna existe, pergunte também por uma coluna inventada; se o erro for o mesmo, a medição não está medindo nada.

curl e dry run são as ferramentas mais diretas disso.

12. Conteúdo e web pública

Ser encontrado, e ser compartilhável.

SEO prát.

Search Engine Optimization: fazer o conteúdo ser encontrado em buscadores. Só alcança o que abre sem login — página atrás de autenticação não é assunto de SEO.

A renderização importa, mas não é tudo: CSR não torna o site invisível (o Google executa JavaScript), e sim mais lento para indexar, frágil, com títulos repetidos, e completamente opaco para os robôs que não executam JS — WhatsApp e redes sociais entre eles. Ver Open Graph.

Desempenho entra como sinal de ranqueamento pelos Core Web Vitals — e a métrica a olhar é o LCP, não o TTFB. Numa SPA os dois discordam: TTFB ótimo com LCP ruim é a assinatura do modelo, não sinal de que está tudo bem.

robots.txt arq.

Arquivo na raiz do site que diz aos robôs o que não visitar.

User-agent: *
Disallow: /admin/

Sitemap: https://exemplo.com.br/sitemap.xml

Três mal-entendidos: (1) é um pedido, não uma trava — e por ser público, listar /admin/ apenas publica onde ele fica; (2) impede a visita, não a indexação (ver noindex); (3) um Disallow: / esquecido derruba o site inteiro da busca, silenciosamente — é o primeiro item a conferir em qualquer “não aparecemos no Google”.

noindex conc.

Instrução para o robô não listar a página no resultado. Vai na própria página, nunca no robots.txt:

<meta name="robots" content="noindex">

Ou como cabeçalho HTTP — única opção quando não há HTML (PDF, imagem):

X-Robots-Tag: noindex

A armadilha: Disallow no robots.txt impede o robô de ver o noindex. Bloqueada, a página não é baixada, a meta tag não é lida, e a URL pode ser listada assim mesmo — sem descrição. Para tirar do Google de verdade: libere no robots.txt e ponha noindex na página.

sitemap.xml arq.

Lista das URLs que você quer que sejam indexadas, com data de atualização. Não garante indexação; ajuda o robô a descobrir o que existe, sobretudo em site grande ou com páginas pouco linkadas. Frameworks como o Next geram o arquivo a partir das rotas, o que evita que ele envelheça.

Canonical conc.

O endereço que a página declara como o original de si mesma. Vem de cânone: a versão oficial, a que vale. Vai no <head>:

<link rel="canonical" href="https://www.site.com.br/receitas/risoto">

O problema que resolve: para você é uma página; para o buscador, cada endereço é uma página diferente. Estes quatro podem mostrar exatamente o mesmo conteúdo:

https://www.site.com.br/receitas/risoto
https://www.site.com.br/receitas/risoto?utm_source=instagram
https://site.com.br/receitas/risoto
http://www.site.com.br/receitas/risoto

Diante de cópias idênticas sem nenhuma dizendo qual é a original, o Google escolhe sozinho — e avisa no Search Console: “Cópia sem página canônica selecionada pelo usuário”. A tag é a resposta: não importa por onde você chegou, o original é este.

Três detalhes que confundem:

  • É sugestão, não ordem. O Google costuma aceitar, mas ignora uma canonical que pareça errada — apontando para página de conteúdo bem diferente, por exemplo.
  • Não é redirecionamento. O redirect (301/308) leva a pessoa para outro endereço; a canonical não leva ninguém a lugar nenhum — a pessoa fica onde está, e só o robô recebe o recado. Por isso o Search Console lista os dois como motivos separados, e “Página com redirecionamento” quase sempre é o redirect funcionando, não defeito.
  • Toda página aponta para si mesma, com URL absoluta e na forma escolhida (https, com ou sem www). Parece redundante; é o que absorve os ?utm= e as variações que você não controla.

A armadilha da SPA: quando o servidor devolve o mesmo index.html para qualquer caminho, /qualquer-coisa-errada responde 200 com o conteúdo da home — uma fábrica de cópias. Uma canonical fixa apontando para a home resolve isso de graça, enquanto o app não tiver rotas de conteúdo. No dia em que existir /receitas/risoto, a mesma linha passa a mentir: toda receita se declara cópia da home e nenhuma é indexada. Aí a canonical tem de ser gerada por rota — e precisa estar no HTML servido, pelo mesmo motivo do Open Graph.

Com o noindex forma um par que se confunde: noindex diz “não liste esta página”; canonical diz “liste, mas pelo outro endereço”. Usar os dois na mesma página manda recados contraditórios.

Slug conc.

A parte legível da URL que identifica um item:

/receitas/risoto-de-abobora-com-alecrim
            └──────── o slug ────────┘

Minúsculas, sem acento, sem espaço (hífen no lugar), sem caractere especial. O nome vem do jornal impresso: slug era o apelido curto que a redação dava a uma matéria durante a produção, antes do título definitivo.

  • É melhor que /receitas/482 — diz ao humano e ao buscador do que se trata antes de abrir.
  • Uma vez indexado, mudar custa caro: links quebram e o ranqueamento zera. Exige redirecionamento permanente (301) para não perder o que havia. Por isso se decide com cuidado e se congela.
  • Precisa ser único. Duas receitas de mesmo nome se resolvem com sufixo (-2) ou com slug híbrido (/receitas/482-risoto-de-abobora), que é legível e garantidamente único.

Cada âncora deste glossário (#cache-busting, #edge-function) é um slug.

Open Graph pad.

Conjunto de meta tags criado pelo Facebook em 2010 e adotado por todo mundo, que define o card exibido quando alguém compartilha o link.

<meta property="og:title"       content="Risoto de abóbora">
<meta property="og:description" content="Pronto em 40 min, serve 4.">
<meta property="og:image"       content="https://site.com.br/img/risoto.jpg">
<meta property="og:url"         content="https://site.com.br/receitas/risoto">
<meta property="og:type"        content="article">

Três detalhes que fazem falhar na prática:

  • É property=, não name=. As outras meta tags usam name; trocar faz várias ferramentas ignorarem em silêncio.
  • A imagem precisa de URL absoluta — quem lê está em outro servidor. Idealmente ~1200×630.
  • Não podem ser injetadas por JavaScript. Os robôs de WhatsApp, Instagram, Facebook e LinkedIn não executam JS: leem o HTML servido e vão embora. Numa SPA, tags adicionadas depois pelo React não existem para eles, e o link aparece sem foto nem título.

O X/Twitter tem um conjunto próprio (twitter:card), mas cai nas og: quando elas faltam — então og primeiro.

Esses serviços cacheiam o card: corrigir a tag não corrige o link já compartilhado. Cada plataforma tem um depurador para forçar a releitura. É cache outra vez, agora numa camada que não é sua.

Dados estruturados (JSON-LD) pad.

Marcação que descreve o conteúdo de forma legível por máquina: que aquilo é uma receita, com ingredientes, tempo de preparo, porções e avaliação. Vai num bloco à parte:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Recipe",
  "name": "Risoto de abóbora com alecrim",
  "recipeIngredient": ["300 g de arroz arbóreo", "500 g de abóbora"],
  "totalTime": "PT40M",
  "recipeYield": "4 porções"
}
</script>

O “LD” é de Linked Data, dados ligados — e é a parte interessante. A web liga documentos por links, mas as coisas descritas neles não se ligam: meu site diz "autor" e o seu diz "criador", e nenhuma máquina sabe que é o mesmo conceito. Linked Data resolve identificando conceitos por URL — duas páginas que apontam para a mesma definição estão falando da mesma coisa, comprovadamente. É a ideia de web semântica, de Tim Berners-Lee.

Daí as três chaves especiais: @context é o vocabulário (“quando eu disser name, é no sentido de schema.org”) e é o que transforma JSON comum em dado ligado; @type é que coisa é (Recipe, Product, Organization, RealEstateListing); @id é o identificador global, quando outras páginas precisam apontar para o item.

Por que JSON-LD venceu as alternativas anteriores (microdata, RDFa): elas exigiam espalhar atributos pelo HTML, entrelaçando dado e marcação — mudar o layout quebrava os dados. JSON-LD é um bloco separado, independente da estrutura visual. O Google recomenda explicitamente.

O retorno é concreto: é o que produz o resultado rico — foto, estrelas, tempo de preparo —, que ocupa várias vezes mais espaço na busca que um resultado comum. Depende de o HTML ser servido pronto, o que liga isso diretamente à escolha de renderização.

CMS / headless CMS serv.

CMS (Content Management System) é onde pessoas não-técnicas escrevem e editam o conteúdo do site. O WordPress tradicional é acoplado: guarda o texto e monta a página.

Headless (“sem cabeça”) jogou fora a parte de montar a página. Sobra um banco de conteúdo estruturado mais uma API que o devolve como dados — JSON, sem HTML nem CSS. Quem desenha é você. Exemplos: Contentful, Sanity, Strapi, Directus, Payload.

Resolve modelagem de conteúdo, edição sem tocar no repo, fluxo editorial e um conteúdo servindo vários destinos. Custa a pré-visualização fiel, dependência de um serviço, e assinatura.

O critério: headless se paga quando há alguém além do programador escrevendo conteúdo. Se só você edita, um arquivo Markdown no repo já é um CMS de graça — com diff e histórico.

WordPress / WooCommerce serv.

PHP + MySQL; o WooCommerce é o plugin que o transforma em loja. Roda cerca de 40% da web.

Não cabe na Vercel, e não é limitação de plano: precisa de banco, escreve no próprio sistema de arquivos (upload de imagem, plugin instalado) e se administra por dentro, com o site no ar — tudo incompatível com disco efêmero e pacote imutável vindo do Git.

O moderno equivalente é o commerce headless: Next na Vercel mais um back-end de comércio por API (Shopify, Medusa, Stripe). Ganha desempenho e flexibilidade; perde onde importa para lojista pequeno — sem programador, nada muda na loja. O critério não é técnico: é quem opera no dia a dia.

13. Diversos

O que não coube em lugar nenhum, e mesmo assim aparece.

MCP prot.

Model Context Protocol: protocolo aberto (Anthropic, 2024) que padroniza como uma IA conversa com ferramentas e dados externos. Antes, cada integração era feita à mão; com MCP, um “servidor MCP” expõe ferramentas e qualquer cliente compatível as usa.

É o que permite a um assistente listar seus projetos no Supabase ou na Vercel sem você passar nada.

MV3 pad.

Manifest V3: a versão atual do formato de extensões do Chrome. Trocou as páginas de fundo permanentes por service workers efêmeros — a mesma mudança conceitual do serverless — e restringiu execução de código remoto. Só importa para quem escreve extensão, mas é o motivo de metade das extensões antigas terem parado de funcionar.

Thumbs.db / .DS_Store arq.

Arquivos que o sistema operacional cria sozinho numa pasta — miniaturas no Windows (Thumbs.db), metadados de exibição no macOS (.DS_Store). Ocultos, regeneráveis e sem relação com o projeto.

Estão em praticamente todo .gitignore do mundo por serem o exemplo típico de lixo que aparece sozinho, muda sozinho e polui o diff.