Guide Thumbnail
+

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 placeholder YOUR_FORM_ID. We’ll replace this with our own form endpoint in a bit.
  • The method attribute must be POST 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:

HTML form submit error

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.

Formspree new form modal

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.

HTML form integration code

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.


Got Feedback?