HTML Forms with Eleventy (11ty)
In this guide we’ll show you how to add a contact form to your Eleventy (11ty) website using Formspree.
Formspree is a form backend that’s an ideal companion for static site generators, letting you get on with building and deploying your Jamstack website.
At the end of this guide you should have a working HTML contact form in your Eleventy project that sends you email notifications. Check out a live demo of the final project. The project repository is hosted on GitHub.
Prerequisites
To follow this guide you’re going to need a Formspree account, which you can sign up for free right here, and an existing website built in Eleventy. If you don’t have an Eleventy site yet, you can clone the basic blog example by running:
git clone https://github.com/11ty/eleventy-base-blog.git
If you’re not familiar with Eleventy then check out the official documentation to learn more.
Adding a form to Eleventy
Eleventy has an full templating API meaning that the form code you’re about to add can be neatly wrapped up in a partial. Create a new file called contact-form.html
inside of your _includes
directory within the source of your Eleventy project. Here’s an example of the file structure including your new partial:
project-root/
├─ .eleventy.js
└─ src/
├─ _includes/
│ └─ contact-form.html
└─ index.html
Now you can copy-paste the following example form into your contact-form.html
partial and tailor it to meet your needs:
<form action="https://formspree.io/f/YOUR_FORM_ID" method="POST">
<label>
Your email:
<input type="email" name="email">
</label>
<label>
Your message:
<textarea name="message"></textarea>
</label>
<button type="submit">Send</button>
</form>
A few notes:
- Currently the
action
attribute contains a placeholderYOUR_FORM_ID
. We’ll replace this with our own form endpoint in a bit. - The
method
attribute must bePOST
for the form to submit correctly. - Each input has a
name
attribute. This is essential to correctly send the data to Formspree. - For the sake of clarity, this form doesn’t include any styling, but you can see an example of how to apply styles to the form in this tutorial’s companion GitHub project.
- You can create any form you want by adding your own
<input ... >
tags and labels. For more examples and inspiration checkout our Form Library.
The partial can now be imported into any part of your website. Here’s what it looks like to import the partial using the default template language in Eleventy, Nunjucks:
{% include "contact-form.html" %}
Once you’ve saved your changes, use your build or deployment workflow to either run the Eleventy site locally or deploy it to your live environment to see the newly added form.
When you attempt to submit the new form you’ll see a page like this:
Oops! We get an error because we still have the placeholder YOUR_FORM_ID
in the form action. Let’s fix this by setting up a form endpoint to accept our form submissions.
Creating a form endpoint
Next we’ll create a form endpoint using Formspree. If you don’t have an account yet you can sign up here.
To start, create a new form with the +New form button, call it Contact form and update the recipient email to the email where you wish to receive your form submissions. Then click Create Form.
You’ll be presented with the integration options for your new Formspree form. Formspree provides you with a wide range of implementation examples such as React, Ajax and regular HTML.
Integration view of the sample code section, tabbed with alternative language samples
The code we used to create the contact-form.html
partial is almost identical to the HTML example code on the integration page. We just need to update the action
URL.
Copy the 8 character ID from your new form’s endpoint URL and replace the YOUR_FORM_ID
placeholder in your contact-form.html
partial.
<form action="https://formspree.io/f/abcd1234" method="POST">
Now when you fill out the form and submit, you should see a success message.
That’s it, you’re done!
Bonus Tip: Production and Development Forms
Sometimes you want to test out a new design locally, but don’t want to affect your production data. With eleventy you can switch between development and production forms using environment variables.
If you’re using Nunjucks, you can use a variable for your form action like so:
<form action="{{ env.FORMSPREE_ENDPOINT }}" method="POST">
...
</form>
Now you need to ensure the variable is set when you build. Create a _data/env.js
file with the following content:
// _data/env.js
require('dotenv').config();
module.exports = process.env
This script uses the dotenv
library to merge variables from your local .env
file into your environment, and then exposes them under the env
object to Nunjucks, or whatever template language you’re using.
Now you can add a .env
file at the project root that looks like this:
FORMSPREE_ENDPOINT=https://formspree.io/f/xxxxxxxx
Caveats:
- Be sure to add your
.env
file to.gitignore
so you don’t accidentally check-in any secrets to version control. Your Formspree endpoint isn’t secret, but nevertheless, it’s a good practice. - Anything you render through Nunjucks will be publicly visible in your website’s HTML. Don’t put secret environment variables, like API keys, into your Nunjucks templates.
Now, as you’re working locally, your form will submit to the endpoint in your .env
file. When you’re ready to ship to production, create a new production form in the Formspree dashboard, and set the FORMSPREE_ENDPOINT
environment variable to the new form endpoint in your hosting config (eg. Netlify or Vercel).
You can read more about how to use environment variables in Eleventy, and how to set build environment variables in Netlify and Vercel.