Back to blog

How to Add a Contact Form to Your Astro Site Without a Backend

If you are building a portfolio, landing page, or blog with Astro, chances are you need a contact form.

But here is the catch:

Astro is a static site framework. It generates fast, lightweight HTML with no server-side backend. That means your forms have nowhere to send data by default.

Setting up a backend to handle a contact form feels unnecessary work for most Astro developers. And that is exactly why thousands of people search for things like "Astro contact form without backend" every month.

In this guide, you will learn exactly how to handle form submissions in your Astro site without building your own backend, using Formgrid.

We will walk through a step-by-step tutorial with code you can copy, paste, and deploy immediately.


Why Astro Developers Need a Form Backend

Astro builds static HTML files. That is its biggest strength. Fast. Lightweight. No server required.

But static HTML forms cannot process their own submissions. When someone clicks submit on a plain HTML form, the data has nowhere to go unless something on the server receives it.

Setting up your own backend just to collect form submissions means:

You need a server running Node, PHP, or Python. You need routing, validation, and spam protection. You must configure email notifications. You need a database to store submissions. You must maintain it indefinitely.

All this work just to receive a message from a website visitor.

That is why most Astro developers use a form submission service instead.


Popular Ways to Handle Forms in Astro Without a Backend

Formspree

One of the oldest form backend services. Simple and reliable, but paid plans get expensive quickly. Google Sheets integration starts at $90/month.

Netlify Forms

A great free option, but only works if your site is deployed on Netlify. If you host on Vercel, Cloudflare, or GitHub Pages, it does not work at all.

Formgrid.dev (Open-Source)

A newer privacy-first alternative that works with any Astro site, regardless of where it is deployed.

Features include:

Open source under MIT license

Works on any website or deployment platform

Email notifications for every submission

Spam protection with a honeypot and rate limiting

Optional Proof-of-Work CAPTCHA

Free plan: unlimited forms and 50 submissions per month

Google Sheets sync on the Professional plan at $16/month


Why Use Formgrid for Your Astro Site

Formgrid is a privacy-first open source alternative to services like Formspree and Netlify Forms. Here is why it works well with Astro specifically:

Instant email notifications: Receive every submission immediately in your inbox with clean, organized formatting.

Works anywhere: Unlike Netlify Forms, Formgrid works whether you deploy on Vercel, Netlify, Cloudflare Pages, GitHub Pages, or your own server.

Spam protection: Built-in honeypot fields, rate limiting, and optional Proof-of-Work CAPTCHA keep bots out.

Self-hostable: Run Formgrid on your own infrastructure using Docker for complete data control.

Submission dashboard: Every submission is saved to your Formgrid dashboard. No submission is ever lost, even if the email fails to arrive.

Open source: MIT license, no vendor lock-in, fully auditable.

Whether you are a solo developer building a portfolio or a freelancer building client websites, Formgrid makes form handling fast, simple, and secure.


Step 1: Create a Formgrid Account

Go to formgrid.dev and sign up using Google or Email. No credit card required.

Image description

Formgrid offers free and paid plans. The free plan includes:

Unlimited forms

50 submissions per month

Email notifications

Spam protection


Step 2: Create a New Form

Once logged in, go to your dashboard and click New Form.

Give your form a name:

"Astro Contact Form"
"Portfolio Enquiry Form"  
"Client Contact Form"

Click Create Form.

Image description


Step 3: Copy Your Endpoint URL

After creating your form, you will land on the form overview page.

Go to the Overview tab and copy your unique endpoint URL. It looks like this:

https://formgrid.dev/api/f/your-form-id

Image description

You will use this URL as the action attribute on your HTML form or inside your fetch call.


Step 4: Add the Form to Your

Astro Site

There are two ways to add Formgrid to your Astro site. Choose the one that fits your project.

Option A: Simple HTML Form

This is the fastest approach and requires zero JavaScript. Perfect for straightforward contact forms.

In any .astro file, add this code:

<form
  action="https://formgrid.dev/api/f/your-form-id"
  method="POST"
>
  <label for="name">Your Name</label>
  <input
    type="text"
    id="name"
    name="name"
    required
  />

  <label for="email">Email Address</label>
  <input
    type="email"
    id="email"
    name="email"
    required
  />

  <label for="message">Your Message</label>
  <textarea
    id="message"
    name="message"
    rows="5"
    required
  ></textarea>

  <!-- Honeypot spam protection -->
  <input
    type="text"
    name="_honey"
    style="display:none"
  />

  <button type="submit">Send Message</button>
</form>

Replace your-form-id with the actual endpoint slug from your Formgrid overview tab.

When someone submits the form the page redirects to a Formgrid confirmation page. You receive the submission instantly by email.

Option B: Fetch-Based Form

with No Page Redirect

This approach keeps the user on your page after submission and shows a success message without any page reload. It uses Astro's built-in <script> tag.

Create a new file called ContactForm.astro in your components folder and add the following:

---
// ContactForm.astro
---

<div class="form-wrapper">
  <form id="contact-form">

    <!-- Honeypot spam protection -->
    <input
      type="text"
      name="_honey"
      style="display:none"
      aria-hidden="true"
    />

    <div class="field">
      <label for="name">Your Name</label>
      <input
        type="text"
        id="name"
        name="name"
        placeholder="Allen Jones"
        required
      />
    </div>

    <div class="field">
      <label for="email">Email Address</label>
      <input
        type="email"
        id="email"
        name="email"
        placeholder="allen@example.com"
        required
      />
    </div>

    <div class="field">
      <label for="message">Message</label>
      <textarea
        id="message"
        name="message"
        rows="5"
        placeholder="Write your message here"
        required
      ></textarea>
    </div>

    <p 
      id="success-message" 
      style="display:none; color: green;"
    >
      Your message was sent successfully.
    </p>

    <p 
      id="error-message" 
      style="display:none; color: red;"
    >
      Something went wrong. Please try again.
    </p>

    <button type="submit" id="submit-btn">
      Send Message
    </button>

  </form>
</div>

<script>
  const form = document.getElementById(
    'contact-form'
  ) as HTMLFormElement

  const submitBtn = document.getElementById(
    'submit-btn'
  ) as HTMLButtonElement

  const successMsg = document.getElementById(
    'success-message'
  ) as HTMLParagraphElement

  const errorMsg = document.getElementById(
    'error-message'
  ) as HTMLParagraphElement

  form.addEventListener('submit', async (e) => {
    e.preventDefault()

    submitBtn.textContent = 'Sending...'
    submitBtn.disabled = true
    successMsg.style.display = 'none'
    errorMsg.style.display = 'none'

    const formData = new FormData(form)
    const data = Object.fromEntries(
      formData.entries()
    )

    try {
      const response = await fetch(
        'https://formgrid.dev/api/f/your-form-id',
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data),
        }
      )

      if (response.ok) {
        form.reset()
        successMsg.style.display = 'block'
      } else {
        errorMsg.style.display = 'block'
      }
    } catch {
      errorMsg.style.display = 'block'
    } finally {
      submitBtn.textContent = 'Send Message'
      submitBtn.disabled = false
    }
  })
</script>

Replace your-form-id with the actual endpoint slug from your Formgrid overview tab.

Now import the component on any page:

---
// src/pages/contact.astro
import ContactForm from 
  '../components/ContactForm.astro'
---

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Contact</title>
  </head>
  <body>
    <h1>Get In Touch</h1>
    <ContactForm />
  </body>
</html>

Step 5: Receive Submissions Instantly

Whenever someone submits your form you will receive an email notification that looks like this:

New Submission: Astro Contact Form

Name: Allen Jones
Email: allen@example.com
Message: Hi, I would love to work 
         with you on my next project.

Submitted: 10:30 AM, April 9, 2026

Image description

Clean. Organized. Ready to act on.

You can also view all submissions in your Formgrid dashboard at any time.

Image description

Every submission is saved to your dashboard regardless of whether the email was delivered. You never lose a submission.


Bonus: Send Astro Form Submissions

to Google Sheets

If you want every form submission to automatically appear as a new row in a Google Sheet with no Zapier and no API setup, this is available on the Professional plan at $16/month.

Here is how it works:

Share a Google Sheet with the Formgrid service account email address. Paste the sheet URL into your form settings. Done. Every submission flows in automatically as a new row.

Column headers are created from your form field names on the very first submission, so you do not need to set anything up in the spreadsheet.


When to Use a Form Service

vs Building Your Own Backend

Use Formgrid if:

You need a simple contact or enquiry form. You do not want to build or maintain a backend. You want instant email notifications. You want spam protection without configuration. You are deploying a static Astro site. You want submissions saved to a dashboard automatically.

Build your own backend if:

You need custom authentication logic. You need advanced server-side validation. You want to store submissions in your own database. You are building a full SaaS application with complex form workflows.

For 90% of Astro portfolios, landing pages, and client websites, a form service is more than enough.


Final Thoughts

Handling form submissions in an Astro site without a backend used to mean hacks, expensive services, or deploying a server you did not need.

With Formgrid, you can:

Build a working contact form in under 5 minutes. Receive submissions instantly by email. Avoid all backend code entirely. Self-host if you want full data control. Connect to Google Sheets automatically on the Professional plan.

If you want a simple, open source, privacy-first way to handle form submissions in your Astro site, give Formgrid a try.

👉 Try Formgrid free at formgrid.dev

👉 GitHub: github.com/allenarduino/formgrid


Full disclosure: I built Formgrid. Written as honestly as I could. Let me know in the comments if anything looks off.


Tags: #astro #webdev #javascript #tutorial #formgrid