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.
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.
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.
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.
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.
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 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.
<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>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.
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.
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.
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.
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.
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.
Create a free MyFormCapture form endpoint and skip building your own backend.
Start Free TrialNo credit card required · 5-minute setup