Use Cases (Mis à jour: 02/06/2026)

Générer des PDF avec Claude Code : factures et rapports avec Playwright

Implémentez la génération PDF avec Claude Code, Playwright, CSS print, polices, factures, rapports et tests visuels.

Générer des PDF avec Claude Code : factures et rapports avec Playwright

Un bouton “Télécharger en PDF” paraît simple, jusqu’au moment où le document part chez un client. Une facture doit contenir des montants justes, une taxe correcte, des marges stables, un tableau lisible et un total qui ne disparaît pas entre deux pages. Un rapport mensuel combine souvent texte, tableaux, captures, graphiques et recommandations. Un certificat doit rester propre à l’écran comme à l’impression.

L’approche la plus robuste pour une équipe web est HTML-to-PDF avec un vrai moteur de navigateur. On construit le document en HTML, on écrit un CSS d’impression, puis Chromium le rend et l’exporte en PDF via Playwright ou Puppeteer. Claude Code peut générer cette base rapidement, à condition de lui donner des contraintes de document imprimable : format A4, marges, polices, couleurs de fond, sauts de page, vérification visuelle et cas d’échec. Sinon il risque de produire un exemple fragile basé sur un canvas ou sur des coordonnées manuelles.

Les références officielles à garder ouvertes sont page.pdf pour Playwright, PDF generation et PDFOptions pour Puppeteer, @page et le CSS d’impression sur MDN, ainsi que le Claude Code overview. Pour le contexte ClaudeCodeLab, combinez cet article avec l’automatisation de tableurs, les tests Playwright et les stratégies de test.

Pourquoi commencer par HTML-to-PDF

Trois stratégies reviennent souvent. Avec une bibliothèque bas niveau comme jsPDF, on dessine du texte et des traits à des positions fixes. C’est acceptable pour une petite étiquette, mais une facture devient vite une suite de coordonnées. Avec une approche image ou canvas, on colle une capture dans le PDF. Le premier rendu peut sembler correct, mais le texte devient difficile à rechercher, le fichier grossit et la régression visuelle est pénible.

HTML-to-PDF garde le document dans un modèle connu des développeurs web. Les tableaux restent des tableaux, les titres restent des titres et @page contrôle le papier. On peut ouvrir le HTML imprimable avant l’export, faire une capture Playwright et comparer les changements. Claude Code travaille alors sur des fichiers HTML, CSS, Node et tests, ce qui rend la revue beaucoup plus claire.

flowchart TD
  A["Données métier"] --> B["Modèle HTML"]
  B --> C["CSS print et @page"]
  C --> D["Rendu Chromium"]
  D --> E["PDF"]
  C --> F["Comparaison screenshot"]
  F --> G["Preuve de revue"]

Cas d’usage concrets

Le premier cas est la facture. Elle exige vendeur, client, lignes, TVA, total, échéance et numéro stable. Les bugs dangereux sont un arrondi faux, une taxe oubliée, une couleur de tableau absente ou un total coupé par un saut de page.

Le deuxième cas est le rapport mensuel. SEO, publicité, produit SaaS ou ventes : le document mélange résumé, tableaux, captures et graphiques. Il faut éviter qu’un titre reste seul en bas de page ou qu’un graphique soit séparé de son explication.

Le troisième cas est le certificat. Nom, formation, date, ID, logo et QR code tiennent souvent sur une page. Gardez les informations importantes en texte HTML et réservez les images aux logos, signatures et codes QR.

Le quatrième cas est le rapport d’audit interne. Permissions, déploiements, validations et incidents doivent être traçables. Ajoutez date de génération, environnement, version de l’application et identifiant de source dans le pied de page.

Prompt pour Claude Code

Implémente une génération PDF.

Direction:
- Rendre un modèle HTML avec Playwright Chromium et exporter en PDF.
- Ne pas transformer tout le document en une seule image canvas.
- Utiliser A4 portrait, marges 14mm, fonds visibles et CSS print.
- Prévoir une pile de polices compatible latin et japonais.
- Garder une structure réutilisable pour factures, rapports et certificats.

Implémentation:
- Ajouter scripts/create-invoice-pdf.mjs.
- Générer out/invoice-FR-2026-0602.pdf depuis des données d’exemple.
- Formater les montants avec Intl.NumberFormat.
- Échapper les textes utilisateur avant insertion HTML.
- Utiliser printBackground et preferCSSPageSize dans page.pdf.

Vérification:
- Documenter la commande.
- Rendre le HTML imprimable comparable par screenshot.
- Vérifier polices, sauts, fonds et total.

Code exécutable

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-FR-2026-0602.pdf");
const money = new Intl.NumberFormat("fr-FR", { style: "currency", currency: "EUR" });

const invoice = {
  number: "FR-2026-0602",
  buyer: "Exemple Numérique SAS",
  seller: "Masa Design Lab",
  issuedAt: "2026-06-02",
  items: [
    { name: "Conception du modèle PDF", quantity: 1, unitPrice: 800 },
    { name: "Script de génération Playwright", quantity: 1, unitPrice: 1200 },
    { name: "CSS print et vérification des polices", quantity: 1, unitPrice: 600 },
  ],
};

function escapeHtml(value) {
  return String(value).replace(/[&<>"']/g, (char) => ({
    "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;",
  })[char]);
}

function renderHtml(data) {
  const subtotal = data.items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 0);
  const tax = Math.round(subtotal * 0.2);
  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="fr"><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>Facture</h1><div>Numéro: ${escapeHtml(data.number)}<br>Date: ${escapeHtml(data.issuedAt)}</div></header>
  <p><strong>Client:</strong> ${escapeHtml(data.buyer)}</p>
  <p><strong>Fournisseur:</strong> ${escapeHtml(data.seller)}</p>
  <table><thead><tr><th>Poste</th><th class="num">Qté</th><th class="num">Prix</th><th class="num">Montant</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();
}

Échecs fréquents et contrôle

Les échecs typiques sont connus : document converti en image unique, printBackground oublié, polices absentes en CI Linux, logo externe non chargé, texte client non échappé, ou longue note qui pousse le total sur une nouvelle page. Demandez à Claude Code de reproduire le cas et de corriger avec le plus petit changement possible.

Ne vous contentez pas de vérifier que le fichier existe. Testez le calcul des montants, ouvrez la route imprimable, appliquez page.emulateMedia({ media: "print" }) et gardez une capture Playwright. Testez aussi un document court, un document long, un logo manquant et un texte multilingue.

CTA et résultat vérifié

La génération PDF est monétisable car elle touche des livrables concrets : factures, rapports, certificats, checklists et documents clients. Commencez par la ressource gratuite Claude Code, utilisez les produits ClaudeCodeLab pour des modèles réutilisables, et passez à la formation ou consultation si votre équipe veut intégrer génération, revue et tests Playwright dans son dépôt.

Pour cet article, j’ai vérifié le flux avec Node.js local, Chromium Playwright et une facture d’exemple. L’amélioration la plus utile est de traiter le HTML imprimable comme une surface de test. Dans les projets de Masa, les problèmes les plus fréquents ne sont pas les erreurs de syntaxe, mais les polices, les fonds disparus et les sauts de page non relus.

#Claude Code #PDF generation #jsPDF #Puppeteer #reports
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.