Skip to content
SheetLink Forms

Building · 2026-08-17 · 9 min read · By Arden Talbot, founder of SheetLink

Jamstack forms: a short history

From cgi-bin scripts and FormMail to hosted endpoints: how "forms for static sites" became a product category, and where it goes now that static hosting costs nothing.

A ledger-styled timeline illustration tracing a form submission's path from a 1990s cgi-bin terminal to a modern endpoint feeding a spreadsheet.

The oldest problem on the static web

HTML has always been able to draw a form. It has never been able to receive one. The <form> tag renders inputs and a submit button, but the moment a visitor clicks submit, the data has to go somewhere - and a pile of static files has no somewhere. Every era of the web has had to answer the same question: my page is just HTML, so what do I put in the action attribute?

The answers to that question form a neat thirty-year arc - from scripts you compiled yourself, through an era when everyone ran a server whether they wanted one or not, to today's hosted endpoints. It is a small history, but it explains why the current category looks the way it does, and it hints at where the category goes next. This is that history, told honestly, including the parts where the industry embarrassed itself.

1993: cgi-bin and the first form handlers

The first real answer arrived in 1993 with the Common Gateway Interface: a convention, born at NCSA alongside the early web servers, that let a URL execute a program instead of returning a file. Suddenly action="/cgi-bin/register.pl" meant something - the web server would run a Perl script, hand it the form data on standard input, and return whatever the script printed.

CGI made forms possible and also made them a systems programming exercise. You parsed the urlencoded body yourself, escaped everything yourself, and emailed or appended to a flat file yourself, usually in Perl, often incorrectly. Every webmaster of the era either wrote a form handler or, far more commonly, copied someone else's. Which brings us to the someone else.

FormMail and the mailto years

The someone else was usually Matt Wright, whose FormMail - a Perl CGI script from the mid-1990s that emailed form submissions to a configured address - became one of the most copied pieces of code on the early web, installed on hundreds of thousands of sites. Its ubiquity taught the industry a hard lesson: early versions could be tricked into mailing anywhere, and spammers scanned the web for installations to use as open relays. A generation of administrators learned about input validation from FormMail advisories.

The truly desperate skipped CGI entirely with action="mailto:me@example.com", which asked the visitor's own email client to send the submission - a mechanism so dependent on client configuration that it failed silently for large fractions of visitors. The era's verdict was clear: forms-to-email was what everyone wanted, and self-hosted scripts were a liability-prone way to get it.

The dynamic detour

Then, for roughly a decade, the problem seemed to dissolve - because the static site itself dissolved. PHP made every page a program, and the great CMS platforms of the 2000s meant an ordinary website ran on a server with a database as a matter of course. If your whole site is dynamic, a form handler is just another route; the capability came bundled with the architecture, and "where do forms go?" stopped being a question anyone asked separately.

It is worth pausing on why this era ended, because the reasons became the sales pitch for what followed: dynamic sites had to be patched, secured, scaled, and backed up, and the overwhelming majority of pages they served never needed to be computed at all. The industry had adopted a server per site largely because a few features - forms prominent among them - needed one.

Static comes back, and the problem comes back with it

The pendulum swung back beginning around 2008, when Jekyll paired with GitHub Pages made static site generation respectable again: write markdown, generate HTML, serve it from a CDN for pennies, with effectively nothing to hack or crash. Performance-obsessed and security-burned developers led the migration, and the tooling - Hugo, Gatsby, Eleventy, and later Astro - kept lowering the cost.

And with the return of static came the return of the 1993 question, entirely intact: the marketing site is static files again, so what goes in the action attribute? The answer could no longer be "your CGI script" - the whole point of the new architecture was owning no server. The gap sat there, obvious, waiting to become a product.

The category gets a name

The product arrived from two directions at once. Around 2014, Formspree offered the minimal viable answer: point your form's action at our URL and we will email you the submission - forms-to-email as a hosted service, FormMail's job without FormMail's liabilities. It proved there was real demand, and a wave of similar endpoints followed. Then the hosts moved in: Netlify built form handling directly into its platform, detecting forms at deploy time, making the capability a hosting feature rather than a separate signup.

The architecture soon had a name - Jamstack, coined by Netlify cofounder Mathias Biilmann in the mid-2010s and stewarded at jamstack.org - for static front ends talking to APIs for their dynamic needs. Forms were, for most sites, the first and often only such need, which made the form endpoint the gateway product of the whole architecture. Credit where due: Formspree defined the shape of the category, and Netlify Forms proved hosts could absorb it. Our comparisons with both - Formspree and Netlify Forms - exist because they earned being the reference points.

What the endpoint era matured

A decade of hosted endpoints turned a script's job into an operational discipline. Spam screening became table stakes - honeypots, rate limits, heuristics - because a public POST URL attracts bots within days. AJAX embeds, CORS handling, and redirect control became standard, as our static-site contact form guide walks through in practice. The better services added delivery logs and retries, quietly importing reliability engineering into a category that began as "a Perl script that calls sendmail."

What matured less was the destination. The category's default output in 2024 was the same as FormMail's in 1996: an email in an inbox. The submission's journey got dramatically more reliable; where it ended mostly did not.

The commoditization squeeze

Which brings the history to its present tension. Static hosting has commoditized to effectively free - GitHub Pages, Cloudflare Pages, Netlify's and Vercel's generous tiers - and when hosting margins compress, bundled extras stop being a competitive moat and start being a cost center; hosts' form tiers have stayed conspicuously modest. Meanwhile standalone form backends multiplied into the crowded field we survey in our roundup of form backends, most differentiated by little more than pricing tiers on the same forms-to-email core.

Commoditization at the transport layer pushes value to the layers that resist commoditization. Receiving a POST is now nearly free; what remains scarce is everything after: screening you can trust, delivery you can audit, and data landing somewhere a team actually works.

Our read: the destination is the product

Here is the position this history has argued us into - and yes, we built a company on it, so weigh the bias. The inbox was always a strange terminus for structured data. A form submission is a labeled record; an email is where labeled records go to become unsearchable prose. The next turn of the category treats the endpoint as settled plumbing and competes on the working destination - which for most small teams means the spreadsheet, the one tool where leads get sorted, assigned, and counted.

That is the bet behind SheetLink Forms: permanent endpoints in front, rows landing directly in Google Sheets or Excel in back, attribution captured on the way through - the whole path is on how it works, and the live demo feeds a public sheet you can inspect. Thirty years after cgi-bin, the action attribute finally points somewhere that was worth the trip.

The next thirty years of the action attribute

Histories owe a forecast, so, briefly: the static architecture is not going anywhere - if anything, edge rendering blurs it into the default way sites ship - and the form endpoint will keep being the piece of infrastructure a static site cannot fake. Expect hosts to keep bundling a baseline version, standalone endpoints to compete on destinations and data quality, and the humble <form> tag, action attribute and all, to outlive several more framework cycles, exactly as it outlived CGI, PHP, and the CMS era.

The through-line of the whole story is that the form tag never changed - only the address it points to did. Choose that address well. If you want ours, the docs show the full request lifecycle, and signup is open - start free.

FAQ

What does Jamstack mean?

An architecture - the name was coined by Netlify cofounder Mathias Biilmann in the mid-2010s - where sites ship as prebuilt static files served from a CDN, with dynamic needs handled by JavaScript calling APIs. Forms were most sites' first such dynamic need.

How did forms work on websites before form backends existed?

Through CGI scripts - programs, usually Perl, that the web server executed on POST. Most sites ran copied scripts like Matt Wright's FormMail, which emailed submissions and became infamous when spammers exploited early versions as open mail relays.

Why did action="mailto:" forms fail?

Because they depended on the visitor's machine having a configured email client that cooperated with the browser. For a large share of visitors nothing was sent at all, and the site owner had no way to know - silent failure as a core mechanic.

What was the first modern form backend?

Formspree, around 2014, is the usual answer: it turned "point your form action at our URL and we will email you the submission" into a hosted product, and its shape - a permanent POST endpoint for static sites - defined the category that followed.

How are Netlify Forms different from a standalone form backend?

Netlify Forms is a hosting feature - forms detected at deploy time, submissions collected by the platform - convenient if you host there, bounded by its plan limits. Standalone endpoints work from any host. See our Netlify Forms comparison.

Do static sites still need a form backend in the edge-function era?

Serverless functions can receive a POST, but you are then writing and operating the screening, retries, and delivery yourself - the same job as 1990s CGI with better ergonomics. The trade-offs are covered in our endpoint vs serverless guide.

What does a Jamstack form look like in markup?

An ordinary HTML form whose action points at an endpoint: <form action="https://sheetlinkforms.com/f/your-token" method="POST"><input type="email" name="email" required><input name="_slhp" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px"><button>Send</button></form> - the hidden field is the spam honeypot.

Where is the form backend category heading?

As static hosting commoditizes, differentiation moves past receiving the POST to what happens after: trustworthy screening, auditable delivery, attribution, and destinations teams work in - spreadsheets rather than inboxes. Our roundup maps the current field.

Give your action attribute a destination

A permanent endpoint for any static site, with rows landing straight in Google Sheets or Excel - free to start.

Start freeSee the live demo

The multi-touch attribution myth for small teamsWe built our waitlist on our own product