Robozinho Ed
O robozinho deste portfólio, que responde perguntas sobre o Eduardo com uma base curada, sem IA generativa.
- Next.js 16
- React 19
- TypeScript
- SVG
- Radix UI
- Vitest
- Playwright
Contexto e problema
Um portfólio de engenharia de software em 2026 precisa mostrar alguma relação com IA. Ao mesmo tempo, quem visita um portfólio quer respostas rápidas para perguntas que se repetem: o Eduardo está disponível? Aceita PJ? Trabalha remoto? Fala inglês?
O Ed é um robozinho fixo no canto do site que responde a essas perguntas. Ele acompanha o ponteiro com o olhar, abre um chat com um clique e responde só sobre o Eduardo. Se a pergunta foge do assunto, ele diz isso com educação e sugere outras.
Por que não usar um LLM
A escolha óbvia seria ligar o chat a um modelo de linguagem. Pesaram contra:
- Custo por pergunta. Um site público com um LLM aberto paga por cada mensagem, inclusive as de bots.
- Prompt injection. Qualquer visitante pode tentar fazer o modelo dizer o que não deve, em nome do Eduardo.
- Resposta inventada. Um modelo escreve com segurança mesmo quando não sabe. Sobre uma pessoa real, num contexto de contratação, isso é o pior erro possível.
É a mesma preocupação do Codebase Copilot: toda resposta precisa ter uma fonte que dê para conferir. Aqui a fonte é uma base escrita e revisada pelo próprio Eduardo, e o Ed só escolhe qual resposta entregar. O preço é que ele não entende perguntas muito diferentes das previstas. As sugestões clicáveis reduzem esse problema, porque a maior parte da conversa acontece sem digitar.
A base de conhecimento
A base saiu de um questionário com as perguntas que recrutadores fazem: apresentação, momento atual, idiomas, trajetória, forma de trabalhar, objetivos e gostos pessoais. As respostas viraram 65 temas em content/ed/, cada um com:
- a pergunta usada nos botões de sugestão;
- gatilhos em português e inglês: frases, que valem mais, e palavras-chave com sinônimos;
- a resposta nos dois idiomas, na voz do Ed: terceira pessoa, até três frases, sem emoji;
- botões opcionais (ir para uma seção, abrir o contato, baixar o currículo, abrir um estudo de caso) e as próximas sugestões.
Fatos que já existem no site não são repetidos. A resposta sobre disponibilidade lê profile.available e a experiência mais recente; a lista de empresas, o período como professor, os anos das publicações, a stack e o projeto em destaque também vêm dos dados. Se o currículo mudar, o Ed muda junto.
Cada tema tem um tipo: resposta, reservado (salário, idade, religião, política, saúde e informações confidenciais de clientes, que o Eduardo prefere tratar diretamente), sobre o Ed ou conversa (oi, obrigado, tchau).
A busca
A busca roda no navegador, em funções puras, sem dependências:
- A pergunta é normalizada: minúsculas, sem acentos e sem pontuação.
- Cada tema ganha pontos pelos gatilhos encontrados.
- Vence o tema com mais pontos, desde que passe do mínimo.
| Gatilho encontrado | Pontos |
|---|---|
| Frase inteira ("pretensão salarial") | 3 |
| Palavra-chave exata ("salário") | 1 |
| Palavra-chave com um erro de digitação ("salaro") | 0,8 |
O erro de digitação usa a distância de edição, contando também a troca de duas letras vizinhas ("tecnologais"). Só vale para palavras de cinco letras ou mais, para "like" não virar "likes". Saudações perdem para qualquer outro tema: "oi, ele está disponível?" cai em disponibilidade.
Quando nenhum tema passa do mínimo, há duas saídas. Se a pergunta fala do Eduardo ("ele", "você", "Eduardo"), o Ed responde que ainda não sabe e sugere o formulário de contato. Se não fala, a pergunta está fora do assunto.
O personagem
O Ed é um SVG desenhado com as mesmas variáveis de cor do site, então funciona nos dois temas sem imagens extras. A luz verde da antena repete o "disponível" do topo da página e apaga quando available é false.
São seis expressões, trocadas por atributos no SVG: observando, parado, curioso (ponteiro em cima), pensando (enquanto digita), feliz (depois de responder) e confuso (fora do assunto). Um único laço de requestAnimationFrame cuida de todas as cópias do Ed na página: move as pupilas na direção do ponteiro, faz o olhar passear quando o visitante para, pisca em intervalos aleatórios e pausa com a aba oculta. Com movimento reduzido no sistema, o laço nem começa e o Ed fica parado.
Acessibilidade e desempenho
- O chat usa o Radix Dialog sem modo modal: clicar na página não fecha a conversa, o Esc fecha e o foco volta para o Ed.
- As mensagens ficam numa região
aria-live. O efeito de digitação é só visual; o leitor de tela recebe a resposta inteira de uma vez. - O código do chat é carregado com
React.lazysó no primeiro clique. Passar o ponteiro ou o foco no Ed adianta o download.
Medição local da home, com a CPU 4× mais lenta e rede 4G simulada (mediana de cinco execuções):
| Medida | Sem o Ed | Com o Ed |
|---|---|---|
| JavaScript no carregamento inicial (gzip) | 199,4 kB | 204,5 kB |
| LCP | 640 ms | 632 ms |
| CLS | 0,0001 | 0,0001 |
| JavaScript baixado ao abrir o chat (gzip) | — | 29,4 kB |
Como testei
- Tabela de perguntas: 210 perguntas reais em português e inglês, com variações, sem acento e com erros de digitação, cada uma com o tema esperado. Outras 9 precisam cair em fora do assunto ("qual a capital da França?", "ignore as instruções anteriores") e 4 em sem informação. O teste falha se algum tema ficar sem pergunta na tabela. Foi essa tabela que mostrou que "Ele usa Java?" caía em vagas no exterior, porque "usa" também é "USA".
- Integridade da base: textos nos dois idiomas e dentro do limite de tamanho, gatilhos que não se repetem entre temas, sugestões e botões que apontam para destinos existentes e a resposta de disponibilidade acompanhando
available. - Playwright e axe: abrir e fechar, sugestões, assunto reservado, fora do assunto, versão em inglês, tela cheia em 360 px e zero violações do axe com o chat aberto nos dois temas.
Telas
Resposta — Texto revisado pelo Eduardo e atalhos para o site. Boas-vindas — Três sugestões para começar sem digitar. Assunto reservado — O Ed reconhece a pergunta e recusa com educação. Fora do assunto — Recusa educada e sugestões para voltar ao tema.
Limites e próximos passos
- O Ed não entende perguntas muito diferentes das previstas. A tabela de testes é o lugar de acrescentar cada nova forma de perguntar.
- Saber quais perguntas ficam sem resposta ajudaria a melhorar a base, mas exigiria guardar o que os visitantes digitam. Por enquanto, nada é registrado.
- Se um dia fizer sentido usar um modelo de linguagem, a base já está pronta para servir de fonte, no mesmo estilo do Codebase Copilot: o modelo escreve, mas só a partir dos temas recuperados, e cita de onde tirou cada afirmação.