mcpField
W
weasyprint-pdf-creation

weasyprint-pdf-creation

github.com/slapashDocuments645 installsUpdated 25w ago
Repository

About weasyprint-pdf-creation

weasyprint-pdf-creation is a skill for creating new PDFs from HTML/CSS templates with WeasyPrint, for documents such as invoices, reports, and proposals. It emphasizes repeatable rendering and provides checks for pages, text, and visual layout.

Key features

  1. 01Generate PDFs from HTML/CSS templates
  2. 02Inject data with Jinja2
  3. 03Set print styles and page layouts
  4. 04Check render warnings, page count, and extracted text
  5. 05Preview and inspect layout and page breaks

Use cases

  1. 01Create reusable invoice or report templates
  2. 02Format business data as printable documents
  3. 03Check PDF content, pagination, and overlapping elements

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/slapash/weasyprint-pdf-skill --skill weasyprint-pdf-creation

After installing, type/weasyprint-pdf-creationin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

README.md
LICENSE
.gitignore
requirements.txt
data/
sample-one-page-brief.json
sample-report.json
sample-statement.json
sample-invoice.json
sample-receipt.json
sample-proposal.json
docs/
pdf-qa.md
template-rules.md
examples/
index.html
invoice.html
report.html
one-page-brief.html
proposal.html
receipt.html
statement.html
fonts/
README.md
outputs/
.gitkeep
scripts/
build_examples.py
qa_pdf.py
render_pdf.py
templates/
proposal.html
one-page-brief.html
invoice.html
report.html
statement.html
receipt.html

Details

From the project README

WeasyPrint PDF Creation

Overview

Use this skill to create polished PDFs from source-controlled HTML/CSS templates. The core workflow is:

HTML template + print CSS + data → WeasyPrint → PDF → QA → publish/share

This is for new PDFs you own: invoices, reports, proposals, briefs, statements, one-page docs, printable guides, and template-driven business documents.

Do not use this as the default for editing arbitrary existing PDFs or capturing JavaScript-heavy webpages. See the decision table below.

When to Use

Use this skill when the user asks to:

  • create an invoice, report, proposal, brief, contract-style doc, handout, or printable PDF
  • make a reusable PDF template from HTML/CSS
  • generate a better-looking PDF than a markdown/export default
  • publish a PDF preview for review on an artifact shelf/static host
  • test whether a designed document survives print/PDF rendering

Do not use this skill for:

  • editing text in an existing PDF → use nano-pdf/PyMuPDF
  • OCR/extracting text from scans → use OCR/document extraction tooling
  • screenshots or JS-rendered dashboards → use Playwright/Chromium
  • raw programmatic vector drawing → consider ReportLab/SVG/PyMuPDF

Decision Table

NeedTool
New designed invoice/report/doc from templateWeasyPrint
Existing PDF text editnano-pdf / PyMuPDF
JS-heavy webpage or dashboard to PDFPlaywright/Chromium
Extract/OCR a PDFOCR/document tools
Low-level PDF surgery/merge/splitpikepdf / PyMuPDF

Recommended Repo Shape

pdf-project/
  templates/
    invoice.html
    report.html
    proposal.html
    one-page-brief.html
    receipt.html
    statement.html
  styles/
    print.css
  data/
    sample-invoice.json
    sample-report.json
    sample-proposal.json
  scripts/
    render_pdf.py
    qa_pdf.py
  outputs/
    .gitkeep
  examples/
    index.html
    invoice.pdf
    invoice.png
  docs/
    pdf-qa.md
    template-rules.md
  fonts/
    README.md
  requirements.txt
  README.md

Keep templates boring to run and tasteful to look at:

  • semantic HTML
  • print-first CSS
  • no required JavaScript
  • local assets/fonts where possible
  • data injection separated from layout
  • source-controlled sample JSON
  • deterministic generated output

Install

Python venv
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
python -m weasyprint --info

requirements.txt minimum:

weasyprint==68.1
Jinja2>=3.1
pypdf>=5.0
Debian/Ubuntu native dependencies

For most modern Debian/Ubuntu hosts:

sudo apt-get update
sudo apt-get install -y \
  python3-pip \
  libpango-1.0-0 \
  libpangoft2-1.0-0 \
  libharfbuzz-subset0 \
  fontconfig \
  fonts-dejavu-core

Template Rules

CSS

Use @page and print media deliberately:

@page { size: A4; margin: 0; }
@media print {
  body { background: white; }
  .page { width: 210mm; height: 297mm; overflow: hidden; }
  .no-print { display: none; }
}

Prefer:

  • mm for page canvas and key print spacing
  • CSS grid/table for stable document layout
  • font-variant-numeric: tabular-nums for money and IDs
  • explicit column widths for invoice tables
  • reserved space for stamps/badges/decorative elements
  • wrapping rules for long strings like IBANs, emails, IDs

Avoid or verify carefully:

  • absolute positioning near content
  • unsupported browser-only CSS
  • fancy effects like box-shadow, filter, mix-blend-mode
  • JS-only chart/render flows
  • content that fits only because sample text is short
HTML

Use semantic blocks and stable classes:

<section class="page invoice">
  <header class="invoice-header">...</header>
  <section class="invoice-meta">...</section>
  <table class="line-items">...</table>
  <section class="payment-box">...</section>
</section>

For long values:

.long-value { overflow-wrap: anywhere; }
.amount { white-space: nowrap; text-align: right; }

Render Script Pattern

Use a small Python script so rendering is repeatable and testable.

from pathlib import Path
import argparse, json
from jinja2 import Environment, FileSystemLoader, select_autoescape
from weasyprint import HTML

parser = argparse.ArgumentParser()
parser.add_argument('--template', required=True)
parser.add_argument('--data', required=True)
parser.add_argument('--out', required=True)
args = parser.parse_args()

template_path = Path(args.template)
data = json.loads(Path(args.data).read_text())

env = Environment(
    loader=FileSystemLoader(str(template_path.parent)),
    autoescape=select_autoescape(['html', 'xml'])
)
html = env.get_template(template_path.name).render(**data)
Path(args.out).parent.mkdir(parents=True, exist_ok=True)
HTML(string=html, base_url=str(template_path.parent.resolve())).write_pdf(args.out)

QA Checklist

Run all of these before calling a PDF done.

1. WeasyPrint warning check
python scripts/render_pdf.py --template templates/invoice.html --data data/sample-invoice.json --out outputs/invoice.pdf 2> outputs/weasyprint.log
test ! -s outputs/weasyprint.log

Warnings often reveal unsupported CSS or broken assets. Fix them unless they are intentionally harmless and documented.

2. PDF metadata/page check
pdfinfo outputs/invoice.pdf | grep -E 'Pages|Page size|PDF version'

Expected A4:

Page size: 595.276 x 841.89 pts (A4)
3. Text extraction smoke test
pdftotext outputs/invoice.pdf - | grep -E 'Invoice|Total|Payment'

This catches invisible text, missing content, and many accidental blank-page failures.

4. Browser preview

Open the HTML preview and check console errors. For artifact shelf/static hosting:

artifact add-dir my-pdf-lab ./public --title "PDF Lab" --type site --tag artifact
curl -fsSI https://artifacts.example.com/artifacts/my-pdf-lab/
5. Visual/overlap check

Inspect the rendered HTML/PDF visually. Focus on:

  • totals and money columns
  • payment boxes
  • long IDs/IBAN/email fields
  • stamps/badges
  • footer spacing
  • page breaks
  • table rows at page boundaries

If the user reports overlap, do not hand-wave it. Re-check with browser/vision and redesign the cramped area.

Publishing Pattern

For review, publish a static folder containing previews and PDFs:

public/
  index.html
  invoice.html
  invoice.pdf
  report.html
  report.pdf

Then:

artifact add-dir pdf-lab public --title "PDF Lab" --type site --tag artifact
curl -fsSI https://artifacts.omarbenaidy.com/artifacts/pdf-lab/

If using a different environment, any static host works: GitHub Pages, Cloudflare Pages, Netlify, nginx, S3, etc.

Font Guidance

Fonts affect pagination and overflow. For reproducible PDFs:

  • define an explicit font stack
  • bundle or install production fonts
  • avoid relying on macOS-only fonts unless the renderer runs on macOS
  • re-run QA after font changes
  • keep fonts/README.md updated with chosen fonts and licenses

Common Pitfalls

  1. Treating browser CSS support as WeasyPrint CSS support. WeasyPrint is excellent for print CSS, but not a full Chrome clone. Generate once early and read warnings.

  2. Decorative absolute positioning over real content. Stamps, blobs, and badges need reserved layout space. If they float over payment/totals/footer, they will overlap with real data.

  3. Long values in single-line fields. IBANs, addresses, emails, and invoice references need overflow-wrap:anywhere or stacked layout.

  4. Accidental extra blank pages. Fixed min-height:297mm plus padding/content can overflow. In print mode, use height:297mm, controlled padding, and inspect page count with pdfinfo.

  5. Unpinned renderer versions. Rendering can change across WeasyPrint versions. Pin the version and re-check golden PDFs after upgrades.

  6. Unpinned fonts. Missing or different fonts change layout. Install known fonts and avoid relying on system-specific typography.

  7. Screenshot-only QA. Screenshots are secondary. Check logs, page count, extracted text, browser console, and actual PDF availability.

Verification Checklist

  • WeasyPrint version pinned
  • Native dependencies/fonts installed and documented
  • Render command is repeatable
  • Render log has zero unexpected warnings
  • pdfinfo page count/size is expected
  • pdftotext finds key content
  • Browser preview has no console errors
  • Visual QA checks totals/payment/footer/page breaks
  • Public/review links return 200 when publishing is requested

Comments

Markdown supported