Adding a contact form to an Astro site

July 22, 2026

Astro's whole philosophy is less JavaScript, and a contact form is where that philosophy gets to prove itself: the right amount of JavaScript for a contact form is none. You need HTML that POSTs somewhere, and somewhere for it to POST.

1. Grab a form endpoint

Set up a NormForms form (free, ~30 seconds), and you'll get back a URL like https://normforms.com/f/x7Kp2mQ9RtLw.

2. Drop the form into any .astro file

It's plain HTML, so it goes wherever 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">
  <label for="nf-name">Name</label>
  <input id="nf-name" type="text" name="name" autocomplete="name" required>

  <label for="nf-email">Email</label>
  <input id="nf-email" type="email" name="email" autocomplete="email" required>

  <label for="nf-message">Message</label>
  <textarea id="nf-message" name="message" required></textarea>

  <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
  <button type="submit">Send</button>
</form>

Style it with whatever CSS your project already uses: scoped styles, Tailwind, doesn't matter. The _gotcha field is the spam honeypot; keep it exactly as it is, invisible and empty.

3. Test it before you ship

Submit from npm run dev on localhost and it's automatically test mode: delivered to your email with a [Test] prefix, and it doesn't count 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 get to skip

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 gets stored in your dashboard with delivery status, so nothing's lost even if email acts up. Past your plan's monthly limit, submissions are still stored and still readable: only the email pauses until you upgrade.

Ship your form →