Astro contact forms
for static sites.
Keep your Astro pages static and fast. Form Plume gives every contact form a hosted backend for email, submissions, spam protection, files, integrations, and webhooks.
---
const endpoint = "PASTE_YOUR_FORM_PLUME_ENDPOINT_HERE";
---
<form action={endpoint} method="POST">
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<button>Send message</button>
</form>The full guide
A contact form backend that fits Astro.
Use static form actions first, then add a tiny script only when inline confirmation improves the page.
- 1Create your Form Plume accountStart free and give your Astro form a hosted endpoint for email, submissions, spam filtering, uploads, integrations, and webhooks.Start free
- 2Create the form and copy the endpointCopy the endpoint URL from Form Plume. It looks like
https://api.formplume.com/f/your-slug - 3Connect it inside AstroUse a real form action in your .astro component, then add a small client script only if you want inline status. Send one test submission from the real Astro app or preview environment and confirm it reaches Form Plume.
You can use this AI prompt to hand the platform-specific wiring to an assistant without accidentally creating a backend.
Static Astro form
Astro is excellent for content-heavy sites, and a contact form can stay static. Point the form at Form Plume and Astro does not need an API route.
---
const endpoint = "PASTE_YOUR_FORM_PLUME_ENDPOINT_HERE";
---
<form action={endpoint} method="POST">
<label for="name">Name</label>
<input id="name" name="name" autocomplete="name" required />
<label for="email">Email</label>
<input id="email" type="email" name="email" autocomplete="email" required />
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" required></textarea>
<button type="submit">Send message</button>
</form>The deployed page can be static while Form Plume handles email notifications, stored submissions, spam filtering, file uploads, integrations, and webhooks.
Add a thank-you route
Astro sites often use a dedicated success page. Add _redirect when you want Form Plume to send successful visitors there.
<input type="hidden" name="_redirect" value="/thanks" />Keep the thank-you page in Astro so it can match the rest of the site and explain when the visitor should expect a reply.
Progressive enhancement in Astro
Use a tiny script when you want inline confirmation. The form still works when scripts are blocked.
<form id="contact" action={endpoint} method="POST">
<!-- fields -->
<button type="submit">Send message</button>
<p id="contact-status" role="status"></p>
</form>
<script>
const form = document.querySelector("#contact");
const status = document.querySelector("#contact-status");
form?.addEventListener("submit", async (event) => {
event.preventDefault();
status.textContent = "Sending...";
const response = await fetch(form.action, {
method: "POST",
headers: { Accept: "application/json" },
body: new FormData(form),
});
status.textContent = response.ok
? "Thanks, we got your message."
: "Please try again.";
});
</script>Astro environment notes
Only expose values to the browser when they are safe to be public. A Form Plume endpoint is public by design, but email provider keys, webhook secrets, and database credentials should never appear in Astro client code.
If you use import.meta.env.PUBLIC_FORM_PLUME_ENDPOINT, remember that PUBLIC_ values are included in the client bundle.
You usually do not need Astro server endpoints for contact forms. Let the static page submit to Form Plume and keep your deployment simple.
Files, spam, and integrations
For uploads, add enctype="multipart/form-data" and an input named attachment.
For spam protection, start with Form Plume defaults. Add stronger checks only when the form starts attracting targeted abuse.
For operations, connect Form Plume to Slack, Discord, Google Sheets, Mailchimp, ActiveCampaign, or a signed webhook so the Astro site does not have to know about every downstream tool.
Primary sources
FAQ
Astro form questions
before publish.
One line. Zero backend.
