Este portfólio é, ele mesmo, um projeto de portfólio. Ele tem 4 temas completos, efeitos de movimento, sons, easter eggs e um debugger público: um painel onde qualquer pessoa liga, desliga e ajusta cada efeito para ver como o site funciona por dentro. Aperte ⇧D e teste.
Este post é vivo: a cada mudança relevante no site, ele é atualizado. O histórico está no fim, em Changelog.
Resumo
- Stack: Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS 4, GSAP 3 e Lenis.
- Deploy: Vercel, com deploy automático a cada push no GitHub.
- Performance (celular, PageSpeed Insights): 82 de performance, 92 de acessibilidade, 96 de boas práticas e 100 de SEO, antes dos ajustes descritos abaixo.
- Acessibilidade: respeita
prefers-reduced-motion, tem modo leve no celular e chegou a 100 no Lighthouse depois de 3 correções. - IA: construído em par com o Claude Code. Eu decidi o quê e por quê; a IA implementou, mediu e encontrou bugs comigo.
A ideia
Um portfólio de dev precisa mostrar duas coisas: o que você entrega e o seu nível técnico. O próprio site é a prova do segundo ponto.
O risco de um site cheio de animação é parecer júnior: muito efeito, pouco critério. Por isso cada tema escolhe 2 ou 3 efeitos-assinatura e executa bem, em vez de ligar tudo ao mesmo tempo. E todo efeito pode ser desligado, porque quem visita controla a experiência.
Os 4 temas
| Tema | Personalidade | Efeitos-assinatura |
|---|---|---|
| Editorial | Revista de design: serifa gigante, papel e respiro | Text reveal por linha, lista com imagem no cursor, grain |
| Terminal | Tudo mono, fósforo verde | Text scramble, terminal escondido, scanlines |
| Aurora | Vidro, shader e luz | Shader no fundo, spotlight e tilt nos cards, scroll horizontal pinado |
| Bauhaus | Grid suíço e formas primárias | Cards empilhados, marquee rápido, botões magnéticos |
Cada tema tem modo claro e escuro, fonte própria e até um som próprio: papel no Editorial, 8-bit no Terminal, vidro no Aurora e madeira no Bauhaus.
Stack
| Camada | Escolha | Por quê |
|---|---|---|
| Framework | Next.js 16 (App Router, Cache Components) | Páginas geradas no build, servidas pela CDN; SEO e primeiro paint rápidos |
| UI | React 19 + TypeScript | Componentes tipados de ponta a ponta |
| Estilo | Tailwind CSS 4 + tokens em CSS | Cada tema é um conjunto de variáveis; trocar de tema não recarrega nada |
| Animação | GSAP 3 (ScrollTrigger, SplitText, ScrambleText) | Timeline precisa, scroll-driven e velocidade global controlável |
| Scroll | Lenis | Scroll suave sem quebrar position: sticky nem o scroll nativo |
| Estado | Zustand | Uma config única (tema, efeitos, sons) salva no navegador |
| Som | Web Audio API | Todos os sons são sintetizados: zero arquivos de áudio |
| Fundo | WebGL puro | Um shader leve, sem Three.js, renderizado em baixa resolução |
| Deploy | Vercel | Deploy por push, preview por branch, CDN global |
Arquitetura em uma frase
Uma config (tema, modo, efeitos, layout, sons) vive num store; todo efeito passa por um hook, useFx(), que combina essa config com prefers-reduced-motion e com o modo leve do celular antes de animar qualquer coisa.
Isso dá três garantias:
- Nenhum efeito ignora a acessibilidade: se o sistema pede movimento reduzido, nada se mexe.
- O celular recebe uma versão leve: cursor, magnetismo, tilt, shader e smooth scroll ficam de fora em telas pequenas ou touch.
- O debugger é só uma interface para a config: cada controle muda um valor, e cada valor tem um botão para voltar ao padrão do tema.
Deploy
O código fica no GitHub e a Vercel faz o deploy a cada push no main. As páginas são geradas no build e servidas da CDN; na primeira medição, o HTML da home respondia direto do cache da borda.
O site é bilíngue: /pt e /en. Um proxy (o novo nome do middleware no Next 16) olha a língua do navegador: qualquer variação de português vai para /pt, qualquer outra língua vai para /en. Se você escolher um idioma no seletor (o ícone 文A), essa escolha vale nas próximas visitas.
Performance: medida, não opinião
As primeiras medições foram feitas no site em produção, logo após o primeiro deploy:
| Ferramenta | Performance | Acessibilidade | Boas práticas | SEO |
|---|---|---|---|---|
| PageSpeed Insights, celular | 82 | 92 | 96 | 100 |
| Lighthouse local, desktop (mediana de 3) | 85 | 92 | 96 | 100 |
O Lighthouse só mede o carregamento. Num site com animação, o que importa também é a fluidez durante o uso, então escrevi um teste que abre o site no Chrome e rola até o fim medindo cada frame:
| Cenário | FPS médio | Frames lentos (abaixo de 30 fps) |
|---|---|---|
| Desktop | 84 | 1,7% |
| Celular simulado, CPU 4x mais lenta | 36 | 29% |
O que essas medições mudaram:
- Preloader de 1,6 s para 0,4 s. Ele segurava o LCP (o título do hero) por mais de 3 segundos no celular.
- Erro de hidratação corrigido. As datas do blog eram formatadas no fuso do servidor (UTC) e do navegador (UTC−3), e o React via dias diferentes. Só aparecia em produção, e foi o Lighthouse que acusou.
- Próximo passo: reduzir o JavaScript inicial no celular, onde o tempo de bloqueio ainda é o maior custo.
Acessibilidade
prefers-reduced-motioné respeitado por padrão, e o debugger permite simular isso para testar.- O modo leve desliga os efeitos pesados em telas pequenas e touch.
- O Lighthouse apontou 3 problemas, todos corrigidos: contraste de um atalho no debugger,
aria-labelem parágrafos divididos pelo SplitText e nomes acessíveis que não batiam com o texto visível. Resultado: 100 em acessibilidade.
Como a IA entrou no processo
O site foi construído em par com o Claude Code, o agente de programação da Anthropic. A divisão foi clara:
- Eu decidi: os temas, o que fica e o que sai, o debugger ser público, o tom dos textos, o que é brega (o selo de "disponível para projetos" saiu por isso).
- A IA implementou e verificou: escreveu o código, rodou build, lint e type-check a cada etapa, abriu o site num navegador para conferir e mediu performance.
- Os bugs mais interessantes apareceram nessa verificação, não no código em si (veja abaixo).
A lição: IA acelera muito a execução, mas qualidade continua sendo uma decisão. O critério, o "isso está bom o suficiente?", fica com quem assina o trabalho.
Bugs que valeram a pena
- Shader cinza. O efeito do React rodava duas vezes em dev (Strict Mode) e a limpeza destruía o contexto WebGL do mesmo canvas. Solução: liberar os recursos sem matar o contexto.
- Página travada no celular. O Lenis era criado no primeiro render, destruído quando o modo leve ligava e, logo depois, "parado" numa instância já destruída, o que travava o scroll. Solução: ignorar instâncias que não são mais a atual.
- Temas vazando. Os cards de prévia do debugger herdavam regras do tema ativo da página. Solução: regras de tema que respeitam o tema mais próximo.
- Datas trocadas. O erro de hidratação por fuso horário descrito acima.
O que vem pela frente
- Conteúdo real: projetos, cases com números, depoimentos.
- Menos JavaScript inicial no celular.
- Dados reais de visitantes com Vercel Speed Insights.
Changelog
- 16/10/2026: versão em inglês com detecção automática de idioma, SEO para buscadores e IAs, este post (com badges clicáveis para cada ferramenta citada).
- 15/10/2026: primeiro deploy na Vercel, medições de performance, preloader de 0,4 s, correção de hidratação, acessibilidade 100, debugger seguindo o tema.
- 15/10/2026: sons sintetizados por tema, easter eggs com destaque, reset por opção, seletor de cor próprio.
- 14/10/2026: primeira versão: 4 temas, efeitos, debugger público, paleta ⌘K e terminal escondido.