How to Add Formspree to a Static Site
Static HTML cannot process form submissions on its own—you need a hosted endpoint. Formspree accepts POST requests from plain <form> elements and forwards submissions to your inbox or integrations, which matches the no-backend philosophy of LaunchStatic templates. This guide follows Formspree's documented form setup for static sites and covers spam controls, custom fields, and what to test before launch.
Create a Formspree form
Sign up at formspree.io and create a new form from the dashboard. Formspree assigns a unique form ID used in the action URL. On the free tier you receive a limited number of submissions per month—enough for early waitlists and contact pages. Name the form clearly (for example, "Waitlist – SaaS landing") so notifications are searchable later. Copy the endpoint that looks like https://formspree.io/f/xxxxxxxx; you will paste it into your HTML.
Add the form markup to your HTML
Place a standard form wherever your template expects it—hero section, dedicated contact page, or footer CTA. Set method="post" and point action at your Formspree URL. Each input needs a name attribute; those names appear in email notifications and export files. Use type="email" on email fields so mobile keyboards adapt and Formspree can validate format.
<form action="https://formspree.io/f/xyzabcde" method="post">
<label for="email">Email</label>
<input id="email" name="email" type="email" required
placeholder="you@company.com" autocomplete="email">
<button type="submit">Join waitlist</button>
</form>
LaunchStatic waitlist templates already include accessible labels and large tap targets. Replace the placeholder action URL with your real endpoint before deploying—never commit a teammate's form ID to a public fork unless you intend to share that inbox.
Configure redirects and thank-you UX
By default, Formspree shows its own confirmation screen. For a branded experience, add a hidden field named _next with the absolute URL of a thank-you page on your site. Create a simple thanks.html that confirms submission and links back to your homepage or docs. Use root-relative paths only for internal assets, but _next must be a full https:// URL in production.
<input type="hidden" name="_next" value="https://example.com/thanks.html">
<input type="hidden" name="_subject" value="New waitlist signup">
The optional _subject field customizes the email subject line you receive. Keep it short and identifiable so mobile mail clients do not truncate it.
Reduce spam with honeypot and reCAPTCHA
Public forms attract bots. Formspree supports a honeypot field—an input humans never see but bots auto-fill. Add <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off"> inside the form. Enable reCAPTCHA or hCaptcha in the Formspree dashboard for higher-traffic launches. According to Formspree documentation, spam filtering also learns from reported messages; mark junk in your inbox to improve filtering.
Collect extra fields responsibly
Waitlists often ask for role or company size. Each additional field needs a unique name and a privacy justification if you publish a GDPR-aligned policy. Avoid collecting data you do not need—every field reduces conversion. If you add a message textarea on contact forms, set maxlength to prevent abuse. Document collected fields in your privacy policy (see our privacy policy how-to).
<select name="role" aria-label="Your role">
<option value="">Select role (optional)</option>
<option value="founder">Founder</option>
<option value="engineer">Engineer</option>
<option value="other">Other</option>
</select>
Test locally and on staging
Formspree accepts submissions from any origin once the form ID is public, but you should still test before swapping DNS. Submit a real email to yourself from localhost (file:// pages may block POST—use python -m http.server instead). Confirm the notification arrives, fields map correctly, and _next redirect works. Repeat on your *.pages.dev URL, then again on the custom domain after cutover.
- Form action uses your form ID, not a demo placeholder
- Required fields match what your copy promises
- Thank-you redirect uses https:// production URL
- Honeypot field is present and hidden from screen readers
- Privacy policy mentions Formspree as a processor
Monitor submissions and upgrade paths
The Formspree dashboard lists submissions with export to CSV. Connect Slack or Zapier on paid plans if you need instant team alerts. Watch monthly quotas; if launch traffic spikes, upgrade temporarily rather than losing signups silently. Archive or delete test submissions so metrics reflect real interest.
Accessibility and mobile form UX
Static forms still need accessible markup. Associate every input with a <label> via for and id. Mark required fields visually and with the required attribute. Ensure error messages from Formspree do not trap keyboard users—if you add client-side validation later, mirror errors in text, not color alone. On mobile, use inputmode="email" where appropriate and keep submit buttons full-width for thumb reach. Touch targets should meet the 44×44px guideline referenced in WCAG understanding docs.
Security and secret handling
The form ID in your action URL is public by design—anyone can POST to it. That is why honeypots and dashboard spam settings matter. Never embed private API keys in static HTML; Formspree's browser integration uses the public form endpoint only. If you fork a template repository, rotate the form ID so trolls cannot flood your inbox with submissions triggered from the old public repo. Rate limiting at the edge (Cloudflare WAF rules) can supplement Formspree when a launch post goes viral.
Double opt-in and mailing lists
Formspree delivers email notifications; it is not a full newsletter CRM. If you promise GDPR-compliant marketing emails, connect Formspree to ConvertKit, MailerLite, or similar via integrations or Zapier, and document that flow in your privacy policy. Collect only affirmative consent when required—pre-checked marketing boxes are invalid under EU ePrivacy interpretations for many use cases. A simple waitlist for product updates differs legally from a weekly promotional newsletter; match your form copy to what you actually send.
After launch, export submissions monthly and back them up outside Formspree in case you switch providers. Document the export format (CSV columns) in your ops notes so migrations do not lose historical waitlist context.
Related: Waitlist template Write a privacy policy Form tools roundup Waitlist conversion tips
Do I need JavaScript to use Formspree?
No. A plain HTML form with method="post" and the correct action URL works without any client-side script, which keeps static sites fast and simple.
Can I use Formspree on GitHub Pages or Cloudflare Pages?
Yes. Any static host that serves your HTML can use Formspree because processing happens on Formspree servers, not yours.
Why am I not receiving emails?
Check spam folders, confirm the form ID, and verify you did not leave a placeholder action URL. Some corporate filters block formspree.io until you whitelist it.
Is Formspree GDPR compliant?
Formspree publishes a Data Processing Agreement and privacy documentation. You must still disclose the service in your site privacy policy and lawful basis for collecting emails.
Launch a waitlist this week
Use our waitlist template with Formspree-ready markup, then deploy in minutes.
Get waitlist template Add custom domain