integrations · framework

A contact form for Astro: no island, no adapter, no backend.

An Astro contact form doesn't need an SSR adapter, an API endpoint, or a framework island. Astro renders plain HTML by default, and a plain HTML form is all a contact form needs: point its action at your mailcontact endpoint and submissions land in your project's inbox, with a notification in Discord, Slack, email, or a webhook.

It ships zero JavaScript, works with Astro's fully static output on any host, and keeps working if you later add an adapter, because it's markup in a .astro page, not a plugin or a server route.

recommended setup

Use the MailContact script with your own design.

Add this HTML to your site, or use the form builder. Replace the form link with yours. The hosted script injects the hidden check, handles sending and automatic verification, and preserves the draft on errors. You control the HTML and CSS. Free forms display a visible “Processed by mailcontact.app” link; Pro and Plus do not. Feedback follows the browser’s language; set data-mailcontact-language="fr" on the form to force French.

contact.html
<form action="https://mailcontact.app/api/forms/your-form-id" method="POST" data-mailcontact-form>
  <fieldset>
    <legend>Contact us</legend>
    <label>
      Name (optional)
      <input name="name" type="text" autocomplete="name" maxlength="200" />
    </label>
    <label>
      Email
      <input name="email" type="email" autocomplete="email" maxlength="320" required />
    </label>
    <label>
      Message
      <textarea name="message" rows="5" maxlength="5000" required></textarea>
    </label>
    <noscript>
    <div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden;">
      <label>Website
        <input name="company_website" type="text" tabindex="-1" autocomplete="off" />
      </label>
    </div>
    </noscript>
    <button type="submit">Send message</button>
  </fieldset>
  <p data-contact-status role="status" aria-live="polite" aria-atomic="true"></p>
</form>
<script defer src="https://mailcontact.app/forms/v1.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

For a component with its own submit handler, load the same script and use MailContact.prepare(form) and MailContact.send() instead of the automatic marker. See the custom interface reference for loading, feedback and Free attribution.

the snippet

Alternative: a direct integration for Astro.

This example posts directly to the API. Keep the required company_website field present and empty. Native posts open JSON on success or a verification page when needed. Custom scripts without verification support send suspicious messages to Spam for review; strong spam is also held there without notifications or quota usage. A success response confirms reception, including review, or a silent discard of a filled check. See spam protection for the full behavior.

src/pages/contact.astro
---
// No frontmatter needed: the form is plain HTML.
---

<form action="https://mailcontact.app/api/forms/your-form-id" method="POST">
  <input type="text" name="name" placeholder="Your name" required />
  <input type="email" name="email" placeholder="[email protected]" required />
  <textarea name="message" placeholder="What's on your mind?" required></textarea>
  <button type="submit">Send</button>
  <input name="company_website" type="text" tabindex="-1" autocomplete="off"
    style="position:absolute;left:-10000px" aria-hidden="true" />
</form>

how it works

Three steps, start to finish.

01

Create an inbox

One inbox per project. Name it after your site and you get a form endpoint and a project email address immediately.

02

Paste the form

Drop the markup above into any .astro page or component: src/pages/contact.astro, a footer, a layout. It's your HTML; style it however you like.

03

Get notified

Add a Discord, Slack, email, or webhook channel. Delivered messages ping you where you already are.

why mailcontact

Built to pair well with Astro.

Zero JavaScript, zero islands

No client:load, no framework component, no hydration cost. The form is static HTML, which is exactly what Astro ships fastest.

No SSR adapter required

Astro's server endpoints need an adapter and a server to run on. Posting to an external endpoint keeps your build fully static. astro build, upload, done.

One inbox per site you ship

Astro makes it cheap to spin up marketing sites, docs, and side projects. Each one gets its own inbox and its own address instead of piling into your personal email.

faq

Astro + mailcontact, answered

Can Astro handle form submissions without a server?

Not by itself. A statically built Astro site has nothing running to receive a POST. Pointing the form's action at a mailcontact endpoint fixes that: mailcontact's servers accept the submission and your site stays fully static.

Does this work on Netlify, Vercel, GitHub Pages, or Cloudflare Pages?

Yes. The endpoint accepts cross-origin posts from any domain, so the form works wherever your static output is hosted. No adapter, functions, or host-specific form feature needed.

How do I show a success message instead of leaving the page?

Use the hosted MailContact script for submission, automatic verification and inline feedback, or MailContact.send() in your own handler. A configurable redirect for native form posts is not currently available.

Can I style the form with Tailwind or scoped Astro styles?

Yes. It's your markup in your page, so scoped <style> blocks, Tailwind classes, or global CSS all apply as usual. mailcontact only cares about the field names: email and message are required, name and subject are optional; company_website must also be present and empty.

related

Also works with

One inbox for every Astro project you ship.

Forms and a real email address, together, with notifications where you live. Start with a free account.

Create your free form

No credit card needed. Free includes one project and 50 form messages per month.