Astro is one of the fastest-rising frameworks for building content-heavy websites. It ships zero JavaScript by default, which is great for performance — but it means there is no built-in way to handle form submissions. You need a form backend.
The good news: adding a working contact form to Astro takes about 2 minutes.
Why Astro Forms Need a Backend
Astro renders pages statically or on the server. Either way, it does not give you a submission handler out of the box. When a user clicks Submit, the browser needs somewhere to POST the data. That is what a form backend does.
The Quickest Setup: HTML Action
In your .astro component, add a plain HTML form pointing at your Flowqen endpoint:
---
// src/components/ContactForm.astro
---
<form
action="https://flowqen.com/api/f/YOUR_FORM_ID"
method="POST"
>
<input type="text" name="name" placeholder="Your name" required />
<input type="email" name="email" placeholder="Email address" required />
<textarea name="message" placeholder="Your message" required></textarea>
<input type="hidden" name="_redirect" value="https://yoursite.com/thanks" />
<input type="text" name="_gotcha" style="display:none" />
<button type="submit">Send message</button>
</form>
Replace YOUR_FORM_ID with the ID from your Flowqen dashboard. That is it — no Node.js, no API endpoints, no environment variables.
AJAX Submission (No Page Reload)
If you want to show a success message without a full redirect, use a small script inside your Astro component:
---
// ContactForm.astro
---
<form id="contact-form">
<input type="text" name="name" required />
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
<p id="success" style="display:none">Message sent!</p>
<script>
const form = document.getElementById('contact-form');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const data = new FormData(form);
await fetch('https://flowqen.com/api/f/YOUR_FORM_ID', {
method: 'POST',
body: data,
headers: { 'Accept': 'application/json' },
});
form.style.display = 'none';
document.getElementById('success').style.display = 'block';
});
</script>
Using Astro + React Islands
If your Astro project uses React islands (via client:load), you can use a React component with Flowqen instead:
// src/components/ContactForm.tsx
export default function ContactForm() {
const [sent, setSent] = React.useState(false);
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const data = new FormData(e.currentTarget);
await fetch('https://flowqen.com/api/f/YOUR_FORM_ID', {
method: 'POST',
body: data,
headers: { Accept: 'application/json' },
});
setSent(true);
}
if (sent) return <p>Thanks! We'll be in touch.</p>;
return (
<form onSubmit={handleSubmit}>
<input name="name" placeholder="Name" required />
<input name="email" type="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
<button type="submit">Send</button>
</form>
);
}
Then in your Astro file: <ContactForm client:load />
Spam Protection
Flowqen includes honeypot spam filtering automatically. Just include the hidden _gotcha field shown above and bots are filtered server-side — no CAPTCHAs needed for most use cases.
What Happens After Submission
- You get an email notification instantly.
- The submission appears in your Flowqen dashboard.
- You can route it to Slack, Discord, Google Sheets, Notion, or a webhook.
FAQ
Does this work with Astro's static output mode?
Yes. The form posts to Flowqen's servers, not yours. Static output is fine.
Does this work with Astro SSR mode?
Yes. You can use the same HTML action or AJAX approach regardless of whether Astro is in static or server mode.
Do I need to sign up?
You can create a form and receive submissions without an account. Sign up for a dashboard and email notifications.
Or skip all this and use FlowQen — 2 lines of code, done.