Home / Guides / Astro Contact Form Integration (Static & SSR)
INTEGRATION GUIDE · ASTRO & JAMSTACK

Astro Contact Form Integration (Static & SSR)

How to add contact forms to Astro static sites (SSG) and hybrid server routes using Lugatu endpoints without maintaining email servers or databases.

1. Pure Static Site (SSG) Form Ingestion

Astro is renowned for zero-JavaScript by default. With Lugatu, you can keep your Astro site 100% static while collecting inquiries with standard HTML forms and lightweight client-side fetch.

src/pages/contact.astro astro
---
// src/pages/contact.astro
---
<form id="astro-contact-form" class="space-y-4 max-w-md">
  <div>
    <label class="block text-sm font-semibold mb-1">Your Name</label>
    <input type="text" name="name" required class="w-full border rounded-xl p-2.5" />
  </div>
  <div>
    <label class="block text-sm font-semibold mb-1">Email Address</label>
    <input type="email" name="email" required class="w-full border rounded-xl p-2.5" />
  </div>
  <div>
    <label class="block text-sm font-semibold mb-1">Message</label>
    <textarea name="message" rows="4" required class="w-full border rounded-xl p-2.5"></textarea>
  </div>

  <input type="text" name="_gotcha" style="display:none !important" tabindex="-1" autocomplete="off" />

  <button type="submit" class="btn-primary-editorial py-2.5 px-6">Send Message</button>
</form>

<script>
  const form = document.getElementById('astro-contact-form') as HTMLFormElement;
  form?.addEventListener('submit', async (e) => {
    e.preventDefault();
    const formData = new FormData(form);

    const payload = {
      fields: {
        name: formData.get('name'),
        email: formData.get('email'),
        message: formData.get('message'),
      },
      honeypot: formData.get('_gotcha') || '',
    };

    const res = await fetch('https://www.lugatu.com/api/v1/public/forms/YOUR_PUBLIC_FORM_ID/submissions', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
      body: JSON.stringify(payload),
    });

    if (res.ok) {
      alert('Thank you! Message delivered.');
      form.reset();
    }
  });
</script>

2. Astro Hybrid / SSR API Route with Server API Key

If your Astro site runs in hybrid or SSR mode on Cloudflare Pages, Netlify, or Vercel, forward submissions securely through an Astro API route.

src/pages/api/contact.ts typescript
import type { APIRoute } from 'astro';

export const POST: APIRoute = async ({ request }) => {
  const data = await request.formData();
  const fields = {
    name: data.get('name')?.toString(),
    email: data.get('email')?.toString(),
    message: data.get('message')?.toString(),
  };

  const res = await fetch(`https://www.lugatu.com/api/v1/forms/${import.meta.env.LUGATU_FORM_ID}/submissions`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${import.meta.env.LUGATU_API_KEY}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': crypto.randomUUID(),
    },
    body: JSON.stringify({ fields }),
  });

  return new Response(JSON.stringify({ success: res.ok }), {
    status: res.status,
    headers: { 'Content-Type': 'application/json' },
  });
};

Security & Authentication Invariant

Security Instruction: Never expose import.meta.env.LUGATU_API_KEY in Astro client-side script tags. Client scripts must only use the public endpoint.

Troubleshooting & Common Ingestion Errors

Form works locally but fails on production Cloudflare / Netlify build

Ensure your production environment variables (LUGATU_FORM_ID and LUGATU_API_KEY) are configured in your hosting dashboard.

Frequently Asked Questions

Can I keep my Astro site 100% static with Lugatu?

Yes. Pure static (SSG) sites submit directly to the Lugatu public endpoint without requiring any server compute on your hosting provider.

Ready to create your form endpoint?

Get started for free in seconds. No credit card required.

Start Free →