# Forms

Contact, signup and quote forms that look like your site: build them in the admin or in your own code, get every submission in an inbox and by email, with spam protection that needs no setup.

**Beta.** Forms is in beta: it works, but things may still break. Tell us if something does: open an issue at https://github.com/sundoggs/support/issues/new.

Category: [Forms and leads](/categories/forms-and-leads.md)

## Requirements (tell the site owner before buying)

- Cloudflare plan: Cloudflare free plan
- Works on: Cloudflare Workers, Cloudflare Pages
- Version: 0.7.3 (needs site layer 0.23.0 or later; it comes in the same download)
- Runs on the Cloudflare free plan, in the same D1 database as your other site apps. Submissions never leave your Cloudflare account (except to your own email and webhook).
- Optional, free: email notifications. Turn on Cloudflare Email Routing for your domain and verify the address that should receive them (one click in a Cloudflare email). Workers sites add a send_email binding; Pages sites add an API token secret (Pages has no email binding).
- Forms submit to /forms/<name> (POST only, so a page at /forms keeps working). Forms are inserted into pages as they're served, so page views run through the site apps (as with link tagging).
- Works with any framework. Optional, free: Cloudflare Turnstile as a human check (a site key and a Worker secret). Not yet: file uploads, auto-replies to the person who submitted (these need Workers Paid).
- Cost per visit: page views add no writes (the automatic clean-up of old spam and submissions checks after a page view at most every 6 hours: one small write to claim the run, plus the deletions). A submission is about 3 small writes (the submission, the contact and an event) and is limited to 8 per visitor per 10 minutes (messages that go to Spam count too). Submissions are never dropped by the logging budget; if the Cloudflare free database limit is reached they are emailed to you when email is set up. Visit sources are counted by core: page views are added up in memory and saved in a few small writes about every 20 seconds, within the daily write budget; at the Cloudflare free limits counting pauses and the site is unaffected.

Settings:
- `TURNSTILE_SITE_KEY` (optional): Optional Turnstile human check: the widget's public site key (or set it in Forms, Settings).
- `TURNSTILE_SECRET_KEY` (optional): Optional Turnstile human check: the widget's secret key. Store it as a Worker secret; it is never saved in the database.
- `SITE_EMAIL` (optional): Workers: send_email binding for notifications.
- `SITE_EMAIL_BINDING` (optional): Workers: the name of an existing send_email binding to use instead of SITE_EMAIL (e.g. EMAIL).
- `SITE_EMAIL_API_TOKEN` (optional): Pages: API token with Email Sending: Edit.
- `SITE_EMAIL_ACCOUNT_ID` (optional): Pages: the Cloudflare account id for that token.

## Works with

Cloudflare Workers, Cloudflare Pages, Astro, Next.js (with OpenNext), Vite, Hugo, Plain HTML sites, Vanilla JavaScript, Cloudflare Turnstile, Zapier (via webhooks), Make (via webhooks).

## Works with your other apps

Connects with no setup, in any install order: [Popups](/apps/popups.md), [Waitlist](/apps/waitlist.md), [Social Proof](/apps/proof.md), [Analytics](/apps/analytics.md), [Tag Manager](/apps/tags.md).

## Price

Free

## What's new in 0.7.3

- Marked as beta: it works, but things may still break. The admin shows where to report a problem.

## Included

- Site admin dashboard (installed with your first app, no extra cost)
- Updates for as long as the app is free (you keep it if that ever changes)
- An agent skill and install guide
- Free License: any number of sites

## Install

Free on every site. The site owner signs in (the client opens the browser), or you send an API key. Then call the MCP tool `get_download` for the site's domain with `apps: ["forms"]`: it claims the app first if the account doesn't own it (or claim it on its own with `claim_free_app`) and gives the files.

The prompt the app page gives the owner to paste into their agent:

```
Install the Forms app (id: forms) from the Sundogs site apps store on this site.
First read https://sundo.gs/apps/forms.md and tell me what it needs and what it costs.
It's free: get_download claims it for me if I don't have it yet.
Then download it with get_download for this site's domain. Follow the install guide (site-apps/INSTALL.md in the download, also at https://sundo.gs/install-guide.md).
Check it with the install guide's step 6 (the public status, then the self-test once you can sign in to the admin) and tell me what's next.
(Not connected to the store yet? See https://sundo.gs/agents.)
```

## Related playbooks

- [Add a contact form with spam protection to a static site on Cloudflare](/playbooks/contact-form-turnstile-d1.md): A working contact form for a static site on Cloudflare Pages: a Pages Function receives the post, Turnstile blocks bots, D1 stores the messages. No third-party form service.
- [Email signup popups that grow your list without hurting SEO or accessibility](/playbooks/email-signup-popups-without-hurting-seo.md): What makes an email popup earn signups instead of annoying people: the offer, timing, how often it shows, how it behaves on phones, what Google says about intrusive interstitials, keyboard and screen-reader access, and consent. Includes a minimal accessible popup with the native dialog element, and the list of what's hard to get right on a real site.
- [How to vibecode an affiliate site on Next.js (and host it free on Cloudflare)](/playbooks/vibecode-affiliate-site-nextjs.md): Build a whole affiliate site with an AI coding agent, start to finish: pick a niche you can win, plan the pages that earn (best-of lists, comparisons, reviews), set up Next.js as a static export, write content Google rewards, get the SEO basics right, deploy on the Cloudflare free plan, then monetise with affiliate links and an email list, and measure which pages make money. With prompts you can give your agent at each step.
- [Move a static site from Netlify, Vercel or GitHub Pages to Cloudflare](/playbooks/move-static-site-to-cloudflare.md): Move a static site (Astro, Hugo, Eleventy, Vite, Next.js static export, Jekyll or plain HTML) to Cloudflare Workers with static assets or Pages, keeping its redirects, headers and environment variables, replacing Netlify Forms, and switching the domain over with a tested rollback. The old host stays live until you're sure.
- [Start a new website on Cloudflare Workers, with or without GitHub](/playbooks/start-a-site-on-cloudflare.md): No site yet? An AI agent creates one on the Cloudflare free plan, puts it live on a free workers.dev address, and adds the free site apps (a contact form inbox and a health page). With GitHub you get automatic deploys on every push; without GitHub it deploys straight from your computer. Includes the Cloudflare temporary accounts, where the agent deploys first and you claim the site within an hour.
