Back to blog
    By Updated

    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.

    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?

    Key takeaways

    • Static sites have no server to POST to, which is the whole reason form backends exist.
    • The three usual options are a hosted form endpoint, a serverless function you write, or a third-party embed.
    • A hosted endpoint needs no code to maintain and no cold starts.
    • Spam screening, notifications and storage come with the endpoint rather than being yours to build.

    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 screens every submission, and how deeply depends on the plan: heuristics on the free plan, an AI model reading the ambiguous cases from Starter, and that model on every submission from Pro. Each one carries a spam score and a readable reason, with 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

    Next steps

    Start collecting submissions for free →