Guides Eleventy
Contact form for an Eleventy (11ty) site
Eleventy outputs static HTML, so a form needs a backend to post to. Rather than writing a serverless function, point the form at sendm8: put the endpoint in global data, the form in an include, and use it on any page.
Keep the endpoint in global data
export default {
url: "https://yoursite.com",
formEndpoint: "https://sendm8.com/f/you@example.com",
};Change you@example.com to your address. Using a CommonJS project? Write module.exports = { … } instead.
The form as an include
<form action="{{ site.formEndpoint }}" method="POST">
<label>Your email <input name="email" type="email" required></label>
<label>Message <textarea name="message" required></textarea></label>
<input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
<input type="hidden" name="_next" value="{{ site.url }}/thanks/">
<button>Send</button>
</form>Use it from any template or Markdown page. Eleventy runs Markdown through Liquid first by default and lets HTML through, and the include is plain HTML, so it works the same from Liquid and Nunjucks:
---
title: Contact
layout: base.njk
---
Say hello.
{% include "contact-form.html" %}Using Liquid or WebC instead? The form is plain HTML, so the same markup works in any template language; only the include syntax changes.
Confirm and test
- The first time anyone submits, sendm8 stores the message and emails
you@example.com(well, your address) one confirmation link. Click it and that message, plus anything that arrived meanwhile, is delivered. After that, submissions just arrive. - Run
npx @11ty/eleventy --serveand send a test from localhost. Local posts are always allowed, so you can try it before you deploy. - Create a
thanks.mdpage for the_nextredirect, or remove that line to use sendm8’s own thank-you page.
An inline success message
To stay on the page after sending, add the helper script and data-sendm8. No build step and no bundler config: it’s a single script tag.
<script src="https://sendm8.com/s/v1.js" defer></script>
<form action="{{ site.formEndpoint }}" method="POST"
data-sendm8 data-sendm8-success="Thanks! Speak soon.">Taking file uploads
To accept files, add enctype="multipart/form-data" to the form and use a normal <input type="file">. Each file can be up to 5 MB, with 10 MB and 5 files per submission. Files are stored with the submission, and your notification links to them rather than attaching them, so nobody’s inbox fills up.
Spam and limits
Submissions are rate-limited, scored for spam and checked by a small AI model. Anything flagged goes to a spam folder, not your inbox, and nothing is ever dropped without a trace.
A no-account endpoint keeps up to 100 submissions a month and delivers by email. Sign in with the same address and the form moves into your account: 1,000 submissions a month, a dashboard inbox with search and CSV export, and Discord, Slack, Telegram or webhook delivery.
Questions
- Do I need Netlify Forms or a serverless function for an Eleventy form?
- No. The form posts straight to sendm8, so it works on any host without a function, a build plugin or host-specific form handling.
- Can I use it with Eleventy’s WebC or Liquid templates?
- Yes. The form is plain HTML, so only the include syntax differs between template languages.
- How do I keep my email address out of the HTML?
- Sign in, create a form in the dashboard and use its id in formEndpoint. The address then stays in your account rather than in the page.