Adding a contact form to an Astro site

July 22, 2026

Astro's whole philosophy is shipping less JavaScript, and a contact form is the perfect place to honor it: the correct amount of JavaScript for a contact form is none. You need HTML that POSTs somewhere, and somewhere for it to POST.

1. Get a form endpoint

Create a NormForms form (free, ~30 seconds). You'll get a URL like https://normforms.com/f/x7Kp2mQ9RtLw.

2. Drop the form in any .astro file

It's plain HTML, so it goes anywhere markup goes — a page, a component, a layout:

---
// src/components/ContactForm.astro — no frontmatter needed, it's just HTML
---
<form action="https://normforms.com/f/YOUR_TOKEN" method="POST">
  <input type="text" name="name" placeholder="Your name">
  <input type="email" name="email" placeholder="Your email">
  <textarea name="message" placeholder="Your message"></textarea>
  <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
  <button type="submit">Send</button>
</form>

Style it with your existing CSS — scoped styles, Tailwind, whatever your project uses. The _gotcha field is the spam honeypot; keep it exactly as-is, invisible and empty.

3. Test it before you deploy

Submit from npm run dev on localhost and it's automatically test mode — delivered to your email with a [Test] prefix, not counted against your quota. When you deploy, set your site's domain in the form's settings and submissions from anywhere else get silently dropped.

What you skipped

No adapter change (your site stays fully static — no need to switch to SSR or add an Actions endpoint for one form), no serverless function, no email provider account, no spam tuning. Visitors get redirected to a thank-you page (or your own URL, configurable), and every submission is stored in your dashboard with delivery status — so nothing is lost even if email misbehaves.

Add your form →