Gerar PDF com Claude Code: faturas e relatórios usando Playwright
Implemente PDF com Claude Code: Playwright, CSS de impressão, fontes, faturas, relatórios e testes visuais.
Um botão “baixar PDF” parece simples até o documento ser usado por clientes. Uma fatura precisa de valores corretos, impostos, margens, tabela legível e total que não seja cortado. Um relatório mensal combina texto, imagens, gráficos e recomendações. Um certificado precisa manter nome, data, ID e layout confiável quando for impresso.
O caminho mais prático para times web é HTML-to-PDF com renderização real de navegador. Você monta o documento em HTML, controla papel e impressão com CSS, renderiza no Chromium e exporta com Playwright ou Puppeteer. Claude Code ajuda bastante, mas o prompt precisa especificar formato de página, margens, fontes, fundos, quebras, verificação visual e o que deve ser evitado. Sem isso, ele pode gerar um exemplo frágil com canvas ou coordenadas manuais.
Use fontes oficiais para validar detalhes: page.pdf do Playwright, PDF generation e PDFOptions do Puppeteer, @page e CSS de impressão na MDN, além do Claude Code overview. Para contexto interno, leia também automação de planilhas, testes Playwright e estratégias de teste.
Por que começar com HTML-to-PDF
Existem três abordagens comuns. Com jsPDF, você desenha textos e linhas por coordenadas. É aceitável para etiquetas simples, mas difícil para faturas com várias seções. Com screenshot ou canvas, você transforma o documento em imagem. A primeira revisão pode parecer boa, mas o texto fica ruim para busca, cópia, zoom, acessibilidade e regressão visual.
HTML-to-PDF usa ferramentas que desenvolvedores web já conhecem. Tabelas continuam tabelas, títulos continuam títulos e @page controla o papel. Antes de exportar, você pode abrir o HTML de impressão no navegador e comparar screenshots. Para Claude Code, isso também melhora a revisão: ele edita HTML, CSS, scripts Node e testes Playwright.
flowchart TD
A["Dados de negócio"] --> B["Template HTML"]
B --> C["CSS de impressão e @page"]
C --> D["Renderização Chromium"]
D --> E["Arquivo PDF"]
C --> F["Comparação de screenshot"]
F --> G["Evidência de revisão"]
Casos de uso reais
O primeiro caso é a fatura. Ela exige fornecedor, cliente, itens, imposto, total, vencimento e número estável. Os bugs perigosos são arredondamento errado, imposto faltando, fundo da tabela ausente e total empurrado para outra página.
O segundo caso é o relatório mensal. SEO, mídia paga, SaaS e vendas misturam resumo, tabelas, capturas e gráficos. O fluxo de página importa: um título não deve ficar sozinho no fim da folha, e um gráfico não deve se separar da explicação.
O terceiro caso é o certificado. Nome, curso, data, ID, logo e QR code geralmente cabem em uma página. Mantenha texto importante como HTML e use imagens apenas para logo, assinatura ou QR.
O quarto caso é o relatório de auditoria. Permissões, deploys, aprovações e incidentes precisam ser rastreáveis. Coloque data de geração, ambiente, versão do app e ID da fonte de dados no rodapé.
Prompt para Claude Code
Implemente geração de PDF.
Direção:
- Renderizar um template HTML com Playwright Chromium e exportar PDF.
- Não transformar o documento inteiro em uma imagem canvas.
- Usar A4 retrato, margem de 14mm, fundos visíveis e CSS de impressão.
- Usar uma pilha de fontes compatível com português, inglês e japonês.
- Manter estrutura reutilizável para faturas, relatórios e certificados.
Implementação:
- Adicionar scripts/create-invoice-pdf.mjs.
- Gerar out/invoice-BR-2026-0602.pdf com dados de exemplo.
- Formatar dinheiro com Intl.NumberFormat.
- Escapar texto de usuário antes de inserir no HTML.
- Usar printBackground e preferCSSPageSize em page.pdf.
Verificação:
- Documentar o comando de execução.
- Permitir comparação por screenshot do HTML de impressão.
- Conferir fontes, quebras, fundos e total.
Código executável
npm init -y
npm pkg set type=module
npm i -D playwright
npx playwright install chromium
mkdir scripts out
node scripts/create-invoice-pdf.mjs
import { chromium } from "playwright";
import { mkdir } from "node:fs/promises";
import { dirname, resolve } from "node:path";
const outputPath = resolve("out/invoice-BR-2026-0602.pdf");
const money = new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" });
const invoice = {
number: "BR-2026-0602",
buyer: "Exemplo Digital Ltda.",
seller: "Masa Design Lab",
issuedAt: "2026-06-02",
items: [
{ name: "Design do template PDF", quantity: 1, unitPrice: 4000 },
{ name: "Script Playwright de geração", quantity: 1, unitPrice: 6000 },
{ name: "CSS de impressão e verificação de fontes", quantity: 1, unitPrice: 3000 },
],
};
function escapeHtml(value) {
return String(value).replace(/[&<>"']/g, (char) => ({
"&": "&", "<": "<", ">": ">", '"': """, "'": "'",
})[char]);
}
function renderHtml(data) {
const subtotal = data.items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 0);
const tax = Math.round(subtotal * 0.12);
const rows = data.items.map((item) => `<tr>
<td>${escapeHtml(item.name)}</td>
<td class="num">${item.quantity}</td>
<td class="num">${money.format(item.unitPrice)}</td>
<td class="num">${money.format(item.quantity * item.unitPrice)}</td>
</tr>`).join("");
return `<!doctype html><html lang="pt-BR"><head><meta charset="utf-8">
<style>
@page { size: A4; margin: 14mm; }
body { font-family: "Noto Sans", Arial, sans-serif; color: #202124; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
header { display: flex; justify-content: space-between; border-bottom: 3px solid #1f5eff; padding-bottom: 14px; }
h1 { margin: 0; font-size: 28px; }
table { width: 100%; border-collapse: collapse; margin-top: 24px; }
th { background: #eef3ff; text-align: left; }
th, td { border-bottom: 1px solid #d7dce5; padding: 10px 8px; }
.num { text-align: right; white-space: nowrap; }
.total { margin-left: auto; width: 260px; margin-top: 20px; font-size: 18px; font-weight: 700; }
.avoid-break { break-inside: avoid; page-break-inside: avoid; }
</style></head><body>
<header><h1>Fatura</h1><div>Número: ${escapeHtml(data.number)}<br>Data: ${escapeHtml(data.issuedAt)}</div></header>
<p><strong>Cliente:</strong> ${escapeHtml(data.buyer)}</p>
<p><strong>Fornecedor:</strong> ${escapeHtml(data.seller)}</p>
<table><thead><tr><th>Item</th><th class="num">Qtd.</th><th class="num">Preço</th><th class="num">Valor</th></tr></thead><tbody>${rows}</tbody></table>
<div class="total avoid-break">Total: ${money.format(subtotal + tax)}</div>
</body></html>`;
}
await mkdir(dirname(outputPath), { recursive: true });
const browser = await chromium.launch();
try {
const page = await browser.newPage();
await page.setContent(renderHtml(invoice), { waitUntil: "networkidle" });
await page.evaluate(() => document.fonts.ready);
await page.emulateMedia({ media: "print" });
await page.pdf({ path: outputPath, printBackground: true, preferCSSPageSize: true, margin: { top: "0", right: "0", bottom: "0", left: "0" } });
console.log(`Created ${outputPath}`);
} finally {
await browser.close();
}
Falhas comuns e verificação
As falhas mais comuns são PDF como imagem única, printBackground ausente, fonte que existe no notebook mas não no Linux de CI, logo externo carregando tarde, texto de cliente sem escape e nota longa quebrando a página. Peça ao Claude Code para reproduzir o caso e corrigir com a menor mudança possível.
Verifique mais que a existência do arquivo. Teste o cálculo do total, abra a rota imprimível, aplique page.emulateMedia({ media: "print" }) e salve screenshot com Playwright. Rode casos curto, longo, sem logo e com texto multilíngue.
CTA e resultado verificado
PDF é um tema monetizável porque vira entrega concreta: faturas, relatórios, certificados, checklists e materiais para clientes. Comece pelo material gratuito de Claude Code, use produtos ClaudeCodeLab para templates repetíveis e veja treinamento ou consultoria se sua equipe quer integrar geração, revisão e Playwright no repositório.
Este fluxo foi verificado localmente com Node.js, Playwright Chromium e dados de fatura. O ponto mais útil foi tratar o HTML de impressão como superfície testável. Na prática de Masa, fontes, fundos ausentes e quebras de página são problemas mais frequentes do que erro de sintaxe.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Workflow Obsidian para CLAUDE.md com Claude Code
Transforme notas de trabalho do Obsidian em notas operacionais CLAUDE.md para preservar contexto.
Claude Code Revenue CTA Routing: artigos para PDF, Gumroad e consultoria
Um fluxo com Claude Code para levar leitores ao PDF grátis, Gumroad ou consultoria conforme intenção.
Regras de handoff para equipes com Claude Code: evidências, permissões, rollback e receita
Formato prático para entregar trabalho do Claude Code com prova, permissões, rollback, PDF grátis, Gumroad e consultoria.