SAVEFORM
All posts
Guide

How to add a contact form to a static site (no backend, no signup walls)

A practical guide to wiring an HTML form to a hosted endpoint when you do not want to spin up a server, write a route handler, or babysit a database.

4 min readforms·static-sites·html

You built a static site. Maybe it's a Next.js export, an Astro build, a hand-rolled HTML page on Cloudflare Pages, or something a designer handed you to deploy. Everything works fine, until someone asks you to add a contact form. Suddenly you need a server. Or do you?

You don't need a backend to collect form submissions. You need an endpoint.

The four bad answers most tutorials give

Search “static site contact form” and you'll get four well-meaning suggestions, all with sharp edges:

  1. A mailto: link. Opens the visitor's default mail client, which on mobile might be a half-configured Gmail web view, and on desktop might be no client at all. Conversion rate from a real form: a fraction of one percent.
  2. An embedded Google Form. Free, but the iframe ruins your design and trains visitors that you're fine with their data ending up in a spreadsheet they have no relationship with.
  3. Spin up a server. Now you own a route handler, a database, an SMTP setup, an SSL cert, a deploy pipeline, and a backup story. For a contact form.
  4. A no-code SaaS with five upsells. Drag- and-drop form builders that own your design, lock you to their CDN, and try to upsell webhooks at $29/month.

What you actually want

For 95% of static-site contact forms, the requirements are short:

That set of requirements has a category of solution called a form backend service: a hosted endpoint you POST your form to. SaveForm is one. Formspree, FormSubmit, Web3Forms, and Netlify Forms are others. The shape is the same: you point your form's action at a URL and their server takes care of the rest.

The 5-minute version (no JavaScript)

Here's the entire integration if you don't want to write a single line of JavaScript:

HTMLcontact.html
<form action="https://saveform.io/api/submit/YOUR_FORM_ID" method="POST">
  <!-- Where the notification email lands -->
  <input type="hidden" name="_emailTo" value="you@example.com" />

  <!-- Your real fields -->
  <input type="text"  name="name"  required />
  <input type="email" name="email" required />
  <textarea           name="message" required></textarea>

  <button type="submit">Send</button>
</form>

That's the whole thing. The browser handles the POST natively, the user gets a clean success page, and you get an email. No JavaScript, no fetch handler, no error states to write.

When you do want JavaScript

The HTML-only version is great until you want a custom “Thanks, we'll be in touch” UI without a full page navigation. Then you reach for fetch:

JavaScriptcontact.js
const form = document.querySelector('#contact-form');

form.addEventListener('submit', async (e) => {
  e.preventDefault();
  const data = Object.fromEntries(new FormData(form));

  const res = await fetch('https://saveform.io/api/submit/YOUR_FORM_ID', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
    body: JSON.stringify(data),
  });

  if (res.ok) showSuccessUI();
  else showErrorUI();
});

Send Accept: application/json and the response comes back as JSON instead of an HTML success page. From there, swap the form out for a thank-you message, fire your analytics event, whatever you want.

Things that bite you 90 days in

The 5-minute setup gets you a working form. The interesting problems show up later, and they're the same regardless of which service you pick:

A boring recommendation

Pick the simplest option that covers spam, dashboard storage, email notifications, and webhooks. Avoid anything that ties you to a drag-and-drop form builder. Your HTML is fine; you don't need to rebuild it inside someone else's WYSIWYG. And avoid the mailto: trick. It feels free; the cost is the silently-lost submissions you never know about.

A form endpoint in five minutes

SaveForm gives you a form action URL, a dashboard, email notifications, honeypot spam filtering, and webhooks. 100 submissions/month on the free tier, no credit card.

How to add a contact form to a static site (no backend, no signup walls) — SaveForm.io | SaveForm.io