Este portfólio é cheio de animação, som e efeito, exatamente o tipo de site que costuma ir mal em performance. Então, antes de opinar, medi. Este post é o diário dessa otimização: quais ferramentas usei, o que cada uma encontrou, o que mudei e quanto melhorou.
No fim tem um checklist para aplicar em qualquer projeto. Eu mesmo vou usar nos meus outros apps.
Antes e depois
Medições do PageSpeed Insights na home, no celular. "Antes" é o primeiro deploy (15/10/2026), "depois" é o domínio próprio no dia seguinte, com as correções deste post.
| Métrica | Antes | Depois |
|---|---|---|
| Performance | 82 | 84 |
| Acessibilidade | 92 | 96 → 100* |
| Boas práticas | 96 | 100 |
| SEO | 100 | 100 |
| Total Blocking Time | 80 ms | 50 ms |
| Speed Index | 7,8 s | 6,4 s |
| Largest Contentful Paint | 3,6 s | 3,5 s |
* O 96 tinha um problema de contraste que corrigi depois dessa medição; no Lighthouse local, com a correção, a acessibilidade chega a 100.
As ferramentas
| Ferramenta | O que mede | Precisa de login? |
|---|---|---|
| Lighthouse | Carregamento, acessibilidade, boas práticas e SEO, rodando no seu computador | Não |
| PageSpeed Insights | O mesmo Lighthouse, rodando nos servidores do Google, mais dados de usuários reais quando o site tem tráfego | Não |
| Chrome DevTools | Fluidez durante o uso: FPS, frames lentos, tarefas longas | Não |
| Schema Markup Validator | Se os dados estruturados (JSON-LD) estão corretos | Não |
| Rich Results Test | Se o Google consegue gerar resultados ricos com esses dados | Sim, conta Google |
| Google Search Console | Indexação, buscas que trazem gente ao site, erros de rastreamento | Sim, e verificar o domínio |
Uma regra que aprendi: rode o Lighthouse mais de uma vez. No meu desktop, três rodadas seguidas deram 95, 83 e 85. Use a mediana, não o melhor número.
O que cada ferramenta encontrou
1. O preloader segurava a página
O preloader (aquele contador de 0 a 100) durava 1,6 s. Ele cobria o título principal, que é o maior elemento da tela, e o LCP passava de 3 segundos no celular. Baixei para 0,4 s.
O ganho no LCP foi pequeno (3,6 s para 3,5 s), e isso também é um aprendizado: o título entra com uma animação de revelação, e o navegador só conta o LCP quando ele aparece de verdade. O próximo passo é fazer o título já nascer visível e animar só o detalhe.
2. Um erro que só existia em produção
As boas práticas estavam em 96 por causa de um erro no console: erro de hidratação do React (#418). As datas dos posts eram formatadas no fuso do servidor (UTC) e no fuso do navegador (UTC−3), e uma data de meia-noite virava "12 de ago." num lado e "11 de ago." no outro.
No meu computador, servidor e navegador estavam no mesmo fuso, então o erro nunca aparecia. A correção foi formatar as datas sempre em UTC. Resultado: 100 em boas práticas.
3. Acessibilidade: o que o olho não vê
O Lighthouse apontou quatro problemas, nenhum visível a olho nu:
aria-labelproibido: a biblioteca que divide o texto para animar (SplitText) colocavaaria-labelem parágrafos, o que só é permitido em títulos e alguns elementos.- Nome acessível diferente do texto visível: o link do logo dizia "Início" para leitores de tela, mas mostrava "Iago Gois".
- Contraste de um atalho dentro do debugger.
- Contraste dos botões: o laranja do tema Editorial com texto branco dava 4,0:1, e o mínimo é 4,5:1. Calculei o contraste de todos os temas: três combinações estavam abaixo. Escureci levemente dois tons e troquei a cor do texto no terceiro, sem mudar a cara de nenhum tema.
4. A página "pulava" no desktop
No desktop, o PageSpeed acusou CLS de 0,105 (o limite do "bom" é 0,1). O culpado parecia ser o efeito de granulado da tela, mas não era: durante o preloader a rolagem fica travada, sem barra; quando ela libera, a barra de rolagem aparece e a página fica 15 px mais estreita, e tudo se desloca. O granulado só levou a culpa por ser o maior elemento.
A correção é uma linha de CSS:
html {
scrollbar-gutter: stable;
}Ela reserva o espaço da barra desde o início. O mesmo problema derrubava um item da nova categoria Agentic Browsing do Lighthouse, que mede se o site é navegável por agentes de IA.
5. Fluidez: o que o Lighthouse não mede
Lighthouse só olha o carregamento. Num site animado, o que importa também é se a rolagem é suave. Escrevi um teste que abre o site no Chrome com tela de celular e CPU 4x mais lenta, rola até o fim e mede cada frame.
A primeira descoberta foi incômoda: o modo leve não aliviava nada. No tema Aurora ele era até mais lento que tudo ligado.
Para entender o porquê, gravei traces de performance no Chrome DevTools e desliguei um efeito por vez:
- JavaScript não era o problema. Era só ~8% do tempo de CPU durante a rolagem, somando GSAP, React e o código do site.
- O custo vinha de efeitos que nunca param: marquees (mesmo fora da tela), grain animado, reveal linha a linha e, no Aurora, o fundo com blur ao vivo e o desfoque de vidro nos cards. Enquanto algo se mexe, o navegador refaz estilo e camadas da página inteira a cada frame.
- O modo leve mirava o alvo errado. Desligava cursor, magnetismo e tilt, que no celular já não rodam (precisam de mouse), e trocava o shader por um fundo com blur que não era mais barato.
O que mudou:
- Marquees e loops infinitos pausam quando saem da tela, em todos os modos.
- No modo leve: grain parado, fundo animado vira um gradiente fixo, sem desfoque de vidro e reveal por bloco em vez de por linha.
Resultado no celular simulado (FPS médio, mediana de 4 rodadas):
| Tema | Cenário | Antes | Depois |
|---|---|---|---|
| Editorial | Tudo ligado | 59 | 68 |
| Editorial | Modo leve | 55 | 75 |
| Aurora | Tudo ligado | 45 | 48 |
| Aurora | Modo leve | 35 | 63 |
| Os dois | Sem animação (referência) | 113 | 113 |
No Aurora, os frames lentos (abaixo de 30 fps) no modo leve caíram de 23,5% para 2,2%. E agora o modo leve é, de fato, mais leve que tudo ligado.
Uma lição de método: intercale as rodadas. Rodando um cenário depois do outro, o mesmo teste deu 28 fps numa bateria e 57 na seguinte, só por variação da máquina. Alternando os cenários a cada rodada, os números ficaram estáveis, e a linha "sem animação", que não mudou de código, serve de controle.
SEO técnico
O básico, que todo site deveria ter:
- Metadados por página: título e descrição próprios em cada página, projeto e post.
- Canonical e
hreflang: o site é bilíngue, e cada página diz qual é a versão em português e qual é a em inglês, para o Google mostrar a certa. - Sitemap e robots.txt gerados automaticamente.
- Imagem de compartilhamento (OG) por idioma, para o link ficar bonito no LinkedIn.
Uma pegadinha do domínio: o www.iagogois.com.br redireciona para iagogois.com.br, mas por um momento o sitemap apontava para o www. O Google prefere a URL final, sem redirecionamento, então fixei o domínio principal no código.
Dados estruturados
São blocos invisíveis em JSON-LD que dizem às máquinas o que é a página: uma pessoa (Person), um site (WebSite), uma lista de projetos e cada post (BlogPosting).
O Schema Markup Validator encontrou os blocos com 0 erros e 0 avisos. O Rich Results Test faz uma checagem parecida do ponto de vista do Google, mas pede login com conta Google.
SEO para IAs
Cada vez mais gente pergunta para o ChatGPT, o Claude ou o Perplexity em vez de pesquisar no Google. Para aparecer nessas respostas, o site precisa ser fácil de ler por uma IA:
- Conteúdo renderizado no servidor: o HTML já chega com todo o texto, sem depender de JavaScript.
- llms.txt: um resumo em Markdown em
/llms.txt, com quem sou, projetos e links, no formato que modelos de linguagem leem. Existe também a versão completa em/llms-full.txt. - robots.txt liberando os robôs de IA, como GPTBot, ClaudeBot e PerplexityBot.
- Dados estruturados: os mesmos que ajudam o Google ajudam as IAs a entender quem é quem.
Na categoria Agentic Browsing do Lighthouse, o celular fez 3/3.
Search Console
O Google Search Console é onde o Google conta o que vê do seu site: quais páginas indexou, que buscas trouxeram visitas e o que deu erro. Para configurar:
- Entre no Search Console e adicione uma propriedade de domínio (
iagogois.com.br). Ela cobrewww,httpe todas as páginas. - O Google mostra um registro TXT. Crie esse registro no DNS do domínio (no meu caso, no Registro.br).
- Volte e clique em Verificar. Pode levar alguns minutos.
- Envie o sitemap:
https://iagogois.com.br/sitemap.xml.
Os dados começam a aparecer em alguns dias. Volto aqui com os números quando tiver.
Checklist para qualquer site
- Rodar o Lighthouse 3 vezes e usar a mediana
- Rodar o PageSpeed Insights no celular e no desktop
- Olhar o console do navegador em produção, não só no local
- Testar com o servidor e o navegador em fusos diferentes
- Conferir contraste de texto sobre a cor de destaque (mínimo 4,5:1)
- Usar
scrollbar-gutter: stablese a página trava a rolagem em algum momento - Medir a fluidez da rolagem, não só o carregamento
- Pausar animações infinitas fora da tela
- Título, descrição e canonical em cada página
-
hreflangse o site tiver mais de um idioma - Sitemap e robots.txt
- Dados estruturados validados no Schema Markup Validator
-
llms.txte robots.txt liberando os robôs de IA - Search Console com propriedade de domínio e sitemap enviado
O que ainda falta
- LCP no celular (3,5 s): fazer o título principal aparecer sem esperar a animação.
- JavaScript inicial no celular: é o maior custo de tempo de bloqueio.
- Dados reais de visitantes: os números acima são de laboratório. Com tráfego, o PageSpeed passa a mostrar a experiência de quem visita de verdade.