Blog
PDFops posts
Why this exists, how to use it, what's coming next. Subscribe via RSS or just come back — new posts land here as I have something worth writing down.
-
Filling encrypted government PDFs: what actually works, measured
Some government blanks open fine in any viewer but crash every PDF library at load. Why an empty user password does that, and the measured matrix of what fills CA FL-100 and CRA TD1.
-
PDFops v0.10: fill a PDF by email, make any PDF fillable
Two no-code on-ramps — email-as-API at fill@pdfops.dev and a browser tool that adds form fields to flat PDFs — plus byte-deterministic fills and flatten=true.
-
Merging PDFs in a Bun server: page order, quota, and the 429 you'll eventually hit
A Bun.serve() endpoint that merges uploaded PDFs in order via PDFops, checks quota before it burns the last request, and handles the 429 that shows up the day traffic actually arrives.
-
Snapshot-testing generated PDFs in CI with a hash instead of a diff
A headless-browser renderer stamps a new timestamp into every PDF it produces, so byte-diffing its output in CI always fails. A deterministic fill API and a committed golden hash make the same test actually work.
-
Migrating off wkhtmltopdf on AWS Lambda — the unpatched CVE and the form-fill swap
wkhtmltopdf is archived, its last release carries an unpatched CVSS 9.8 SSRF, and it still ships as a Lambda Layer binary. If what you render is form-shaped — invoice, receipt, statement — here's the fill-form swap that drops the binary entirely.
-
Assembling a KYC packet on Deno Deploy — inspect, fill, and merge with the pdfops-sdk
Discover a template's fields at request time, fill it, and merge in the applicant's ID scan — one PDF packet, chaining PDFops' three primitives with the new pdfops-sdk. ~45 lines of TypeScript.
-
Fill a PDF form inside a Cloudflare Worker — no Chromium, no Lambda
Headless Chrome won't run in a V8 isolate and a render layer doesn't belong on Lambda. The minimal Worker that fills an AcroForm PDF with one fetch — and why the hosting substrate, not the PDF code, is the part that matters.
-
The case for deterministic PDF filling
AI can read almost any document now — but the write step, filling an official PDF, shouldn't be a language model if an auditor might ever look at it. Why the extraction wave needs a deterministic, audit-safe fill step underneath it.
-
Fill and merge PDFs in your browser — free, no signup (or one API call)
A free in-browser tool to fill PDF form fields and merge PDFs — drop a file, fill or merge, download. The same operations are one curl away the moment you automate them.
-
Generating signed contracts from a Tally webhook on Cloudflare Workers
Tally fires the webhook, a Cloudflare Worker fills the contract template via PDFops, stashes the result in R2, and emails the customer a countersigned PDF. ~75 lines of TypeScript, sub-400ms end-to-end, no ops-team round-trip.
-
Generating audit-trail PDFs from a Next.js Server Action
Fill the main template, fill a metadata cover page, merge them — two PDFops endpoints chained in one Next.js Server Action. Cover-page-bound audit trail every contractor signature, ~350-500ms end-to-end, ~75 lines of TypeScript.
-
Auto-filling a W-9 from a contractor-onboarding webhook on Vercel Edge
Onboarding form → Vercel Edge Function → PDFops fill-form → Vercel Blob, sub-300ms end-to-end. ~60 lines of TypeScript. Same pattern works for I-9s, 1099s, and any AcroForm PDF.
-
Monthly PDF bundles on a Cloudflare Cron Trigger
Per-customer statement bundles end-to-end on a Cloudflare Worker — fill, merge, store, email signed link. ~60 lines of TypeScript, fires once a month, no servers.
-
Generating invoice PDFs from Stripe webhooks on Cloudflare Workers
The most common SaaS PDF use case, end-to-end on the edge: Stripe webhook → PDFops fill-form → R2 storage, sub-300ms, ~50 lines of TypeScript.
-
Getting started with PDFops
30 seconds to a working PDF API call. Two curl commands, the limits, and what's coming next.
-
Why I built PDFops
I run several SaaS businesses. Across every one of them, there's a moment when I need to generate PDFs — and every time it's a bigger problem than it should be. So I built it once, as a hosted API.