Case study · Web & product
AdvanceForm: from a plain-English prompt to a live dashboard
A form-to-dashboard platform where you describe a form and watch a KPI heat-matrix build itself — with the unusual twist that one frontend runs on two interchangeable backends, both in production.
01The problem
Teams that run events, registrations and rosters live in a gap. Consumer form tools give you a nice builder but a thin, generic results view — you still export a CSV and rebuild the same pivot tables every time. Enterprise platforms do the analytics but demand a full account setup and a budget. What people actually want is narrow and specific: build the form fast, share a link, and have the answers they care about — headcounts, meals, attendance across sessions, who still needs assigning — appear on their own.
02Constraints
- Two very different deployment homes. Some environments wanted an edge-serverless deploy; others needed to run on a plain Node box. The product had to be first-class on both, not "cloud with a degraded fallback".
- Real auth, real roles. Public submission links, but role-based accounts behind them, with proper password hashing.
- Zero-build frontend. The client is a vanilla-JS SPA (~3,200 lines) with no build step, so it stays trivially portable and easy to host anywhere.
- Analytics that keep up. KPI summaries, heat-matrices and roster auto-fill have to recompute as responses come in, not in a nightly batch.
03Approach
The whole design rests on one discipline: the frontend talks only to a small, stable HTTP contract, and nothing else. Forms, submissions and analytics are a fixed set of JSON endpoints. That contract is implemented twice — once as a Cloudflare Worker (Hono) over D1, once as a Node/Express server over better-sqlite3 — so the client is completely blind to which backend serves it.
On top of that contract sit 14+ field types with branching and skip logic, role-based accounts with session auth and bcrypt/PBKDF2 hashing, and the live dashboard: auto-generated KPIs, attendance heat-matrices, hand-out pick-lists, capacity-aware roster auto-fill and CSV export. AI form generation calls Google Gemini and returns a form definition in exactly the same schema the manual builder emits — so generated and hand-built forms are the same object.
04Architecture
Vanilla-JS SPA
Builder, public form, live dashboard. No build step.
Stable HTTP contract
One set of JSON endpoints for forms, submissions, analytics.
Backend A
Cloudflare Worker (Hono) + D1. Edge serverless.
Backend B
Node + Express + SQLite. Traditional server.
Gemini plugs in beside the builder, emitting the same form schema — the AI path and the manual path converge before anything is stored.
05One hard decision & the trade-off
Maintain two full backend implementations against one contract, instead of picking a single stack or adding a heavy database-abstraction layer.
The upside is genuine deployment freedom: the same product ships to an edge-serverless environment or a self-hosted Node box with no frontend changes, and the discipline of a shared contract kept the API honest and small. The cost is real — every schema change or new endpoint has to land in both backends and stay in sync, and their SQL dialects (D1 vs. better-sqlite3) differ in the corners. I accepted that maintenance tax because the alternative, an ORM abstraction thick enough to hide both, would have added more complexity than the two thin implementations it replaced.
06Outcome
AdvanceForm takes a team from "we need to collect this" to a live, analysed dataset without touching code or a spreadsheet. Describe the form or click it together, share the link, and the dashboard fills itself. And because the frontend is decoupled from the backend by a deliberate contract, the same build runs wherever the customer needs it to.
Tech
- Vanilla JS SPA
- Cloudflare Workers
- Hono + D1
- Node + Express
- better-sqlite3
- Google Gemini
- Session auth · bcrypt/PBKDF2
07FAQ
How can one frontend run on two different backends?
The frontend only ever talks to a small, stable HTTP contract — the same set of JSON endpoints for forms, submissions and analytics. Behind that contract, a Cloudflare Worker on D1 and a Node/Express server on SQLite each implement the same routes. The client neither knows nor cares which one it is hitting, so either can run in production.
What does the AI actually generate?
You describe the form you want in plain English and the model returns a structured form definition — field types, labels, options and branching logic — in the same schema the click-to-build editor produces. So an AI-generated form and a hand-built one are identical objects; you can generate a draft and then tweak it by hand.
Is it just a form builder, or does it do analytics too?
Both. Every form is wired to a live dashboard that computes KPI summaries, attendance heat-matrices, hand-out pick-lists and a capacity-aware roster auto-fill as responses arrive, with CSV export. The point is to go from a question to insight without leaving the tool.
Need an internal tool that runs without IT approval?
Let's talk. Whether it deploys to the edge or a box in the corner, I'll build the version that fits where you actually run things.
Get in touch