Build note / WhyFill
I built a form filler that renders official PDFs inside a lambda.
A government form is a data entry problem wearing a legal costume. WhyFill treats it that way: answer plain questions once, and the official PDF fills itself.
Isaac Benyakar ·
The forms are public. USCIS publishes the I-90 as a PDF anyone can download. The State Department publishes the DS-82. Nobody is hiding them. And yet people pay hundreds of dollars to have someone else fill them in, because the form asks for your A-Number in Part 1 and again in Part 4, phrases half its questions as double negatives, and gets rejected if you use the January edition after March.
That is not a legal problem. That is an interface problem, and interfaces are what I do.
The interview is the product
The naive build is a PDF viewer with input boxes on top. I did not do that, because it keeps the form's language, and the form's language is the reason people give up.
WhyFill asks plain questions in a guided interview and maps the answers onto the official fields behind the scenes. You never see "Part 3, Item Number 5.b." You see a question about where you live. The mapping is the engineering; the plain question is the product.
This is also what makes the second form cheap. Your name, your address, your dates, your A-Number: those are the same on every form that asks for them. So the profile is stored once, encrypted, and reused. On the I-90 interview that means 21 of 34 questions arrive already answered. The first form is work. The fifth is a review pass.
Four languages, one output
You can answer in English, Spanish, Chinese, or Hebrew. The form still comes out in English, because that is the only version the agency accepts.
I want to be precise about why that matters, because it is easy to file under accessibility and move on. The person filling out an immigration form often reads English well enough to get through a webpage and not well enough to be confident about a question whose wrong answer costs a rejection and a refiling fee. Translating the interview and not the output is the whole point: comprehension where the stakes are yours, compliance where the stakes are the agency's.
The renderer used to live on my desk
Here is the part I would have skipped if I were writing marketing copy instead of build notes. For a while, the PDFs were rendered by a Mac in my apartment.
Filling a government PDF properly means writing into the real AcroForm fields of the real published file, not drawing text at coordinates over a flattened image. The libraries that do that well are native. So the first version had a worker on a machine I owned, which is a fine way to prove the product works and a terrible way to run one. It meant the service was up when my apartment had power.
The renderer now runs in a serverless function using mupdf compiled to WebAssembly, with the finished file written to private blob storage and a cron job draining the queue. I proved it with my own passport renewal: a real DS-82, rendered in a lambda, six watermarked pages in the blob store, session marked ready to pay. The Mac is out of the loop.
The watermark matters more than it looks. You see every page of your completed form before you pay. You are not buying a promise that the software worked. You are buying the removal of a watermark from a document you already read.
What I would tell someone building this
Form editions change, and a filled form on last quarter's edition is wastepaper. So the edition date is part of the data model, not a footnote. Storing a form as a set of answers rather than a rendered artifact is what makes a re-render on a new edition cheap instead of a rebuild.
The encrypted profile is also the whole moat and the whole liability. It is the reason the fifth form takes minutes, and it is a pile of exactly the fields identity theft wants. That tension does not get resolved by a decision made once at the start. It gets re-litigated every time a feature wants to touch the profile.
What it runs on
- Next.js + React
- PostgreSQL + Drizzle
- mupdf in WebAssembly
- Private blob storage
WhyFill is live at whyfill.com (opens in a new tab). If you are building something with a similar shape, a boring interface over a strict output format, tell me what you are working on.