Programmatic PDF generation that looks like it was designed, not exported.
PDF generation for invoices, reports, contracts, and documents — using React PDF (react-pdf), Puppeteer, or WeasyPrint depending on the complexity. We build PDF pipelines that produce branded, data-driven documents at scale.
Application that needs to generate PDFs — invoices, reports, contracts — and current PDF output is ugly, manually created, or breaks layout on different content lengths
PDF generation in web applications has three viable approaches, and the wrong choice causes significant rework:
React PDF (@react-pdf/renderer). Renders a React component tree into a PDF. Design PDFs using React-like JSX. No browser dependency. Runs server-side. Best for: structured documents (invoices, reports, certificates) where layout is predictable and doesn't depend on browser rendering.
Puppeteer / Playwright headless Chrome. Renders an HTML page in a headless browser and exports it to PDF. The output matches what the page looks like in Chrome. Best for: complex layouts that leverage CSS, documents that need web fonts and modern CSS features, or when an existing HTML template needs to become a PDF.
WeasyPrint. Python library that converts HTML/CSS to PDF. Better CSS support than most JavaScript PDF libraries. Best for: applications with Python backends, or complex print layouts.
The common mistakes:
Using React PDF for complex HTML layouts. React PDF has its own layout system (Yoga, similar to React Native) — not CSS. Translating complex web layouts to React PDF's layout system is significant work.
Using Puppeteer in Vercel serverless functions. Puppeteer requires a Chromium binary. The uncompressed binary is ~170MB, exceeding Vercel's serverless function bundle limit. Use @sparticuz/chromium for the Lambda-compatible binary, or move PDF generation to a separate service on Fly.io/Railway.
Font loading. PDFs with system fonts look generic. Custom fonts require embedding — font file loading in React PDF or font-face in HTML templates.
PDF generation pipeline with branded templates, dynamic data injection, consistent layout, and the generation endpoint that produces PDF downloads or email attachments on demand
React PDF pipeline
`@react-pdf/renderer` component templates for invoices and reports. Dynamic data injection. Font embedding. Stream to S3 or return as download.
Puppeteer pipeline
Puppeteer setup (either local or via a service). HTML template rendering. PDF generation with print CSS. `@sparticuz/chromium` for serverless compatibility.
PDF generation endpoint
Route Handler that accepts document ID, fetches data, renders PDF, and returns as `application/pdf` response.
Storage and email
Generated PDF stored in S3 or attached to Resend email.
Queued generation
Background job queue for high-volume PDF generation (bulk invoice export, report batches).
One honest number to start.
Fixed-scope, fixed-price. The number below is the starting point — final scope is built from your brief.
PDF generation pipeline with branded templates, dynamic data injection, consistent layout, and the generation endpoint that produces PDF downloads or email attachments on demand
Three steps, every time.
The same repeatable engagement on every project. No surprises, no mystery, no billable ambiguity.
Brief & discovery.
We send you questions, then get on a call. Output: a written scope with every step, feature, and integration listed.
Build & ship.
Fixed schedule, weekly reviews. No scope creep unless you change the scope — and if you do, we reprice it transparently.
Warranty & retainer.
30-day warranty on every launch. Most clients stay on a monthly retainer for ongoing features and maintenance.
Why Fixed-Price Matters Here
PDF scope is defined by the template count and the data complexity. Fixed price.
Questions, answered.
React PDF for invoices, receipts, and structured data documents — clean implementation, no browser dependency. Puppeteer when the PDF needs to match a complex HTML design exactly.
React PDF handles pagination automatically with its layout system. For Puppeteer, CSS `break-before: page` and `break-inside: avoid` control page breaks. Tables that span pages need explicit pagination logic in either approach.
Part of the application build. Full application from $25k. Fixed-price.
Tell Ryel about your project.
Describe what you’re building and what outcome you need. You’ll have a written, fixed-price scope within the week.