Astro
Astro component with a plain HTML form. No client-side JavaScript needed — the browser handles the POST natively.
One-liner
--- // src/pages/contact.astro // One-time setup: curl -X POST https://api.gopigeon.dev/new -d '[email protected]' const ENDPOINT = "https://api.gopigeon.dev/f/f_abc123def456xyz0"; --- <html> <body> <form action={ENDPOINT} method="POST"> <input type="text" name="name" required /> <input type="email" name="email" required /> <textarea name="message" required></textarea> <button type="submit">Send</button> </form> </body> </html>
How it works
The frontmatter block defines the endpoint constant at build time. Astro injects it into the rendered HTML action attribute. When the user submits, the browser issues a standard form-encoded POST directly to gopigeon — your Astro site is never part of the request path, so there is no function invocation, no server budget burn, no cold-start latency.
This makes Astro the cheapest possible integration: zero bytes of client JS, zero server compute, and a form that works the moment the page ships.
The email you passed as recipient above gets a one-click claim link on the first real submission — that is how you become the authenticated owner. See the claim flow for the full sequence.
Configure a thank-you redirect
By default the submitter sees raw JSON after the POST. To redirect them to a thank-you page, claim the endpoint (above), then set redirect_url on the endpoint’s detail page in the dashboard. The browser will follow a 303 to your URL on every successful submission — no JS, no edits to the Astro component.
Suppress spam bots with a honeypot
Add a hidden field anywhere inside the <form>. Real users can’t see or focus it; most spam bots fill every input they find. Gopigeon silently drops submissions where _gotcha is non-empty:
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off"
style="position:absolute;left:-9999px" aria-hidden="true"> CORS / allowed origins
By default Gopigeon allows cross-origin POSTs from any origin (allowed_origins: "*"), which is what you want during development and for the static-HTML form path above. Once you claim the endpoint, you can lock it down to your domain — set allowed_origins to a comma-separated list (e.g. https://yoursite.com) on the endpoint detail page in the dashboard. This matters most if you switch from a native <form> POST to a fetch() call from the browser.