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.