Blog

A contact form that can’t lose your message

A contact form has one job, and it is easy to build one that fails at it without anyone noticing. The visitor types a careful message, presses send, sees a friendly “thanks”, and the message goes nowhere. You never learn about it, and they never hear back.

When we built the form for tuwastudio.com we started from that failure and worked backwards. This is what we ended up with, and the two things that cost us time when we switched it on.

Never pretend to send

For its first day and a half live, our form had no way to deliver anything, because the email service wasn’t connected yet. It didn’t pretend otherwise. It checked what the visitor had typed, then opened a ready-to-send email with every field already filled in, and said so on the page.

That fallback stayed in the finished form. It is still what happens if delivery is ever unavailable, so a message is never quietly dropped.

Check for spam on the server, not just in the page

We use Cloudflare’s Turnstile check instead of a puzzle. It shows a small widget in the page, which hands the browser a token. The token alone proves nothing, because a bot can invent one. The server has to send it back to Cloudflare and get a yes before anything is delivered.

Around that there are a few plain defences: a hidden field only bots fill in, which we quietly ignore, a size limit on what the server will accept, and a rule that it only takes submissions from our own site. None of it is clever. All of it happens before an email is sent.

Deliver it so you can simply reply

Accepted messages go to the studio inbox through Resend, an email delivery service. The visitor’s own address is set as the reply-to, so answering an enquiry is just pressing Reply, with no copying addresses out of a table.

If that delivery fails, the visitor keeps everything they typed and gets the same ready-to-send email as before. One of our tests deliberately makes delivery fail, to check exactly that.

Send from a subdomain

We send the form’s email from a subdomain, send.tuwastudio.com, rather than from the main domain. It has its own authentication records, so the mail passes the same anti-spoofing checks without touching the records that protect the studio’s everyday mailbox. After adding them we looked up the main domain’s mail records again to confirm nothing had changed.

Two traps when switching it on

The public key is baked in when the site is built. Turnstile has a public site key and a private secret. The private one is read by the server when a message arrives. The public one is written into the page when the site is built. We added both in the dashboard and the live form didn’t change, because the page had already been built without the key. Secret values are the same: they only apply to a new deployment. Until we redeployed, the form’s endpoint kept answering “not configured”.

Automated tests can’t prove the widget works. Our tests use a stand-in email service and Cloudflare’s test keys, and they cover both modes: eight tests in all, passing. But in an automated browser the real widget didn’t appear, and Turnstile often refuses to run there. So the final check was a person filling in the form on the live site and confirming the email arrived.

There is a safe health check that sends nothing: post an empty form to the endpoint. “Not configured” means a variable is missing. “Invalid” means the endpoint is working and rejecting the empty form, which is what you want.

Questions to ask about your own form

  • If sending fails, does the visitor find out, and do they keep what they typed?
  • Is the spam token verified on the server, or only checked in the page?
  • Does a reply go to the person who wrote, not to a no-reply address?
  • Has a real person submitted it from the live site since the last change?

A form that fails safely is a small part of a website, and one of the parts a visitor remembers when it goes wrong. If yours has been quietly losing messages, or you are starting a site from scratch, that is what our web design work covers.

Want a site built this carefully?

Tell us what you’re building. A price and a date come back in the first reply.

Start a project