Adding a contact form to an Eleventy site

July 24, 2026

Eleventy people tend to be principled about shipping plain HTML — it's half the reason you chose 11ty. Good news: a contact form is the easiest place in your whole site to hold that line. No client JavaScript, no serverless function bolted to your static site, no build plugin.

1. Get an endpoint

Create a NormForms form — free tier, no card. You'll get a URL like https://normforms.com/f/x7Kp2mQ9RtLw.

2. Add the form to a template or include

Works identically in Nunjucks, Liquid, WebC, or plain HTML files — it's just markup. As an include (_includes/contact-form.njk):

<form action="https://normforms.com/f/YOUR_TOKEN" method="POST">
  <input type="text" name="name" placeholder="Your name">
  <input type="email" name="email" placeholder="Your email">
  <textarea name="message" placeholder="Your message"></textarea>
  <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
  <button type="submit">Send</button>
</form>
{% include "contact-form.njk" %}

Want more fields? Just add inputs — <input name="budget">, a select, whatever. Any field name you send shows up in the notification email with zero configuration. The _gotcha honeypot stays, hidden and empty; it's doing more anti-spam work than it looks like.

3. Test from localhost

Submitting from npx eleventy --serve is automatic test mode — the email arrives with a [Test] prefix and doesn't touch your quota. Set your production domain in the form settings and submissions from any other origin are silently dropped.

Scorecard

Client JavaScript added: 0 bytes. Build time impact: none. Spam filtering, delivery, storage, and a dashboard: included. Your 11ty site remains a folder of honest HTML files, now with a working front door.

Add your form →