<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alen | SmartForm AI</title>
    <description>The latest articles on DEV Community by Alen | SmartForm AI (@alen_builds).</description>
    <link>https://dev.to/alen_builds</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4151203%2F6e706cdf-6f6f-4746-9053-760e3adc0a9a.png</url>
      <title>DEV Community: Alen | SmartForm AI</title>
      <link>https://dev.to/alen_builds</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alen_builds"/>
    <language>en</language>
    <item>
      <title>Adding a Contact Form to a Static Site in 2026: 5 Approaches I Actually Tried (and What I'd Build Differently Today</title>
      <dc:creator>Alen | SmartForm AI</dc:creator>
      <pubDate>Wed, 30 Sep 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/alen_builds/adding-a-contact-form-to-a-static-site-in-2026-5-approaches-i-actually-tried-and-what-id-build-1boa</link>
      <guid>https://dev.to/alen_builds/adding-a-contact-form-to-a-static-site-in-2026-5-approaches-i-actually-tried-and-what-id-build-1boa</guid>
      <description>&lt;p&gt;If you've ever shipped a JAMstack site — Next.js, Astro, Hugo, Gatsby, Eleventy — you've hit the same wall I have: &lt;strong&gt;forms don't fit the static model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No server. No PHP. No Node runtime. Just HTML, CSS, and JavaScript being served from a CDN. And then someone asks: &lt;em&gt;"Can you add a contact form?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Over the past year I've built contact forms for six different static sites — a personal blog, two client marketing sites, a SaaS landing page, an open-source project page, and a documentation portal. I went through every approach I could find before settling on one. This post is the field report — what worked, what broke, and what I'd do differently today.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A note on bias before we start&lt;/strong&gt;: I'm the developer behind &lt;a href="https://usesmartform.com" rel="noopener noreferrer"&gt;SmartForm AI&lt;/a&gt;, an AI-augmented form backend for static sites. I'll mention it once at the bottom of this post because it directly answers a problem I couldn't solve with the other four approaches. Everything before that is vendor-agnostic. If you only want the comparison, scroll to the matrix and skip the rest.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The problem, stated honestly
&lt;/h2&gt;

&lt;p&gt;A static contact form is deceptively simple on the surface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Send&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the second you press "deploy", five real questions show up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Where does the submission go?&lt;/strong&gt; (Email? Database? Slack?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How do I stop spam?&lt;/strong&gt; (CAPTCHA? Honeypot? AI?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How do I attach files?&lt;/strong&gt; (Resume uploads, screenshots)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How do I stay notified?&lt;/strong&gt; (Email? Slack? Webhook to my CRM?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What happens when traffic spikes?&lt;/strong&gt; (Someone posts my form on Reddit and 5,000 bots show up in 10 minutes)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every approach below answers these differently. Let's walk through them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Approach 1: Platform-native forms (Netlify Forms / Cloudflare Forms)
&lt;/h2&gt;

&lt;p&gt;The path of least resistance. If you're already deploying on Netlify or Cloudflare Pages, you can usually turn on form handling with a single attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"contact"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt; &lt;span class="na"&gt;data-netlify=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Send&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Netlify captures submissions, gives you a UI in the dashboard, and even supports webhooks.&lt;/p&gt;

&lt;h3&gt;
  
  
  What works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Zero configuration.&lt;/li&gt;
&lt;li&gt;Spam filtering included (basic honeypot).&lt;/li&gt;
&lt;li&gt;Free tier is generous for hobby projects.&lt;/li&gt;
&lt;li&gt;Works with any static-site generator that produces HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What breaks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vendor lock-in.&lt;/strong&gt; Migrating your static site off Netlify also means rewriting your form backend. I learned it the hard way on a Gatsby project when the build started failing after a Gatsby 4 → 5 upgrade and I had to move to Vercel. Forms broke silently. Submissions just stopped appearing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pricing model has changed twice in two years.&lt;/strong&gt; Netlify switched to credit-based plans in late 2025 — under the new model, Forms submissions are free and unlimited across all tiers, but legacy customers are still being metered on per-site limits. If you're reading tutorials written before 2025, double-check the actual current numbers — most of them are out of date.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No AI.&lt;/strong&gt; Spam filtering is the standard honeypot plus Cloudflare Turnstile. Residential-proxy bot traffic that fills real-looking fields will sail through.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lead intelligence.&lt;/strong&gt; Every submission is just rows in a UI. No classification, no AI summary, no Slack routing based on intent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Verdict
&lt;/h3&gt;

&lt;p&gt;Best for: tiny personal sites already deployed on Netlify. Worst for: any business site where form data is revenue.&lt;/p&gt;




&lt;h2&gt;
  
  
  Approach 2: SaaS form backends (Formspree, Web3Forms, Basin, Forminit)
&lt;/h2&gt;

&lt;p&gt;The de-facto option for most static sites today. You point your HTML form at a third-party endpoint and they handle storage, email, spam, and a dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"https://formspree.io/f/YOUR_FORM_ID"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Send&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or via fetch for a SPA-style experience:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://formspree.io/f/YOUR_FORM_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Portable.&lt;/strong&gt; Works on Vercel, Netlify, Cloudflare, GitHub Pages, raw S3, anywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mature spam filtering.&lt;/strong&gt; Most services now offer reCAPTCHA, honeypot, or ML-based filtering (Formspree's "Formshield", Basin's reCAPTCHA + content filter) out of the box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhooks and Zapier-style integrations&lt;/strong&gt; for routing to Slack, CRMs, etc. This is the killer feature for small teams.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decent free tiers&lt;/strong&gt; (Formspree 50/mo, Web3Forms 250/mo, Basin 50/mo).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What breaks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free-tier cliff, vendor by vendor.&lt;/strong&gt; Formspree jumps from $0 (50 subs) to $10/month (200 subs) on the Personal plan, then $20/month (2,000) on Professional. Web3Forms' free tier is more generous at 250/mo but its paid plans sit at a similar price-per-submission ratio. Basin is the priciest of the three: Starter is $12.50/mo for 250 submissions and Pro is $40.83/mo for 5,000 — roughly 4× more expensive than Formspree Pro for the same volume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File uploads vary wildly.&lt;/strong&gt; Formspree includes 1GB / 5GB / 10GB on its paid tiers (none on Free). Web3Forms and Basin include file storage on paid tiers only. &lt;strong&gt;Getform rebranded to Forminit in January 2026&lt;/strong&gt; and is the only one of these that bundles 100MB of file storage on the Free tier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lead intelligence.&lt;/strong&gt; Every submission lands in your inbox or dashboard as raw rows. If you want to know "which of these 80 messages are actually sales inquiries worth following up today?", you read them manually.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limits and burst behavior differ across vendors and aren't always published.&lt;/strong&gt; A friend hit a Web3Forms wall during a Product Hunt launch with no published threshold to debug against. Plan for a quiet week before any launch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Verdict
&lt;/h3&gt;

&lt;p&gt;Best for: most personal sites, side projects, low-volume marketing pages. Worst for: anything where form content needs classification or where free-tier → paid is too steep.&lt;/p&gt;




&lt;h2&gt;
  
  
  Approach 3: Serverless functions (Cloudflare Workers, Vercel Functions, AWS Lambda)
&lt;/h2&gt;

&lt;p&gt;The "real engineer" answer. Spin up a serverless function, accept the submission, store it, email it. Full control.&lt;/p&gt;

&lt;p&gt;A minimal Cloudflare Worker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Method not allowed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;405&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Honeypot check&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_gotcha&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Send email via Mailgun&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.mailgun.net/v3/yourdomain.com/messages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Basic &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAILGUN_KEY&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;noreply@yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;you@yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`New contact from &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Total control.&lt;/strong&gt; Your logic, your dependencies, your database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cheap at scale.&lt;/strong&gt; Cloudflare Workers' free tier is 100k requests/day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No vendor lock-in.&lt;/strong&gt; The function is yours to deploy anywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency.&lt;/strong&gt; Edge functions run geographically close to the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What breaks (and this is the long list)
&lt;/h3&gt;

&lt;p&gt;I built this exact setup for a client's marketing site. Here's what I learned:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Spam filtering is now your problem.&lt;/strong&gt; Honeypots catch the dumbest bots, but the moment you deploy on a real domain you get targeted bots that read your source code, fill real-looking fields, and bypass honeypots. You'll be reading raw POST bodies at 2am trying to figure out patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limiting means wiring up KV / Redis.&lt;/strong&gt; Cloudflare KV works but its eventual-consistency model means a bot can hit your form 50 times in the first second before the limit kicks in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email deliverability is a full-time job.&lt;/strong&gt; You need SPF, DKIM, DMARC records, a verified sending domain, and warm-up time. I shipped a form on a Friday and spent the weekend debugging why emails went straight to spam on Gmail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File uploads are painful.&lt;/strong&gt; Multipart parsing in Workers is doable but not pleasant. You'll write a custom parser or pull in a 100KB dependency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No dashboard for clients.&lt;/strong&gt; If the site owner isn't technical, you'll be exporting CSVs and emailing them every Monday.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No analytics.&lt;/strong&gt; Want to know conversion rate from page-view → submission? Build your own analytics pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance is forever.&lt;/strong&gt; Six months in I was still patching edge cases: bot signatures, IP reputation lookups, CSRF tokens, file size limits, MIME type sniffing, GDPR data-export endpoints.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I gave up on this approach after about three months. The function itself was 80 lines. The &lt;em&gt;supporting infrastructure&lt;/em&gt; — spam, email, dashboard, analytics, retention — was easily 2,000 lines and growing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verdict
&lt;/h3&gt;

&lt;p&gt;Best for: engineers with very specific needs who enjoy maintaining infrastructure. Worst for: anyone who wants to spend their time on the actual product, not form plumbing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Approach 4: Pay-per-submission credit packs (FormSubmit)
&lt;/h2&gt;

&lt;p&gt;A middle ground. You host no code. You point a form at FormSubmit and the submission lands in your inbox (and optionally a webhook). No subscription — you buy a one-time credit pack and credits never expire.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"https://formsubmit.co/your@email.com"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Send&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FormSubmit's pricing is unusually honest for this category: &lt;strong&gt;100 credits = 100 submissions = $10&lt;/strong&gt;, scaling down to &lt;strong&gt;$0.07/submission at the 2,500-credit pack&lt;/strong&gt;. Credits never expire, no monthly fee, no tier you have to upgrade into.&lt;/p&gt;

&lt;h3&gt;
  
  
  What works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Almost zero setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spam doesn't consume credits&lt;/strong&gt; — only clean submissions are billed against your balance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No subscription trap.&lt;/strong&gt; A weekend project can buy 100 credits once and use them for years.&lt;/li&gt;
&lt;li&gt;Submissions land directly in your inbox, and webhooks are supported out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What breaks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No persistence.&lt;/strong&gt; Once it's in your inbox, it's gone. No dashboard, no search, no analytics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-submission cost adds up at scale.&lt;/strong&gt; At $0.07/submission, 5,000 clean submissions/month = $350/month — Formspree Pro does the same volume for $20/month. FormSubmit is built for low-volume use, not lead-gen SaaS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lead intelligence.&lt;/strong&gt; No AI classification, no Slack routing by intent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CAPTCHA is per-form opt-in.&lt;/strong&gt; You can disable reCAPTCHA on individual forms (&lt;code&gt;&amp;lt;input type="hidden" name="_captcha" value="false"&amp;gt;&lt;/code&gt;), but doing so hands you back to your own spam problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Verdict
&lt;/h3&gt;

&lt;p&gt;Best for: hobby projects and side sites where you want to pay once and forget about it. Worst for: anything resembling a business with meaningful lead volume.&lt;/p&gt;




&lt;h2&gt;
  
  
  Approach 5: An AI-augmented pipeline (the one I ended up shipping)
&lt;/h2&gt;

&lt;p&gt;After all that, here's the architecture I kept wishing existed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Accept form submission via a simple &lt;code&gt;POST /api/v1/f/{form_id}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run it through an LLM that returns: &lt;code&gt;{ is_spam, spam_confidence, intent, intent_confidence, summary, is_high_value }&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If spam → silently drop, don't email, don't count against quota.&lt;/li&gt;
&lt;li&gt;If not spam → email me a digest with the AI summary prepended.&lt;/li&gt;
&lt;li&gt;Store everything in a database with search, filtering, and CSV export.&lt;/li&gt;
&lt;li&gt;Webhook to Slack/CRM with the classification attached.&lt;/li&gt;
&lt;li&gt;Rate-limit at the edge (Redis sliding window).&lt;/li&gt;
&lt;li&gt;Free tier for hobbyists, paid tier for teams.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is essentially what I ended up building. But before you skip to the bottom and click the link — let me show you the AI layer because it's worth understanding even if you don't use my tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  A realistic AI classification prompt
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;SPAM_PROMPT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are a professional spam-detection specialist.
Analyze the form submission below and decide whether it is spam or legitimate.

Decision criteria:
- Spam ads: product/service promotion, mass-sent links, SEO-bait content
- Malicious messages: phishing links, scams, malware promotion
- Legitimate messages: real customer inquiries, technical support requests, feedback

Only analyze the `message` field.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="n"&gt;INTENT_PROMPT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are a professional form-content analyst.
Identify the user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s true intent.

Intent types:
- sales: pricing, quotes, purchase intent
- support: technical help requests
- general: greetings, generic inquiries
- feedback: comments, suggestions, complaints
- other: anything else

High-value sales signals:
- Clear purchase intent
- Bulk / custom pricing questions
- Specific quantities or budgets
- Enterprise / business inquiry

Generate a concise English summary (under 50 words).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used &lt;code&gt;gpt-4o-mini&lt;/code&gt; for this. Cost per submission: roughly $0.0001. Even at 10,000 submissions/month, that's about a dollar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why this matters in practice
&lt;/h3&gt;

&lt;p&gt;A typical week of form submissions on a B2B SaaS landing page might look like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Raw submission&lt;/th&gt;
&lt;th&gt;Without AI&lt;/th&gt;
&lt;th&gt;With AI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"Hi, I'd like a quote for 50 seats of your enterprise plan."&lt;/td&gt;
&lt;td&gt;You read it Monday morning, reply Tuesday.&lt;/td&gt;
&lt;td&gt;Pings your Slack &lt;code&gt;#sales&lt;/code&gt; channel with &lt;code&gt;intent=sales, is_high_value=true&lt;/code&gt;. Rep replies same day.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Buy cheap watches rolex replica &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt;"&lt;/td&gt;
&lt;td&gt;You mark it as spam.&lt;/td&gt;
&lt;td&gt;Auto-classified, never reaches your inbox.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Your docs are great, but the API auth section is confusing."&lt;/td&gt;
&lt;td&gt;You bookmark it, forget to act.&lt;/td&gt;
&lt;td&gt;Pings &lt;code&gt;#docs&lt;/code&gt; channel with &lt;code&gt;intent=feedback&lt;/code&gt;. PM reads it Friday, files an issue.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's the difference between a contact form and a &lt;em&gt;lead funnel&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The honest comparison
&lt;/h2&gt;

&lt;p&gt;Here's the matrix I wish someone had handed me before I spent three weekends on this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Setup time&lt;/th&gt;
&lt;th&gt;Free tier&lt;/th&gt;
&lt;th&gt;File uploads&lt;/th&gt;
&lt;th&gt;AI features&lt;/th&gt;
&lt;th&gt;Data ownership&lt;/th&gt;
&lt;th&gt;Lock-in&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Platform-native (Netlify Forms)&lt;/td&gt;
&lt;td&gt;2 min&lt;/td&gt;
&lt;td&gt;Unlimited under new credit-based plans (legacy: 100/mo)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Vendor's DB&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SaaS (Formspree / Web3Forms / Basin / Forminit)&lt;/td&gt;
&lt;td&gt;5 min&lt;/td&gt;
&lt;td&gt;50–250 subs/mo&lt;/td&gt;
&lt;td&gt;Paid tiers (Forminit includes 100MB on Free)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Vendor's DB&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Serverless function&lt;/td&gt;
&lt;td&gt;1–2 days&lt;/td&gt;
&lt;td&gt;100k req/day (CF)&lt;/td&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;td&gt;Yours&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form-to-email relay (FormSubmit)&lt;/td&gt;
&lt;td&gt;2 min&lt;/td&gt;
&lt;td&gt;Pay-per-submission credits ($0.07–$0.10/clean submission, never expire)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Your inbox&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI-augmented SaaS&lt;/td&gt;
&lt;td&gt;5 min&lt;/td&gt;
&lt;td&gt;200 subs/mo (free)&lt;/td&gt;
&lt;td&gt;No (use a dedicated service)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yours (CSV export)&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few things to read between the lines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setup time&lt;/strong&gt; is misleading for DIY. "1–2 days" is the function. The infrastructure around it (spam, email, dashboard, analytics) is weeks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data ownership&lt;/strong&gt; matters more than most people think. Vendor shutdowns happen. Price changes happen. If your form is a business-critical lead source, make sure you can export everything as CSV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI features&lt;/strong&gt; aren't a nice-to-have if you get more than ~50 submissions/week. Manual triage stops scaling around that point.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My final solution (and the honest disclosure)
&lt;/h2&gt;

&lt;p&gt;After going through all four of those approaches for actual client work, I ended up building a tool that combines them: an AI-augmented form backend that you embed with a single &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; tag or a single &lt;code&gt;fetch()&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I'm the developer behind &lt;a href="https://usesmartform.com" rel="noopener noreferrer"&gt;SmartForm AI&lt;/a&gt;.&lt;/strong&gt; I built it because I kept needing exactly this stack for my own projects and didn't want to wire it up from scratch for the fifth time.&lt;/p&gt;

&lt;p&gt;What it does that the others don't (or don't do well):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI spam filter + intent classification + lead scoring&lt;/strong&gt; out of the box, using a prompt pipeline similar to what I showed above. Legitimate sales inquiries get a Slack ping with &lt;code&gt;is_high_value: true&lt;/code&gt;. Spam never reaches your inbox — and spam doesn't count against your quota, so a bot storm doesn't burn through your free tier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free tier is 200 submissions/month&lt;/strong&gt; with AI spam filtering included, no credit card. SmartForm AI's free tier pairs the AI layer with a generous submission cap — most form-backend free tiers either cap you at 50 submissions (Formspree, Basin) or strip AI out of the free tier entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pricing stays simple.&lt;/strong&gt; Pro is $9.9/mo for 5,000 submissions; Business is $19.9/mo for 50,000. No "AI filtering $9/mo add-on" bolted on, no tier that excludes webhooks, no surprise overage bills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhooks fire with the AI classification attached&lt;/strong&gt; so you can route sales inquiries to your CRM, feedback to Linear, and ignore spam. Pro tier adds HMAC signing; Business adds retry + dead-letter queue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formspree-compatible API&lt;/strong&gt; — &lt;code&gt;POST /api/v1/f/{form_id}&lt;/code&gt; with JSON or form-data, so the migration from a Formspree-backed site is a single URL change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few honest caveats so you can decide if it fits: SmartForm AI doesn't currently support file uploads natively (if you need resume or screenshot attachments, you'll still wire up a dedicated upload service like Uploadcare or S3 presigned URLs). The Free tier caps at 200 submissions/month without an automatic upgrade — submissions above that get rejected with HTTP 402 rather than silently upgraded. If either of those is a deal-breaker, Formspree or Forminit will serve you better.&lt;/p&gt;

&lt;p&gt;I won't pretend it's the only tool in this space — Formspree, Web3Forms, Basin, and the rest are solid for the 80% case. SmartForm AI is what I reach for when I want the AI layer and don't want to maintain the infrastructure myself.&lt;/p&gt;

&lt;p&gt;Try it if it fits your use case, ignore it if it doesn't. The matrix above is the only thing I'd actually want you to take away from this post.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;If you're starting from scratch today, my recommendation in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Personal site, &amp;lt; 100 subs/month&lt;/strong&gt; → Web3Forms (250/mo free with custom redirect) or Forminit's free tier (100/mo with 100MB file uploads). Both let you avoid any vendor lock-in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Already on Netlify for everything else&lt;/strong&gt; → Netlify Forms. Free and unlimited under the current credit-based plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low-volume side project where you'll send &amp;lt; 1,000 forms over its lifetime&lt;/strong&gt; → FormSubmit credit packs. Buy 100 credits once for $10 and forget about subscriptions — they never expire.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client marketing site, &amp;lt; 1,000 subs/month&lt;/strong&gt; → Formspree Personal ($10/mo, 200 subs) or Pro ($20/mo, 2,000 subs). Mature, boring, works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business-critical lead source, &amp;gt; 500 subs/month&lt;/strong&gt; → AI-augmented SaaS or a serverless function with an LLM in the loop. The manual-triage tax will eat your week otherwise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance-sensitive (healthcare, finance, EU)&lt;/strong&gt; → Self-hosted serverless function with your own database. Data ownership is non-negotiable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Have I missed an approach? I'd love to hear what you're using — especially if you've found something I haven't tried. Drop it in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If this saved you some weekend time, a ❤️ or a follow helps others find it. I'm planning a follow-up on the spam-filtering prompt specifically — let me know in the comments if that's useful.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>jamstack</category>
      <category>webdev</category>
      <category>ai</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
