All guides
tutorialshtml forms

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

A step-by-step guide to adding a working contact form to any static site — HTML, Astro, Hugo, or plain pages — without writing or hosting a backend.

Formcrest7 min read

If you have ever wired up a <form> on a Netlify, GitHub Pages, or Cloudflare Pages site and watched it do nothing after clicking Submit, you have hit the fundamental limitation of static hosting: there is no server-side code to receive the POST.

This guide walks through exactly how to fix that — step by step — without writing or hosting any server yourself.

Why static sites can't process form submissions

When a visitor clicks Submit, the browser serialises the form fields and sends an HTTP POST request to whatever URL is in the action attribute. On a traditional web server, a running process — PHP, Node, Python, Ruby — receives that request, reads the fields, and decides what to do with them: send an email, write to a database, return a redirect.

Static hosts serve files from a CDN. There is no running process behind the scenes. If your form's action points at your own domain, the request lands on the edge node, finds no handler, and the visitor gets a 404 or a method-not-allowed error. Sometimes the browser just stalls.

The three escape hatches are:

  • Deploy a backend. A Node, Python, or PHP server that handles the POST. This means infrastructure you have to provision, secure, keep running, and pay for — even if it handles twenty requests a month.
  • Write a serverless function. AWS Lambda, Cloudflare Workers, or Vercel Edge Functions reduce the infrastructure burden. But you still write the email-sending code, deal with SMTP credentials, validate fields, and handle spam.
  • Use a form backend. A dedicated service that accepts POSTs on your behalf, validates the fields, filters spam, stores the submission, and emails it to you. No code to write. No server to run.

For most static sites — portfolios, marketing pages, documentation sites, small business pages — a form backend is the right answer. It is the smallest possible surface to maintain, and you can have a working form in under ten minutes.

What a form backend does

A form backend is an HTTPS endpoint that accepts form submissions from any origin. You point your form's action attribute at it. The service:

  • Receives the POST (standard application/x-www-form-urlencoded or multipart/form-data)
  • Validates the field data
  • Runs spam detection
  • Stores the submission so you can review it in a dashboard
  • Emails the data to the destination email addresses you control

From the visitor's perspective: they click Submit and land on a thank-you page. From your perspective: you get an email with their name, email address, and message. No server was harmed in the making of this contact form.

Step 1: Create a Formcrest form and verify your email

Sign up at formcrest.com/signup — no credit card required. Create a new form from the dashboard. You will be given a unique form ID, for example abc123. Your submission endpoint is:

https://api.formcrest.com/v1/submit/abc123

Before submissions are delivered, verify the destination email address you want them sent to. Formcrest sends a one-time confirmation link; click it and that address is ready to receive submissions.

Step 2: Write the HTML form

Point your form's action at your endpoint and set method="POST". The form below is a complete, working contact form:

<form action="https://api.formcrest.com/v1/submit/abc123" method="POST">
  <label>
    Name
    <input type="text" name="name" required />
  </label>

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

  <label>
    Message
    <textarea name="message" required></textarea>
  </label>

  <!-- Honeypot: hidden from users, irresistible to bots -->
  <input
    type="text"
    name="_honey"
    style="display:none"
    tabindex="-1"
    autocomplete="off"
  />

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

Replace abc123 with your real form ID from the dashboard. That is the only site-specific change needed. The full HTML installation reference is at /docs/installation/html.

Step 3: Every field you want captured needs a name attribute

Formcrest reads the POST body and stores every named field verbatim — there are no required field names on the service side. Name a field phone-number and that is exactly what shows up in the email and the dashboard.

A few practical tips:

  • Use lowercase, hyphen-separated names (first-name, not firstName or First Name)
  • Do not use names beginning with _ for your own fields — Formcrest reserves the underscore prefix for internal fields like _honey
  • required in the HTML adds client-side validation; it is the browser's job to enforce it before the POST is sent

Step 4: Set a custom success redirect

By default, Formcrest redirects a successful submission to its hosted thank-you page. That works, but most sites want to send visitors to their own branded confirmation page.

Configure the success URL in your form's settings in the dashboard. Once set, successful submissions redirect there. You can also configure an error URL; failed submissions redirect there with a ?error=CODE query parameter so you can show a relevant message. Both redirects are available on the free plan.

Step 5: The honeypot field — and why it matters

The _honey field you saw in the HTML above is a spam trap. Real visitors never see it because it is hidden with CSS. Automated bots, however, typically fill in every field they encounter. When the _honey field arrives with a value, Formcrest accepts the submission (giving the bot a normal success response so it gets no signal it was caught) but flags it as spam and never delivers it to your inbox.

Flagged submissions are stored in the dashboard so you can review them if needed. They never count against your monthly submission quota.

Keep the field hidden with style="display:none" rather than type="hidden" — bots can distinguish a genuinely invisible field from one that is programmatically hidden. Set tabindex="-1" to remove it from the keyboard tab order and autocomplete="off" so browsers do not auto-fill it.

The fetch alternative: no page reload

If you want a smoother experience — an inline success message without a full page navigation — intercept the submit event and send the data with fetch. Add the Accept: application/json header to tell Formcrest you want a JSON response instead of a redirect.

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

form.addEventListener('submit', async (event) => {
  event.preventDefault();

  const response = await fetch('https://api.formcrest.com/v1/submit/abc123', {
    method: 'POST',
    headers: { Accept: 'application/json' },
    body: new FormData(form),
  });

  const result = await response.json();

  if (response.ok && result.ok) {
    document.querySelector('#success').hidden = false;
    form.reset();
  } else {
    document.querySelector('#error-msg').textContent = result.message;
  }
});

Build FormData from the form element — the browser sets the correct Content-Type automatically, and the _honey field is included with everything else. A successful submission returns { "ok": true, "submissionId": "sub_abc123" }. For a fuller walk-through including error field handling, see /docs/installation/javascript.

Where submissions go, and how long they are kept

When a submission passes validation and spam checks, Formcrest stores it in the dashboard and emails all the captured fields to your verified destination email. The email includes the submission timestamp and a link to the dashboard entry.

Retention periods depend on your plan: 30 days on Free, 90 days on Pro, and unlimited on Agency. CSV export is available on every plan, so you can always download a copy before any retention window closes.

A quick note on spam at higher volume

The honeypot catches the majority of automated spam on low-traffic sites. If you are running a form on a page that gets significant traffic — or a page that appears in a public directory bots scan frequently — you may want to also enable Cloudflare Turnstile. It is a privacy-friendly challenge that is invisible to most real visitors and available on the free plan. Formcrest also applies automatic rate limiting at the edge; burst attacks are rejected before they reach your quota.

Ready to go

Adding a contact form to a static site takes less than ten minutes:

  1. Create a Formcrest form and verify a destination email address
  2. Copy the endpoint URL into your form's action attribute
  3. Add the _honey honeypot field
  4. Optionally set a custom success redirect

Start for free — no credit card required. The Free plan includes 500 submissions per month, which is enough for most personal sites, portfolios, and small businesses. When you outgrow it, upgrading to Pro or Agency does not require changing a single line of your form HTML.

Ship your form in minutes

Point any HTML form at Formcrest — validation, spam filtering, and delivery included. Free for 500 submissions a month, no credit card.

Get started free