FAE PDF — Agent‑First HTML→PDF with Jinja2 + Playwright
A lightweight, agent‑first toolkit to render Jinja2 HTML into high‑quality PDFs using Playwright (headless Chromium). Built to be called by AI agents, webhooks, and automation flows. Great for resumes, invoices, proposals, and other print‑friendly docs where layout predictability matters.
Highlights
- Agent‑first: stateless CLI, easy to invoke from n8n/Make/Zapier/CrewAI.
- Inline JSON mode: pass a JSON string directly (ideal for webhooks).
- Deterministic output: A4, margins, and background graphics enabled.
- Jinja2 templating: partials/includes for reusable components.
- Minimal surface area: no server; one command does the job.
Quick Start
- Create a virtualenv
- Windows (PowerShell):
python -m venv .venv && .\.venv\Scripts\Activate.ps1 - macOS/Linux:
python3 -m venv .venv && source .venv/bin/activate
- Windows (PowerShell):
- Install deps:
pip install -r requirements.txt - Install Playwright runtime:
python -m playwright install chromium
Usage
-
Render from files (you provide the template and data):
- Windows:
python cli.py render-cmd --template templates\your.html --data data\your.json --out out\doc.pdf - macOS/Linux:
python3 cli.py render-cmd --template templates/your.html --data data/your.json --out out/doc.pdf
- Windows:
-
Render from inline JSON (agent/webhook friendly):
- PowerShell:
python cli.py from-json templates\your.html '{"person":{"full_name":"Ada Lovelace"}}' out\ada.pdf - Bash/zsh:
python3 cli.py from-json templates/your.html '{"person":{"full_name":"Ada Lovelace"}}' out/ada.pdf
- PowerShell:
-
Research report template:
- Render:
python cli.py render-cmd --template templates/research_report.html --data data/research.json --out out/research.pdf - Inline citations: include real HTML anchors in the JSON (e.g.,
...users<a href="https://openclaw.ai/blog/introducing-openclaw">[1]</a>). Markdown-style links ([[1]](url)) are not converted in this template.
- Render:
-
Library use (Python):
from render import render render("templates/your.html", "data/your.json", "out/doc.pdf")
Agent‑First Design
- Stateless CLI: simple inputs (paths or a JSON string) → single PDF output.
- Inline JSON: avoids temp files in workflows; the CLI handles an ephemeral
.tmp.payload.jsoninternally and cleans up. - Deterministic printing: fixed A4 size and margins with
print_background=Truefor reliable layout. - Works anywhere: paths are resolved relative to the repo root for easy includes/partials.
Project Layout
cli.py— Typer CLI (render-cmd,from-json)render.py— rendering engine (Jinja2 + Playwright)assets/— put your fonts/images here (tracked)out/— generated PDFs (git‑ignored)- User‑provided (git‑ignored by default):
templates/— your Jinja2 HTML templatespartials/— reusable partials/includesdata/— your JSON payload files
Template Tips
- Include partials with Jinja2:
{% include 'partials/header.html' %} - Reference assets relatively from templates, for example:
@font-face { font-family: 'YourFont'; src: url('../assets/YourFont-Regular.woff2') format('woff2'); font-weight: 400; }
- Ensure your JSON keys match what the template expects.
Troubleshooting
- Browser not found: run
python -m playwright install chromium. - Fonts missing: confirm files under
assets/and the relative paths used in CSS. - JSON shape errors: verify keys referenced in the template exist in your payload.