Blog Wire up a contact form with a serverless handler

Wire up a contact form with a serverless handler

2 min read

Wire up a contact form with a serverless handler
TL;DR Point your form at a serverless function or a form API instead of a server. It validates the input, checks for spam, and emails you the message. Your static site stays static, and you get submissions in your inbox without running a backend.

A static site does not mean a site without a working contact form. You just move the server part off your site and onto a small endpoint that runs only when someone submits. Here is the pattern.

The shape of it

Your form posts to an external endpoint instead of a server on your own site. That endpoint, a serverless function you write or a hosted form API, does the work: validate the input, filter spam, and email you the message. Your site stays static; the dynamic bit runs on demand somewhere else.

Point the form at a handler

<form action="https://your-endpoint.example/submit" method="POST">
  <input name="name" required />
  <input name="email" type="email" required />
  <textarea name="message" required></textarea>
  <input name="company" class="hidden" tabindex="-1" autocomplete="off" />
  <button type="submit">Send</button>
</form>

That company field is a honeypot, hidden from real users. Bots fill it in; people do not.

The handler

A minimal serverless function validates, checks the honeypot, and emails you:

export async function POST(request) {
  const data = await request.formData();
  if (data.get("company")) return new Response("ok"); // honeypot tripped
  if (!data.get("email") || !data.get("message")) {
    return new Response("Missing fields", { status: 400 });
  }
  await sendEmail({
    to: "you@example.com",
    subject: `Contact from ${data.get("name")}`,
    text: data.get("message"),
  });
  return new Response("Thanks", { status: 200 });
}

Use a form API instead if you would rather not host even this; the idea is the same.

Keep out the spam

  • A honeypot field catches most bots for free.
  • Validate on the server, not just in the browser, since anyone can post directly to the endpoint.
  • Rate-limit so one source cannot flood you.
  • Add a captcha only if needed, because it adds friction for real visitors.

Why this fits a static site

The form is the one common dynamic feature a content site needs, and this keeps it small. Your pages stay fast static files, and the only server work happens for a few seconds when someone actually writes to you. No backend to run, patch, or pay for around the clock, just an endpoint that wakes up on submit.

FAQ

How does a static site send a form without a backend?

The form posts to an external endpoint: either a small serverless function you write, or a hosted form API. That endpoint does the server work, validating, filtering spam, and emailing you, so your site itself needs no server.

How do I stop spam without a captcha?

A honeypot field that real users never fill, plus basic rate limiting and validation on the handler, stops most automated spam. Reserve a captcha for when bots get past the simpler measures, since it adds friction for real people.

Where does the message go?

The handler emails it to you, usually through a transactional email service or a form API's built-in delivery. You can also store submissions, but for a simple contact form, emailing yourself is enough.