Receive form submissions and handle spam
A contact form needs a real receiving service. A “Thanks” message is not proof that anything was sent.
Send a real test submission, check where it arrives and prevent unrestricted public access to messages.
For an in-page form, first complete your chosen online data setup. A simple email link can be added to the basic site without a database.
Let’s do this
- 1In your AI helper
Choose the smallest useful contact method
A normal email link opens the visitor’s mail app and needs no form service. Use it if that is enough. If you need an in-page form, decide which fields are required and where submissions should arrive. Start without file uploads.
MDN: sending form data (opens a new tab) - 2In your AI helper
Choose one receiving route
For the Cloudflare route, use a Pages Function that validates a submission and writes to a private D1 submissions table. You read messages through the signed-in dashboard at first. For the Supabase route, use a protected server function with suitable database rules. Do not let browsers list everyone’s submissions.
- 3In your AI helper
Build honest form behaviour
Ask for visible labels, required-field checks, length limits and server-side validation. Disable repeated sending while waiting. Show success only after the receiving service confirms the message was accepted. Include an error message and retry when it fails. Never silently throw away a submission.
- 4In Cloudflare
Add a free spam check if the form is public
Cloudflare Turnstile can check likely automated submissions. Create a widget for your domain and use its public site key in the page. Put its secret key in the Pages server secrets, then redeploy. The server must verify each token through Siteverify before accepting a submission. Add request limits too; a checkbox by itself is not protection.
Cloudflare: validate Turnstile on the server (opens a new tab) - 5In your browser
Test the receiving end
Submit a clearly labelled test from the live site. Sign into the database dashboard and confirm the record arrived. Try an invalid field, a failed spam check and a repeated click. Confirm the public site has no endpoint that returns the private submission list.
- 6In your AI helper
Add email notifications only if needed
Saving a form does not email you. To send notifications, choose a transactional email provider, check its free allowance, sender verification and pricing, and keep its secret key on the server. Test delivery to your own inbox, including spam. Explain what the form stores and how long you keep it.
A message for your AI helper
Add a real contact form to my first website only if an email link is not enough. Use the existing Cloudflare Pages Functions + D1 route, or the chosen Supabase server route, without adding a second database. Validate fields on the server, limit lengths and repeated submissions, and keep received messages private. Add free Turnstile if appropriate, with server-side Siteverify validation and a server-held secret. Show success only after confirmed acceptance. Do not claim email delivery unless an email service is configured and tested. Guide me through submitting a test and finding it at the receiving end.
What you should see
A real live submission arrives in the intended private store or inbox, and failed submissions produce a useful error.
If you get stuck
Checked 7 September 2026. Screens can change; the official guides below have the latest steps.
MDN: sending form dataCloudflare Pages: D1 bindingsCloudflare Pages: secretsCloudflare: Turnstile plansCloudflare: validate Turnstile on the server