
The New York childcare subsidy application (form OCFS-6025) is 28 pages of government PDF. ChildcareGPT does two hard things with it: it turns that PDF into a guided form a real person can actually complete, and then it fills the official PDF back with their answers — so the output isn't a summary, it's the document they can file.
A wizard that guides instead of validates
The application is broken into tabs — About, Household, Activities, Household Income, Signature — and each tab is a set of section cards that carry their own status: confirmed, flagged, or warned. The clever part is that flagged sections auto-confirm once the user resolves their open items, so the form nudges rather than scolds:
// src/app/application/page.tsx
const TABS = ["About", "Household", "Activities", "Household Income", "Signature"];
// Auto-confirm warned sections once their open items are all resolved
useEffect(() => {
if (warnedSections.has("circumstances") && homeless && military && natGuard && otherFunding)
confirmSection("circumstances");
if (warnedSections.has("activities") && checkActivitiesOk())
confirmSection("activities");
if (warnedSections.has("members") && !members.slice(0, visibleRows).some((m) => m.name && !m.sex))
confirmSection("members");
}, [/* ...the fields each section depends on */]);Confirming a section collapses it; flagging keeps it open and highlighted. The result is a long form that always shows you exactly what's left — the same "state of work made visible" instinct as TerminalGPT's status rings, applied to a questionnaire.
Writing answers back into the real PDF
The payoff step: load the official OCFS-6025.pdf, get its AcroForm, and set
every field from state. Small typed helpers (tf, cb, yn) keep 28 pages of
field-mapping readable, and every try/catch means a renamed field never crashes
the export:
async function buildPdfBytes(): Promise<Uint8Array> {
const baseBytes = await fetch("/OCFS-6025.pdf").then((r) => r.arrayBuffer());
const pdfDoc = await PDFDocument.load(baseBytes);
const form = pdfDoc.getForm();
const tf = (name: string, val: string) => {
try { form.getTextField(name).setText(val || ""); } catch {}
};
const cb = (name: string, checked: boolean) => {
try { const f = form.getCheckBox(name); checked ? f.check() : f.uncheck(); } catch {}
};
const yn = (base: string, val?: string) => {
cb(`${base}_yes`, val === "Yes");
cb(`${base}_no`, val === "No");
};
tf("full_name", `${firstName} ${lastName}`.trim());
tf("address_county", county);
// ...the rest of the 28 pages
}Both the download and the email routes call buildPdfBytes, so the form a family
downloads is byte-identical to the one that gets sent — a single source of truth
for the output.
Why it matters
Most "AI form fillers" produce a nice summary you still have to transcribe. ChildcareGPT closes the loop: a humane intake experience on the front, the authoritative PDF on the back, and typed data in between. That's the difference between helping someone understand a form and actually helping them file it.
Brendan Stanton
Founder, NYSgpt
Read more
TerminalGPT — a localhost dashboard where the disk is the database
How HQ turns the files Claude Code already writes to disk into a live, searchable control room — with a panel that survives navigation, a daemon that outlives the server, and status rings that show the state of every session.

PolicyGPT — reading legislation like a first-class document
The NYSgpt flagship pairs a resilient, resizable PDF reader for live bill text with recharts sparklines and a chat that knows the document — a template for putting a real PDF and a GPT in the same view.
Games — a semantic color system in a single static file
Bank It is a zero-dependency party game whose entire look is a named CSS-variable palette: semantic tokens, a cycling slot palette for boards, and two design knobs that tune chunkiness and depth.