Framework Guide

Eleventy Contact Form

Add a contact form to any Eleventy (11ty) site

Last updated

Eleventy builds plain HTML, so there is no server to receive a form. To add a contact form without a backend, put your key in a global data file, save the include below as _includes/contact-form.njk, and include it from a contact page. The form posts straight to https://api.staticforms.dev/submit and each submission arrives in your inbox. It needs no JavaScript and works on the free plan.

1. Add your API key as global data

Files in the _data folder of your input directory become global data, named after the file. This one is available in every template as site:

_data/site.json

Find the key on the General tab of your form in the app. It ends up in the generated HTML, which is expected: the form API key cannot read submissions.

2. Create the include

_includes/contact-form.njk

redirectTo is optional and must be a full http:// or https:// URL, which is why it starts with site.url. Without it the visitor sees a plain "Form submitted successfully" page. The visitor's email field becomes the reply-to address on the notification, and every other named field appears in the email.

3. Add the contact and thank-you pages

A permalink that ends in a slash is written to index.html in that folder, so this page is built to _site/contact/index.html with the default output directory:

contact.njk
thank-you.njk

Use your own layout name in layout. The include is plain HTML with two Nunjucks variables, so you can paste it into a Liquid or Markdown template as well; change the variable syntax if your template language needs it.

4. Build and test

Build with npx @11ty/eleventy, or run npx @11ty/eleventy --serve while you work. Open the generated contact page and check that YOUR_API_KEY has been replaced. Deploy the output folder to any static host, such as Netlify, Cloudflare Pages, GitHub Pages or Vercel, then send a test message from the live page. It arrives by email and is listed in the Inbox.

More options

CAPTCHAs, file uploads and a JavaScript version that stays on the page all work the same way as in the plain HTML guide. A longer walkthrough with styling and a deployment checklist is in the Eleventy contact form tutorial.

Troubleshooting

What you seeWhy, and what to do
401 "Invalid API key"The key in _data/site.json does not match the form. If the generated HTML still says YOUR_API_KEY, replace the placeholder in _data/site.json with the key from the form's General tab.
400 "API key is required (provide either apiKey or accessKey)"The apiKey value rendered empty, so Eleventy did not find the data file. Put site.json in the _data folder of your input directory.
/contact/ returns 404The page is outside the input directory, or its permalink differs. Check that the output folder has contact/index.html.
The thank-you page returns 404Compare the redirectTo URL with the permalink of thank-you.njk and with site.url.
redirectTo is ignoredIt must be a full URL that starts with http:// or https://, not a relative path.
A field is missing from the emailGive the input a name attribute.

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 an Eleventy plugin or serverless function?

No. The form is plain HTML in an include, so Eleventy only renders it. The browser posts to https://api.staticforms.dev/submit and Static Forms receives the submission.