Voltar para artigos
CategoriaDemo

Como criei uma ferramenta para adaptar currículo usando o método oficial de Harvard

25 de agosto de 2026
Tags
Inteligência ArtificialProdutividadeFrontendCarreiraOpen Source
Como criei uma ferramenta para adaptar currículo usando o método oficial de Harvard

Hero

Tempo estimado de leitura: 5 min

Olha pra tela inicial do ResumeTailor: de cara você vê dois cards bem diretos no topo, um pra colocar o seu currículo (ou clicar em exportar o teu LinkedIn como PDF e subir o arquivo) e outro pra colar a descrição da vaga de trabalho. Logo abaixo, o painel de resultados monta o documento final em tempo real, exibindo os badges com o modelo utilizado e a duração exata de cada etapa.

E muita atenção aqui: esta não é uma ferramenta feita pra criar currículo genérico pra você sair disparando por aí. Não mesmo. O ResumeTailor foi desenhado usando o manual oficial da Harvard para reescrever o seu histórico com foco total em uma vaga específica. É esse o objetivo.

O problema

Mandar o mesmo PDF para cinquenta vagas diferentes é a receita perfeita para ser ignorado em dez segundos. Filtros ATS e recrutadores leem o documento procurando o vocabulário exato da vaga, e se você aplicou para analista de dados com um texto de backend, seu perfil vira ruído na triagem.

E tem outra: muita gente cai na ilusão de que currículo bom é currículo quilométrico. Não é. O mercado lá fora quer ver longevidade e foco no que realmente interessa para a posição, não uma lista infinita de tudo o que você tocou nos últimos dez anos. Só que sentar na frente do computador e reescrever cada linha do histórico na mão a cada candidatura consome horas de um trabalho chato pra caramba.

Aí a galera apela: joga tudo num prompt genérico do ChatGPT. O resultado é péssimo, com a IA inventando números, criando ferramentas que você nunca usou e cuspindo um texto vazio de marketing que qualquer recrutador fareja de longe.

A solução

Para resolver isso, criei o ResumeTailor: uma aplicação focada em pegar o seu histórico e alinhar cada linha às diretrizes do manual oficial de carreiras de Harvard.

O fluxo é direto. Você vai pegar o seu currículo ou clicar em exportar o teu LinkedIn como PDF, postar na ferramenta, colar a descrição da vaga com os dados da empresa e aí sim gerar o documento adaptado junto com a cover letter.

E muita atenção aqui: ela não inventa fatos. Existe um contrato rígido de grounding no prompt que proíbe o modelo de inventar empresas, métricas ou títulos que você não tem. É a verdade da sua carreira, mas no vocabulário exato da vaga.

Você já pode rodar seus testes direto na aba de ferramentas do meu site. É esse o objetivo.

Funcionalidades

Pra fazer a mágica acontecer na prática, estruturei o app com recursos bem diretos ao ponto:

  • Entrada flexível de dados: você pode colar o texto na mão ou simplesmente arrastar um PDF. Se você for no seu perfil do LinkedIn e clicar em exportar como PDF, a ferramenta extrai tudo no próprio navegador via PDF.js, sem mandar teu arquivo pra servidor nenhum.
  • Pipeline multi-modelo em paralelo: ao clicar em "Gerar todas", o app dispara três chamadas simultâneas via OpenRouter para Sumário, Experiência e Habilidades. Se uma seção der erro, ela não trava o resto, e você ainda pode definir um modelo diferente pra cada bloco.
  • Modo de chamada única: se preferir uma voz idêntica no documento todo, esse botão gera o currículo de ponta a ponta e traz seções extras como Formação, Certificações e Idiomas quando seu histórico original sustenta isso.
  • Carta de apresentação no padrão Harvard: tela dedicada com cinco campos opcionais. E muita atenção aqui: se você deixar a empresa ou o contato em branco, o prompt degrada com elegância em vez de inventar dados inexistentes.
  • Contato editável e PDF limpo: o painel recupera seus links e telefone de forma transparente, permitindo ajustes antes de gerar um PDF A4 no servidor, sem cabeçalhos feios do navegador. É esse o objetivo.

Stack técnica

Pra colocar essa máquina de pé sem backend pesado, fechei a arquitetura com peças bem diretas.

No front-end, a base roda com React 19, TypeScript 6.0 e Vite 8. A casca visual usa Tailwind CSS 4 com componentes do shadcn/ui, somada a animações fluidas do Motion. Quando você sobe teu PDF do LinkedIn, a extração de texto acontece direto na sua máquina usando PDF.js. Zero tráfego desnecessário.

A chamada de IA vai direto do navegador pra API do OpenRouter via streaming. O modelo padrão é o openai/gpt-5.6-sol-pro em esforço máximo de reasoning (max), sem passar por servidor intermediário.

O único pedaço que roda em Node é a rota POST /api/pdf. Criei um plugin customizado pro Vite que converte o markdown com markdown-it e aciona o Puppeteer com Chromium headless pra carimbar o PDF A4 na régua exata. Pra amarrar tudo com segurança, escrevi mais de 840 testes no Vitest checando desde os contratos de prompt XML até os invariantes de cabeçalho.

O desafio mais interessante

O maior pesadelo ao colocar IA pra mexer em currículo é a alucinação descarada. Se você só pede pro modelo "adaptar meu histórico pro manual oficial da Harvard", ele se empolga: troca seus termos por verbos de ação incríveis e inventa do nada que você liderou cinquenta engenheiros ou dobrou faturamento. Mentira pura.

Pra travar esse comportamento, montei um template XML estruturado no padrão goal-first. O arquivo define um contrato de grounding severo e divide a execução do raciocínio em etapas internas obrigatórias antes da emissão da resposta final:

xml
<!-- src/assets/prompt.xml -->
<grounding_contract>
  <rule id="resume" apply="true" />
</grounding_contract>

Exportando PDF perfeito no servidor

Tentar imprimir currículo direto pelo navegador usando window.print() é pedir pra passar raiva. O Chrome insiste em estampar a data no topo, tacha a URL com about:blank no rodapé e ainda consegue enfiar uma folha em branco na primeira página por causa de wrapper CSS da aplicação. Não dá pra mandar um documento assim pra vaga dos seus sonhos.

A saída foi chutar o diálogo do navegador e montar uma rota dedicada. O cliente manda o markdown via POST /api/pdf, um plugin do Vite compila isso num HTML limpo e isolado, e o Puppeteer roda o Chromium em segundo plano pra cuspir um A4 impecável.

typescript
// server/vite-plugin-resume-pdf.ts
import { createPdfMiddleware } from './pdfMiddleware';
import puppeteer from 'puppeteer';

export async function renderA4Pdf(htmlContent: string): Promise<Buffer> {
  const browser = await puppeteer.launch({ headless: 'shell' });
  const page = await browser.newPage();
  await page.setContent(htmlContent, { waitUntil: 'networkidle0' });
  const pdfBuffer = await page.pdf({
    format: 'A4',
    printBackground: true,
    displayHeaderFooter: false,
    margin: { top: '0px', bottom: '0px', left: '0px', right: '0px' }
  });
  await browser.close();
  return Buffer.from(pdfBuffer);
}

A flag displayHeaderFooter: false desliga qualquer sujeira de cabeçalho, enquanto o modo headless: 'shell' reduz o consumo de memória sem exigir a instalação pesada do Chrome inteiro. O contraponto aqui é claro: hospedar só arquivos estáticos num bucket sem servidor quebra a geração do PDF. Pra funcionar em produção, você vai precisar de um runtime Node rodando esse middleware junto com o app. É esse o trade-off.

O que aprendi

Construir essa ferramenta me ensinou quatro coisas bem práticas sobre desenvolvimento com modelos de raciocínio.

Primeiro: o catálogo de verbos de ação de Harvard faz uma diferença brutal. Quando você força o modelo a usar verbos de impacto em vez de enrolar em gerúndio corporativo, o currículo ganha outra postura na hora.

Segundo: prender o app em um único provedor é tiro no pé. Deixar o usuário escolher qualquer modelo pelo catálogo da OpenRouter garante liberdade de custo e velocidade sem engessar o produto.

Terceiro: pedir com educação no prompt não resolve alucinação. Você precisa de contratos explícitos de validação e portões de checagem. Sem regra decidível, o modelo inventa dados.

E por último, raciocínio em esforço máximo exige respeitar o tempo da máquina. Aprendi na marra que requisições comuns morrem pelo caminho se a gente não segurar a conexão via streaming SSE com comentários de keep-alive. Paciência programada.

Experimente!

A ferramenta tá no ar e pronta pra você rodar. Entra lá em https://frederico-kluser.com/tools e procura pelo ResumeTailor.

O teste mais rápido que você pode fazer agora é simples: vai no teu perfil do LinkedIn, clica em exportar como PDF e sobe o arquivo direto na aplicação. Se preferir não mexer nos teus dados logo de cara, sem problema, dá pra carregar os exemplos fictícios prontos na interface. Pega a descrição daquela vaga específica que você tanto quer, joga lá e gera o material.

Testa na prática, me diz o que achou e abre uma issue com sugestões de melhoria no repositório. Se tiver algum colega na busca por recolocação, passa esse post pra ele.

Candidatura genérica vai direto pro lixo; aplicar com foco cirúrgico muda o jogo. É esse o objetivo.