Static Sites Are Perfect Until You Need a Form. That's Why I Built StaticForm.

I tried Cloudflare Workers, Netlify Forms, and everything else. Nothing worked well. So I built something that does.

StaticForm Team

Static sites are incredible. They’re fast, secure, cheap to host, and you can deploy them anywhere. But then you need to add a contact form and suddenly you’re neck-deep in serverless functions and spam problems. I’ve been there. I tried everything. Let me tell you what doesn’t work, and what I built instead.

The Cloudflare Workers Trap

Cloudflare Workers seemed perfect. Run JavaScript at the edge! Lightning fast! I was excited. Here’s the simple version everyone starts with:

export default {
  async fetch(request) {
    if (request.method === 'POST') {
      const formData = await request.formData();
      const email = formData.get('email');
      
      await sendEmail(email);
      
      return new Response('Success', { status: 200 });
    }
  }
};

Looks clean, right? But you quickly realize you’re just moving the problem. You still need to implement spam protection because Workers don’t magically filter spam. You still need to handle email delivery failures because Workers don’t retry failed emails. You still need to store submissions somewhere because Workers are stateless.

So now you’re managing environment variables for API keys, setting up Cloudflare KV for storage, debugging why your worker is timing out, and realizing you’ve just built a janky backend in a more complicated way. Plus, every time you want to change your form logic, you’re redeploying a Worker. Want to add a new field? Redeploy. Want to change who gets notified? Redeploy.

Netlify Forms Looked Promising

Netlify Forms seemed like the answer. Just add a netlify attribute to your form tag and boom, form handling is built in:

<form name="contact" netlify>
  <input type="text" name="name">
  <input type="email" name="email">
  <textarea name="message"></textarea>
  <button type="submit">Send</button>
</form>

I tried it on three different projects. Every single time, spam destroyed the experience. The first project got 50 spam submissions in the first week. Most were obvious bots, but Netlify’s spam protection let them through anyway. I ended up checking the submissions dashboard every day, manually sorting through garbage to find the two legitimate inquiries.

The second project had better spam filtering enabled, but then it started blocking real submissions. A potential client reached out via another channel asking why our form wasn’t working. It had flagged her submission as spam because she mentioned “investment opportunities” in her message.

The third project hit the submission limit on Netlify’s free tier. 100 submissions sounds like a lot until bots hammer your form. Also, you’re locked into Netlify’s hosting. Want to move to Vercel? Cloudflare Pages? AWS? Congrats, you’re rewriting your form handling.

The Static Site Dilemma

Here’s the fundamental problem: static sites can’t process forms. That’s literally what “static” means. No server, no processing. So your options are all variations of “add a server”: you can build serverless functions, but now you’re writing backend code and deploying it separately from your static site. You can use a third-party service, but most of them are expensive, limited, or both. You can use form providers built into hosting platforms, but you’re locked in, and the spam protection usually sucks. Every approach forces you to choose between complexity, cost, or vendor lock-in.

What I Built Instead

After trying everything and getting frustrated, I built StaticForm. Designed specifically for static sites. It’s just a form action URL. No build-time configuration, no serverless functions, no vendor lock-in:

<form action="https://api.staticform.app/submit/YOUR_FORM_ID" method="POST">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

That’s the whole implementation. It works with Astro, Nuxt, Next.js, Gatsby, Hugo, Jekyll, or plain HTML. Host it on Netlify, Vercel, Cloudflare, GitHub Pages, or a random VPS in your closet. Doesn’t matter.

The spam protection actually works because I built multiple layers: honeypots, IP filtering, content analysis, email validation. I went from 50 spam submissions per week to zero. Email delivery is reliable because StaticForm uses AWS infrastructure and handles retries automatically. If there’s any issue, it queues it and tries again later. Every submission is stored, so even if email completely fails, you can still see the submission in the dashboard. Export to CSV, set up webhooks, connect to Slack, whatever you need.

The Real Comparison

I’ve used all these approaches on real projects. Here’s what actually happens: with Cloudflare Workers, you spend a day setting it up, then spend ongoing time maintaining it. Spam becomes your problem. Email reliability becomes your problem. Storage becomes your problem. With Netlify Forms, setup is instant but spam is a nightmare. You’re locked into Netlify. Good luck if you want to migrate.

With StaticForm, setup takes five minutes and then you never think about it again. Forms just work. Spam is filtered. Emails are delivered. Submissions are stored. I moved five sites to StaticForm last month. I haven’t touched the form code since. They’re just running, collecting submissions, and not bothering me with spam. That’s what a static site form solution should be: something you set up once and forget about.

Get 10 free credits to test your form at app.staticform.app. Pay as you go, or buy a plan to save money.