Add a working contact form to your Gatsby site with React components and FormsList. No serverless functions or Gatsby Functions needed.
TL;DR
To add a contact form to a Gatsby site, create a React component that submits to `https://formslist.com/f/your-form-id`. Since Gatsby generates static HTML, a form backend like FormsList handles submissions without needing serverless functions.
Sign up for a free FormsList account and create a new form. Copy the endpoint URL from your dashboard.
// Your endpoint will look like this:
// https://formslist.com/f/YOUR_FORM_HASHCreate a React component in your Gatsby project. Gatsby uses React, so the pattern is the same as a standard React form — useState for status management and fetch for submission.
// src/components/ContactForm.jsx
import React, { useState } from "react"
export default function ContactForm() {
const [status, setStatus] = useState("idle")
async function handleSubmit(e) {
e.preventDefault()
setStatus("sending")
const form = e.currentTarget
const data = new FormData(form)
try {
const res = await fetch("https://formslist.com/f/YOUR_FORM_HASH", {
method: "POST",
body: data,
})
if (res.ok) {
setStatus("sent")
form.reset()
} else {
setStatus("error")
}
} catch {
setStatus("error")
}
}
return (
<form onSubmit={handleSubmit} style={{ maxWidth: 480 }}>
<div style={{ marginBottom: "1rem" }}>
<label htmlFor="name" style={{ display: "block", fontWeight: 600 }}>Name</label>
<input type="text" id="name" name="name" required style={{ width: "100%", padding: "0.5rem" }} />
</div>
<div style={{ marginBottom: "1rem" }}>
<label htmlFor="email" style={{ display: "block", fontWeight: 600 }}>Email</label>
<input type="email" id="email" name="email" required style={{ width: "100%", padding: "0.5rem" }} />
</div>
<div style={{ marginBottom: "1rem" }}>
<label htmlFor="message" style={{ display: "block", fontWeight: 600 }}>Message</label>
<textarea id="message" name="message" rows={4} required style={{ width: "100%", padding: "0.5rem" }} />
</div>
<button type="submit" disabled={status === "sending"}
style={{ padding: "0.6rem 1.5rem", background: "#2563eb", color: "#fff", border: "none", borderRadius: 4, cursor: "pointer" }}>
{status === "sending" ? "Sending..." : "Send Message"}
</button>
{status === "sent" && <p style={{ color: "green" }}>Message sent successfully!</p>}
{status === "error" && <p style={{ color: "red" }}>Something went wrong. Please try again.</p>}
</form>
)
}Import the ContactForm component into a Gatsby page. Gatsby pages live in the src/pages/ directory and are automatically routed based on filename.
// src/pages/contact.jsx
import React from "react"
import Layout from "../components/Layout"
import ContactForm from "../components/ContactForm"
export default function ContactPage() {
return (
<Layout>
<h1>Contact Us</h1>
<p>Fill out the form below and we will get back to you within 24 hours.</p>
<ContactForm />
</Layout>
)
}
export function Head() {
return <title>Contact Us</title>
}Build your Gatsby site with `gatsby build` and deploy to your hosting provider (Netlify, Vercel, Gatsby Cloud, etc.). Submit a test message and verify it appears in your FormsList dashboard. Enable email notifications and integrations.
Build a fully functional contact form in React with hooks, validation, and email notifications. No backend server or API routes needed.
Learn moreAdd a fully functional contact form to any static site generator — Jekyll, Hugo, Eleventy, Astro, or plain HTML. No server-side code required.
Learn moreLearn how to process form submissions on any website without writing server-side code. Use a form backend service to receive, store, and forward submissions by email.
Learn moreSet up your form backend in under a minute. No server required, no complex configuration — just a simple endpoint for your forms.