Guide

How to add a contact form to Astro

Add a working contact form to a static Astro site without creating a server endpoint.

Last updated 2026-07-11

Add a working form to a static Astro site

Astro generates static HTML by default. That makes it a good fit for PostMyForm: Astro publishes the page, and PostMyForm receives and processes the form submission.

You do not need to add an Astro server adapter, API route, or server action just to receive a contact form.

1. Create the form in PostMyForm

Sign in to PostMyForm, open Forms, and create a form.

Configure:

  • A recognizable form name.
  • The email address that should receive notifications.
  • The allowed origin for the deployed Astro site.
  • An optional success redirect URL.

For a production site such as:

https://www.example.com/contact/

enter this allowed origin:

https://www.example.com

An origin contains the scheme, hostname, and optional port. It does not contain the page path.

When testing locally, add the exact origin printed by the Astro development server, such as:

http://localhost:4321

Use the actual URL shown in the terminal if Astro selects a different hostname or port.

2. Add the fields

Add the fields required by the form.

A typical contact form includes:

  • Name
  • Email
  • Message

PostMyForm supports text, email, textarea, select, and checkbox fields. Mark fields as required where appropriate.

3. Create an Astro form component

Create a component such as:

src/components/ContactForm.astro

Open the form detail page in PostMyForm and copy the complete generated HTML snippet into that component.

Astro processes normal <script> elements during the build. The PostMyForm snippet uses a small script that must remain in its original position inside the form.

Change only the generated opening script tag from:

<script>

to:

<script is:inline>

The is:inline directive tells Astro to leave the script in the rendered HTML exactly where it appears.

A shortened component example looks like this:

<form action="https://postmyform.com/f/your-endpoint-id" method="POST">
  <div>
    <label for="contact-name">Name</label>
    <input id="contact-name" name="name" type="text" required>
  </div>

  <div>
    <label for="contact-email">Email</label>
    <input id="contact-email" name="email" type="email" required>
  </div>

  <div>
    <label for="contact-message">Message</label>
    <textarea
      id="contact-message"
      name="message"
      required
    ></textarea>
  </div>

  <!-- Keep the generated honeypot and timing fields here. -->

  <button type="submit">Send message</button>

  <script is:inline>
    // Keep the complete script generated by PostMyForm here.
  </script>
</form>

Do not use this shortened example as the finished form. Use the complete snippet from the PostMyForm dashboard so the unique endpoint, randomized honeypot, timing field, and initialization script are preserved.

4. Add the component to an Astro page

Import the component into the page where the form should appear.

For example, in src/pages/contact.astro:

---
import ContactForm from "../components/ContactForm.astro";
---

<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1"
    >
    <title>Contact us</title>
  </head>

  <body>
    <main>
      <h1>Contact us</h1>
      <ContactForm />
    </main>
  </body>
</html>

When the project already uses a shared layout, place <ContactForm /> inside that layout instead of creating another complete HTML document.

5. Test the form locally

Start the Astro development server using the command configured by the project, commonly:

npm run dev

Open the contact page and confirm:

  • The form is visible.
  • The form action points to the PostMyForm endpoint.
  • The development origin is allowed in PostMyForm.
  • The generated honeypot and timing fields are still present.
  • The generated script uses is:inline.

Send one normal test submission. It should appear in the PostMyForm dashboard and trigger a notification attempt.

6. Build and deploy the Astro site

Create the production build using the project's normal build command, commonly:

npm run build

Deploy the generated Astro site using the existing hosting workflow.

After deployment, open the public contact page and send another test submission. Confirm that the public site's exact origin is included in the form's allowed origins.

Troubleshooting

The form works locally but is rejected after deployment

Add the deployed site's exact origin to the form configuration. Do not include /contact, another path, or a trailing page filename.

Preview deployments may use different hostnames. Add a preview origin only when submissions from that preview environment should be accepted.

The timing field remains empty

Confirm that the complete generated script is still inside the form component and that its opening tag is:

<script is:inline>

Without is:inline, Astro may process and move or deduplicate the script instead of preserving its position in the form.

The form displays but does not submit correctly

Replace the shortened example with the complete snippet generated by PostMyForm. Confirm that the endpoint, field names, honeypot, and timing field were not removed or renamed.

The form has no styling

The generated snippet intentionally contains minimal presentation markup. Add classes or scoped styles in the Astro component without changing field names or anti-spam controls.

No notification email arrives

Review the submission and its event history in the PostMyForm dashboard. Suspicious submissions do not trigger notification emails, and provider delivery failures are recorded there.

For additional help, contact support@postmyform.com.