Back to blog

    Handle Form Submissions Without a Backend

    A practical guide to collecting form data from static sites, JAMstack apps, and single-page applications — no server required.

    Handle Form Submissions Without a Backend

    Static sites are fast, cheap to host, and dead simple to deploy. But they have one notorious weak spot: forms. With no server-side code running, how do you receive a contact form submission?

    This post covers the options, their trade-offs, and the simplest path to production-ready form handling.

    Option 1: HTML Form to a Form Service

    The cleanest approach for most sites. Point your form's action attribute at a service URL — the service handles receiving, storing, and notifying you.

    1<form action="https://formboost.app/f/YOUR_ID" method="POST">
    2  <input type="text" name="name" placeholder="Your name" required />
    3  <input type="email" name="email" required />
    4  <textarea name="message" placeholder="Your message"></textarea>
    5  <button type="submit">Send</button>
    6</form>

    Pros: Zero JavaScript, works everywhere, handles spam, sends notifications. Cons: Redirects to a thank-you page on submit (configurable).

    Option 2: Fetch API (AJAX Submit)

    If you want to stay on the page after submission, use fetch to post the data:

    1async function handleSubmit(event) {
    2  event.preventDefault();
    3
    4  const form = event.target;
    5  const data = Object.fromEntries(new FormData(form));
    6
    7  try {
    8    const res = await fetch("https://formboost.app/f/YOUR_ID", {
    9      method: "POST",
    10      headers: { "Content-Type": "application/json" },
    11      body: JSON.stringify(data),
    12    });
    13
    14    if (res.ok) {
    15      form.reset();
    16      showSuccess("Message sent!");
    17    } else {
    18      throw new Error("Submission failed");
    19    }
    20  } catch {
    21    showError("Something went wrong. Please try again.");
    22  }
    23}
    24
    25document.querySelector("form").addEventListener("submit", handleSubmit);

    Pros: Full control over UX, no page redirect, easy to add loading states.

    Option 3: React (with react-hook-form)

    For React apps, integrating with a form service is just as simple:

    1import { useForm } from "react-hook-form";
    2
    3export function ContactForm() {
    4  const { register, handleSubmit, reset, formState: { isSubmitting } } = useForm();
    5
    6  const onSubmit = async (data) => {
    7    await fetch("https://formboost.app/f/YOUR_ID", {
    8      method: "POST",
    9      headers: { "Content-Type": "application/json" },
    10      body: JSON.stringify(data),
    11    });
    12    reset();
    13  };
    14
    15  return (
    16    <form onSubmit={handleSubmit(onSubmit)}>
    17      <input {...register("email", { required: true })} type="email" />
    18      <textarea {...register("message")} />
    19      <button type="submit" disabled={isSubmitting}>
    20        {isSubmitting ? "Sending..." : "Send"}
    21      </button>
    22    </form>
    23  );
    24}

    Spam Protection

    Any public form endpoint will attract bots. A few layers of defense:

    1. Honeypot fields

    A hidden field that only bots fill in:

    1<input
    2  type="text"
    3  name="_honey"
    4  style="display:none"
    5  tabindex="-1"
    6  autocomplete="off"
    7/>

    2. AI filtering

    Formboost runs every submission through an AI classifier trained on millions of spam examples. You get a spam score with each submission and automatic filtering in strict mode.

    3. Rate limiting

    Formboost enforces per-endpoint rate limits so one abuser can't flood your inbox.

    Choosing a Service

    FeatureFormboostDIY serverless
    Setup time< 1 minuteHours
    Spam protectionAI-poweredYou build it
    Email notificationsBuilt-inConfigure SES/SendGrid
    DashboardYesNo
    CostFree tier availableHosting + services

    For most projects, a dedicated form service pays off quickly. The free tier on most services handles personal sites indefinitely, and paid tiers are far cheaper than the engineering time to build it yourself.

    Summary

    • Use a plain <form> with action= for maximum simplicity
    • Use fetch or a React hook when you need to control the post-submit UX
    • Add honeypot fields and use a service with AI filtering to block spam
    • Pick a service with a generous free tier so you can start without commitment

    Start collecting submissions for free →