Jamstack forms: 3 ways to handle submissions
By Nick Peplow ·
Jamstack took the server out of your architecture, and forms keep trying to drag it back in. Routing, content, images — everything else got cleanly solved at build time. A form can’t be, because someone has to be awake at runtime to catch the POST. Three categories of service compete to be that someone, and they trade off in different places.
How does a form work with no server?
The browser doesn’t know or care that your site is static. A <form> POSTs to whatever URL its action names, same as it did in 2004. The whole question is who operates that URL: your hosting platform, a third party’s embedded page, or a dedicated endpoint service. That single decision determines your design control, where the data lives, and what breaks when you move hosts.
Host-captured forms: the Netlify pattern
Netlify Forms is the reference implementation. Add an attribute to your form tag, and at deploy time the platform parses your HTML, registers the form, and captures matching POSTs into a dashboard with email notifications. The strength is real: nothing to sign up for, nothing extra to deploy.
The tradeoffs are structural, and worth stating factually:
- The pipeline belongs to the host. Form handling is a feature of Netlify’s build system, not of your site. Move to Cloudflare Pages or Vercel — neither offers an equivalent — and the form pipeline gets rebuilt from scratch. That isn’t a flaw in Netlify; it’s how platform-native features work. It just belongs on the cost side of the ledger when you’re choosing.
- The quota is small. Netlify’s pricing page lists 100 form submissions per month per site on the free tier, with a paid Forms add-on above that.
- Framework-rendered forms need a workaround. Build-time HTML parsing can’t see a form that only exists after JavaScript runs, so React and Vue apps need a hidden static mirror of the form — a step Netlify’s own docs walk through, and the one that surprises most people.
Embedded widgets: the iframe pattern
Typeform, Tally, and Google Forms solve the problem from the other direction: they host the entire form and you embed it. You get a form builder, conditional logic, and storage without writing markup.
The price is design, and it’s paid on every pageview. An iframe is a styling boundary — the widget’s typography, spacing, and theme render inside your page, and matching them to your site is approximation at best. The embed loads after your page does, shifting layout. And submissions live in the widget vendor’s product, one more dashboard away.
That’s the right trade for surveys and multi-step intake flows, where the builder and logic genuinely earn their keep. It’s the wrong trade for a contact form that should read as part of the site.
Form backends: the endpoint pattern
The third category keeps the form entirely yours — markup, styling, validation — and outsources only the receiving end. A form backend gives you an endpoint URL; the action attribute is the integration. Every POST becomes an email plus a stored record you can search and export. Formspree is the best-known name in the category; Web3Forms, Getform, Basin, and FormWire are the same shape.
The honest tradeoff: you’ve added a vendor to the loop, with a submission quota and an uptime you don’t control, and notification deliverability is their job rather than yours. What you get back is the only architecture on this list that survives a host migration untouched — the form is plain HTML, and plain HTML moves.
How do the three compare?
| Host-captured | Embedded widget | Form backend | |
|---|---|---|---|
| Integration | Attribute in your HTML | iframe or script embed | action URL in your HTML |
| Survives changing hosts | No | Yes | Yes |
| Design control | Full — your markup | Limited to vendor theming | Full — your markup |
| Where submissions live | Host dashboard | Widget vendor’s product | Service inbox + your email |
| Binding constraint | Quota + host coupling | Design mismatch | Quota |
Prose version of the table: host-captured is the fastest start and the deepest coupling; widgets trade design for tooling; form backends trade a small vendor dependency for portability and full design control.
What does the endpoint pattern look like in practice?
Using FormWire as the worked example, the entire integration is:
<form action="https://api.formwire.com/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR-ACCESS-KEY">
<input type="text" name="name" required>
<input type="email" name="email" required>
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
The mechanics worth knowing before you commit to the pattern, with any vendor:
- Plain POST works with zero JavaScript, so the same form runs on Astro, Hugo, Eleventy, or hand-written HTML. Framework apps can POST JSON to the same endpoint with
fetch— include theaccess_keyin the body and anAccept: application/jsonheader, and handle the{"success": true}/ 4xx-with-message responses. CORS is handled server-side, so there’s no proxy to stand up. - The key in your markup is public by design. Delivery is locked to email addresses the account owner has verified, so a scraped key can only send you a submission — the failure mode is spam, and spam is filtered server-side by a honeypot that’s on by default.
- Redirect stays on your site via a hidden
_redirectfield pointing at your own thank-you page. - Submissions are stored before the POST is acknowledged, then emailed with retries — the record survives a delivery failure, which is the property that separates a form backend from a mail-forwarding script.
Portability is the sorting lens
A Jamstack site is portable by construction — until you weld a runtime feature to the platform that builds it. Forms are where that welding usually happens first. Sorted by that lens, the landscape gets simple: widgets when the form is the product, host capture when you’re certain you’ll never move, and a form backend when the form should be ordinary HTML that works wherever the site lands next. If you’ve narrowed to the endpoint category, the practical next question is which vendor — start with the head-to-head: FormWire vs Formspree.