Static Sites
Published: 27-Jul-2026

How to Collect Form Submissions on a Static Website

Static sites (HTML, Hugo, Jekyll, GitHub Pages) cannot run server code. Use a managed form endpoint to store leads, send alerts, and block spam without hosting a backend.

MFC

MyFormConnect Team

Static websites — whether hosted on GitHub Pages, Netlify, Cloudflare Pages, or an S3 bucket — serve pre-built files. There is no persistent server process running, so when a visitor submits a contact form, there is nothing on the host to receive and store the data. This guide explains what actually works, what doesn't, and how to set up reliable form collection on any static host.

The fundamental constraint

Static hosting means files are delivered by a CDN or object store. There is no application server, no database, and no long-running process. A standard form POST to your own domain will either return a 404 or silently fail — the hosting infrastructure simply isn't designed to receive dynamic requests.

This is true even on platforms like Netlify or Vercel that have optional serverless function features. If you're using plain static exports, there's no form handler available by default.

Approaches that don't actually work

mailto: links and forms

Setting action="mailto:[email protected]" opens the visitor's local email client and pre-fills a draft. Most visitors won't complete this step, and many won't even have a mail client configured. It also exposes your email address directly in the HTML source.

Client-side JavaScript email services

Services like EmailJS let you send email directly from the browser using an API key embedded in JavaScript. Because the key is visible in the page source, anyone can use it to send arbitrary emails from your account. This is only acceptable for throwaway projects.

Host-native form solutions

Netlify Forms and similar offerings work well — until you migrate hosts. You end up locked to a specific provider for your form logic, which is inconvenient when CDN pricing or deployment requirements change.

The working pattern: external form endpoint

The reliable approach is to point your HTML form at an external HTTPS endpoint. Your static page sends data there; the endpoint stores it, filters spam, and notifies you. Your static hosting stays exactly as it is.

Step-by-step setup

  1. Create a form in MyFormCapture and copy the endpoint URL
  2. Enable email notifications and spam protection in the form settings
  3. Configure a redirect URL (your thank-you page)
  4. Add the form HTML to your static page
  5. Deploy as usual — no build step changes needed
<form action="https://myformconnect.io/f/YOUR_FORM_ID" method="POST">
  <label for="name">Name</label>
  <input id="name" name="name" type="text" required />

  <label for="email">Email</label>
  <input id="email" name="email" type="email" required />

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="5" required></textarea>

  <input type="hidden" name="_redirect" value="https://yoursite.com/thank-you" />

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

Notes for specific platforms

GitHub Pages

GitHub Pages serves files from your repository directly. There is no form-handling capability. Add the HTML above to any .html file. No _config.yml changes are needed — the form simply posts to the external endpoint.

Hugo

Place the form in a layout file (e.g. layouts/contact/single.html) or in a shortcode. Hugo's build process doesn't touch the action URL — it passes through as-is. Do not store API keys in your repository; the public form ID in the action URL is all that's needed.

Jekyll

Add the form to a .html or .md page using an include partial if you want to reuse it. The Liquid template engine won't interfere with the form markup. Jekyll compiles to static files and the action URL remains unchanged in the output.

Netlify (static export)

If you're deploying a static export and don't want to use Netlify Forms, the external endpoint approach works identically. The form just posts to your myformconnect.io URL instead of a Netlify endpoint.

Spam protection on static sites

Static sites tend to attract automated form submissions because there's no server-side rate limiting or authentication in the way. Enable spam protection in your form settings before you publish the form publicly. At minimum, enable the honeypot field — it catches most simple bots with zero impact on real visitors.

For more detail, see how to stop contact form spam without a backend.

The key point

Static hosting is not a limitation for contact forms — it's simply a different architecture. Your HTML, CSS, and JavaScript live on the CDN; form handling lives on the endpoint. The two layers don't need to be on the same host, and there's no reason they should be.

Once the endpoint is connected, you can move your site between hosts, change CDN providers, or switch static site generators without touching the form at all.

Ready to collect form submissions?

Create a free MyFormCapture form endpoint and skip building your own backend.

Start Free Trial

No credit card required · 5-minute setup