FormWire for Astro

Astro contact forms, fully prerendered.

Astro ships zero JavaScript by default, and your contact form can too. Point a plain HTML form at one endpoint from any .astro component and every submission lands in your inbox and your dashboard — the site stays static, and deploys anywhere static files do.

Copy-paste code

A working form in one .astro component.

Start with the zero-JavaScript component — it's the whole integration. Add the fetch tab when you want an inline status message, and the pages tab shows the routing that completes the loop.

---
// src/components/ContactForm.astro
// Renders to plain HTML at build time — zero client JavaScript and
// nothing to hydrate. Works on a fully prerendered page.
---
<form action="https://api.formwire.com/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR-ACCESS-KEY" />

  <!-- A static page can't redirect after a POST, so FormWire does it.
       Point _redirect at the absolute URL of your thank-you route. -->
  <input type="hidden" name="_redirect" value="https://yoursite.com/thanks/" />

  <label>
    Name
    <input type="text" name="name" required />
  </label>
  <label>
    Email
    <input type="email" name="email" required />
  </label>
  <label>
    Message
    <textarea name="message" required></textarea>
  </label>
  <button type="submit">Send</button>
</form>

Swap YOUR-ACCESS-KEY for your form's key. The full field and response reference lives in the docs at /docs/.

Astro gotchas

The four things that trip up Astro forms.

Each one costs an afternoon the first time. The snippets above already account for all four.

View transitions kill one-shot scripts

With <ClientRouter /> a navigation swaps the DOM without a full page load, so a handler wired on DOMContentLoaded works exactly once — the form goes dead the moment a visitor arrives via a transition. Re-wire inside astro:page-load, which fires after every swap, and guard against double-binding.

Astro rewrites your <script> tags

Scripts in .astro components are processed, bundled, hoisted to the head as modules, and deduplicated — each runs once per page even if the component renders twice. When a script must stay exactly where you wrote it, or you're passing values with define:vars, mark it is:inline and Astro leaves it alone.

Skip the adapter — stay static

Astro Actions and API routes exist for servers you run, and a contact form doesn't need one: the browser POSTs to FormWire directly. Keep the build fully prerendered — no adapter, no output config change — and keep deploying plain files to any static host.

The redirect happens off-site

There's no server-side handler to send visitors to a thank-you page, so FormWire issues the redirect for you: set the hidden _redirect field to the absolute URL of a thanks route. Relative paths won't survive the round trip through the endpoint — spell out the full URL.

Three steps

From nothing to a working form.

  1. Grab your access key

    Create a form in the dashboard and copy its public key. It's a safe-to-ship alias for your verified email, so it goes straight into your component and your repo.

  2. Drop ContactForm.astro into src/components

    Paste a recipe from above, swap in your key, and render <ContactForm /> in any page, layout or MDX file. The markup and styling stay entirely yours.

  3. Submissions land in your inbox

    Every POST arrives as a formatted email with Reply-To set to the visitor, and as a searchable record in your dashboard.

Why FormWire for Astro

Built for a static-first framework.

One recipe for every island

The plain component covers most sites, and the same endpoint accepts a POST from any island — React, Svelte, Vue or Solid components inside your Astro pages submit the same way.

CORS preflight handled

The endpoint answers the OPTIONS preflight and returns readable JSON, so the fetch upgrade works from any domain — localhost:4321 included — with nothing to proxy.

Spam filtered server-side

A honeypot and optional captcha run before delivery, so the zero-JavaScript form stays zero-JavaScript and bots still don't reach your inbox.

Every submission stored

Beyond the email, each POST becomes a searchable record with CSV export and a JSON read API — useful when the form feeds more than one pair of eyes.

Astro form FAQ

The questions Astro developers actually ask.

Building with another framework?

See all frameworks
Ready in a minute

Ship your Astro form today.

Grab an access key, paste a component, and route submissions to your inbox — or on to Slack, Sheets and Zapier.

Free tier forever. No credit card required.