← All posts
formshow-tostatic-sites

How to add a working contact form to a static site (no backend)

BonPages Team · October 4, 2026 · 9 min read
How to add a working contact form to a static site (no backend)

You've built a site. It's fast, it's hosted on Netlify or Vercel or GitHub Pages for nothing, and it has a contact form that does absolutely nothing.

This is the oldest wall in front-end development. HTML gives you <form>, but the browser can only send the submission somewhere. Something has to be listening. On a static site, nothing is.

There are three honest ways out of this, and the right one depends on whether you already have a site, how much you want to maintain, and what has to happen after someone hits submit. Here they all are, with the trade-offs nobody mentions until you're three hours in.

First: don't use a mailto link

The tempting shortcut looks like this:

<form action="mailto:you@example.com" method="POST">

Or the even simpler version, an <a href="mailto:..."> instead of a form at all. Both are worse than having no form.

Here's what actually happens. The visitor taps it, and their device tries to open a mail client. On a work laptop with no configured mail app, nothing happens at all. On a phone, it opens the mail app with a blank draft, and the person is now staring at an empty email they have to write themselves, having lost whatever they'd already typed into your form. Where it does submit, the formatting arrives as URL-encoded soup.

The deeper problem is that you've moved the work from you to them, at the exact moment they were willing to do something. You also expose your address to every scraper that visits. Roughly speaking, a mailto form converts a fraction as well as a real one. Treat it as broken.

Option 1: a hosted form backend

This is the right answer for most static sites. A form backend is a service that gives you a URL to point your form at. It receives the POST, emails you, stores the submission, and forwards it wherever else you want. You change one attribute in your HTML and you're done.

With FormSubmit, the whole integration is this:

<form action="https://formsubmit.app/f/k3m9p2qabx" method="POST">
  <input type="text" name="name" placeholder="Your name" required>
  <input type="email" name="email" placeholder="you@example.com" required>
  <textarea name="message" required></textarea>
  <input type="text" name="_gotcha" style="display:none">
  <button type="submit">Send</button>
</form>

You sign up, create a form, get the endpoint, paste it into the action. There's no SDK, no API key in your source, no build step, and no server. It works the same whether the page is hand-written HTML, a React component, a Next.js app, Webflow, Framer, or something an AI generated for you an hour ago, because all of those ultimately render a <form> element.

(Disclosure, since it matters: FormSubmit is built by the same team as BonPages. We use it on our own static pages, which is why it's the one described here.)

A few details worth knowing whichever backend you pick:

The honeypot. That _gotcha field is hidden from humans by CSS, so only a bot fills it in. Anything that arrives with it populated gets binned. It costs one line and removes a surprising share of junk. Add a real captcha — reCAPTCHA, hCaptcha or Turnstile — only once the honeypot and rate limiting stop being enough, because every captcha costs you some genuine submissions.

Submitting without leaving the page. By default the browser navigates away on submit, which means your visitor lands on someone else's thank-you page. Two ways round it: configure a redirect back to your own thank-you URL, or submit with JavaScript and handle the response yourself. For the second, send Accept: application/json and you get JSON back instead of a page:

const res = await fetch(form.action, {
  method: "POST",
  body: new FormData(form),
  headers: { Accept: "application/json" },
});
if (res.ok) showThanks();

That's the version to use on a single-page app, where a full navigation would throw away your client state.

Where submissions go afterwards. Email is table stakes. The thing that makes a form backend worth paying for is everything after the email: a row in Google Sheets, a message in Slack or Discord, a subscriber in Mailchimp or Kit, a contact in Airtable, or a webhook to your own endpoint with retries. Wire this up on day one, because a form whose results live only in your inbox stops being useful the moment you get more than a few a week.

File uploads. If you need people to send a brief, a photo of a broken part, or a CV, a backend that stores files and gives you private signed links saves you building an upload pipeline. This is the single feature most likely to decide the choice for agencies and tradespeople.

Retention. Decide deliberately how long submissions are kept. Keeping everything forever is a liability as much as an asset, particularly if you're handling anything sensitive. Most backends let you pick, including storing nothing at all and only emailing.

FormSubmit has a free tier with one form and a small monthly submission allowance, which is enough to find out whether it fits, and paid tiers from a few dollars a month when it does. Check its pricing page for current numbers. The behaviour at the limit is the part worth checking on any service you consider: submissions should be held rather than dropped when you exceed a quota, because the alternative is silently losing a lead.

Option 2: a builder where the form is already part of the page

Option 1 assumes you already have a site. Plenty of people asking this question don't, really — they have a half-finished template and a form is the only reason they're in the HTML at all.

If that's you, the question isn't "how do I add a backend to this page" but "do I need to be hand-building this page". A page builder with forms built in gives you the page, the form, the inbox and the analytics as one thing, with nothing to wire up.

That's what BonPages does: forms with 11 field types, each submission emailed to you and kept in an inbox you can filter and export as CSV, plus a webhook per form so submissions still flow onwards to Zapier, Make, n8n or your own endpoint. It's on the free plan, not held back for a paid tier. The guide to connecting bio forms to Zapier, Make and Sheets covers the payload format and what happens when a delivery fails.

The honest line between the two: if the page already exists and you like maintaining it, use a form backend. If the form is the page — a contact page, a lead-capture page, a bio link — a builder gets you there faster and leaves you less to maintain. They're not really competing; most people need one or the other at different moments.

Option 3: roll your own

A serverless function plus a transactional email API is maybe forty lines of code. On Vercel or Netlify you drop a function in the right folder, parse the body, call Resend or Postmark, and return a response.

It is genuinely easy to get to "it works on my machine". What people underestimate is everything after that:

  • Spam. Within a week of being indexed, a public endpoint gets automated traffic. Now you're implementing a honeypot, rate limiting by IP, and probably a captcha.
  • Deliverability. Your email will land in spam until you've configured SPF, DKIM and DMARC on a sending domain. This is the part that eats an afternoon.
  • Storage. Email alone means a lost email is a lost lead. So now you want a database row too.
  • Validation and encoding. Non-Latin names, long messages, attachments.
  • Alerting. When the function starts failing, you find out from an angry customer, unless you build monitoring.

Build it yourself when the form does something genuinely custom — writes to your own schema, triggers domain logic, needs to live inside your own compliance boundary. For a contact form, you're rebuilding a solved problem and taking on its maintenance for the rest of the site's life.

Choosing, quickly

Your situation Use
Static or JAMstack site that already exists A hosted form backend
React, Vue or Next.js app, form inside the UI A form backend with a JSON endpoint
No site yet, and the form is most of the point A page builder with forms included
Need file uploads without building storage A form backend
The form triggers your own business logic Your own function
Strict data residency or compliance rules Your own function, deliberately

Things that matter regardless of which you choose

Name your fields properly before you build anything downstream. The field names become the keys in every email, spreadsheet column and webhook payload. Use short, lowercase, stable names: name, email, budget, message. Change the label when you want to reword the question, never the name, or you'll break every automation silently.

Keep it short, then add one qualifying field. Every field costs you submissions. But one well-chosen question — budget as a dropdown, a date, a postcode — saves you an entire email round trip on each enquiry, and it's usually worth the drop-off. Dropdowns get answered when the same question in prose does not.

Say what happens next. One line above the button: "I reply within two working days." It measurably increases submissions, because the main thing stopping people is not knowing what they're walking into.

Confirm on the page, not on someone else's. Whether by redirect or JavaScript, the person should end up looking at your thank-you message. A visitor dumped on a generic confirmation page assumes something went wrong.

Send an autoresponse. A short confirmation email does two useful jobs: it reassures the sender, and it puts your address in their inbox so their reply threads properly.

Test it like a visitor. Submit the real form from your phone, on mobile data, and check the email arrives and isn't in spam. Then check it again a month later. Forms break silently, and nobody complains — they just leave.

The short version

A static site can have a perfectly good form. If the site exists, point it at a hosted backend like FormSubmit and spend your time on the page instead of on SPF records. If the site doesn't exist yet and the form is the point, use something where the page and the form come together. Write your own only when the form does something only you can do.

What matters far more than the mechanism is what happens after submit: that it reaches you, that it's stored, that it reaches your spreadsheet or CRM, and that you reply. If you want to go further on that last part, growing an email list with forms covers placement and wording, and the best Typeform alternatives covers the survey end of the spectrum.