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.