Framework Guide

Gatsby Contact Form

Add a contact form to a Gatsby site without a backend

Last updated

Gatsby builds static pages, so there is no server of your own to receive a form, and you do not need a Gatsby Function for one. To add a contact form without a backend, post the form data from a React component to https://api.staticforms.dev/submit with your form's API key in an apiKey field. Static Forms emails each submission to you. It works with Gatsby on any static host and on the free plan.

1. Add your API key

Gatsby only exposes environment variables to browser code when their names start with GATSBY_. It reads .env.development during gatsby develop and .env.production during gatsby build, so add the key to both:

.env.development
.env.production

Find the key on the General tab of your form in the app. The value is built into the page's JavaScript, which is expected: the form API key cannot read submissions. On a host that builds your site, such as Netlify or Vercel, set the same variable in the host's build settings.

2. Create the form component

src/components/contact-form.js

The visitor's email field becomes the reply-to address on the notification, and every other named field appears in the email. The API answers { "success": true, "message": "Form submitted successfully" }, or { "success": false, "error": "..." } with the reason, which the component shows. A submission that fails the form's field validation answers with an errors list instead, and the component shows those messages.

3. Add a contact page

Each file in src/pages becomes a page, so this one is served at /contact:

src/pages/contact.js

Optional: a form without JavaScript

Gatsby renders each page to HTML, so a plain form also works. Point its action at the endpoint and add a redirectTo field with the full URL of your thank-you page; after a successful submission the browser goes there. Leave redirectTo out of the fetch version above, because a redirect would replace the JSON result.

JSX

4. Build and test

Run gatsby build and deploy as usual, for example to Netlify, Vercel or Cloudflare Pages. Send a test message from the live page. It arrives by email and is listed in the Inbox.

More options

The React guide covers more component patterns, and the plain HTML guide lists the CAPTCHA widgets and their field names. A longer walkthrough with reCAPTCHA is in the Gatsby tutorial.

Troubleshooting

What you seeWhy, and what to do
401 "Invalid API key"The key does not match the one on the form's General tab, or GATSBY_STATIC_FORMS_KEY is not set for the command you ran (.env.development for gatsby develop, .env.production for gatsby build). An unset variable is sent as the text "undefined".
The page leaves for a thank-you page instead of showing the messageRemove redirectTo from the fetch version.
A field is missing from the emailGive the input a name attribute; FormData only sends named fields.
403 "CAPTCHA verification failed" (reCAPTCHA), or "Turnstile", "hCaptcha" or "Altcha verification failed"A CAPTCHA is turned on for the form, but the submission had no valid token. Add the widget, or turn the CAPTCHA off.

FAQ

Does this work on the free plan?

Yes. The snippet only uses Free plan features: 250 submissions every 30 days, 1 form endpoint, email delivery, the built-in spam filter, a honeypot field and reCAPTCHA v2. No credit card is needed.

How do I keep spam out?

Every submission is checked by the built-in spam filter on every plan. The snippet adds a hidden honeypot field (any field whose name contains "honeypot"); bots fill it in and those submissions are dropped. reCAPTCHA v2 is available on Free. Cloudflare Turnstile, hCaptcha, ALTCHA and reCAPTCHA v3 are available from the Starter plan.

Is it safe to put the API key in my HTML?

Yes. The form API key is meant to be public. It cannot read your submissions or sign in to your dashboard. From the Starter plan you can also restrict submissions to your own domains.

Do I need a Gatsby plugin or Gatsby Functions?

No. The component posts from the browser to https://api.staticforms.dev/submit, so a fully static Gatsby build is enough. No plugin is needed.