Jekyll
A Jekyll contact form as an include, with the access key in _config.yml. Works on GitHub Pages without plugins.
Jekyll turns your site into static HTML, so there is no server to receive a form post. SilentForms takes that role: the form posts straight to the submit endpoint and you get each submission by email. The setup below is an include, one value in _config.yml and a thank-you page. It uses only core Liquid, so it works on GitHub Pages without any plugin.
1. Get an access key#
Enter your email on the access key page and click the confirmation link. The key only routes submissions to your inbox, so it is fine to commit it and publish it in HTML.
2. Add the key to _config.yml#
Every custom value in _config.yml is available to templates through the site variable. Add the key next to your other settings:
title: My site
url: "https://example.com" # your production origin, no trailing slash
baseurl: "" # "/my-repo" for a GitHub Pages project site
silentforms_key: "YOUR_ACCESS_KEY_HERE"url and baseurl matter here because the thank-you redirect is built from them in the next step.
3. Create the include#
Create _includes/contact-form.html:
<form action="https://silentforms.com/api/submit" method="POST" class="contact-form">
<input type="hidden" name="accessKey" value="{{ site.silentforms_key }}">
<input type="hidden" name="subject" value="New message from {{ site.title | escape }}">
<input type="hidden" name="redirect" value="{{ '/thanks/' | absolute_url }}">
<label for="cf-name">Name</label>
<input id="cf-name" type="text" name="name" autocomplete="name" required>
<label for="cf-email">Email</label>
<input id="cf-email" type="email" name="email" autocomplete="email" required>
<label for="cf-message">Message</label>
<textarea id="cf-message" name="message" rows="6" required></textarea>
<!-- Honeypot: hidden from people, filled in by bots -->
<input type="checkbox" name="botcheck" style="display: none;" tabindex="-1" autocomplete="off">
<button type="submit">{{ include.button | default: "Send message" }}</button>
</form>Notes on the Liquid:
absolute_urlprependssite.urlandsite.baseurl, producinghttps://example.com/thanks/. Theredirectfield must be an absolute URL, so a bare/thanks/would be rejected with "redirect must be an absolute http(s) URL."include.buttonis an optional parameter, so{% include contact-form.html button="Get in touch" %}changes the label without copying the file.escapekeeps a site title containing quotes from breaking the attribute.
4. Use it on a page#
Jekyll processes Liquid in any file with front matter, Markdown included, and kramdown passes the form HTML through. Create contact.md:
---
layout: page
title: Contact
permalink: /contact/
---
Questions or feedback? Send us a message and we will reply by email.
{% include contact-form.html %}Use whichever layout your theme provides (page exists in the default Minima theme).
5. Add the thank-you page#
Create thanks.md:
---
layout: page
title: Thanks!
permalink: /thanks/
sitemap: false
---
Your message is on its way. We will get back to you soon.
[Back to the homepage]({{ '/' | relative_url }})The permalink must match the path in the include. sitemap: false is read by the jekyll-sitemap plugin if you use it, and ignored otherwise. If you leave out the redirect field, visitors see the default SilentForms success page instead. See Redirect after submit.
Test it#
Run bundle exec jekyll serve and open http://localhost:4000/contact/. During jekyll serve, Jekyll sets site.url to the local address, so the redirect points at your local thank-you page. Submit the form, check you land on /thanks/, then check your inbox.
Jekyll does not reload _config.yml while it watches for changes. If the key or url looks wrong, stop the server and start it again.
On GitHub Pages#
Nothing extra is needed: includes, site variables, absolute_url and relative_url are all part of Jekyll itself, and the form posts directly from the visitor's browser to SilentForms. Push the files and the form works on the published site. For a project site (username.github.io/my-repo), set baseurl: "/my-repo" so the redirect URL includes the repository path. More on hosting in GitHub Pages.
Gotchas#
- The access key arrives empty. The name in
_config.ymldoes not matchsite.silentforms_key, or the server was not restarted after editing the config. - The redirect goes to the wrong host.
urlis missing or still the theme's example value. It must be your production origin. - Liquid in the form is printed literally. The file has no front matter. Even an empty
---pair at the top is enough for Jekyll to process it.
For every error message, see Troubleshooting.
Next steps#
- Lock the key to your domain: Restrict to your domain.
- Add a CAPTCHA if spam gets through: Cloudflare Turnstile.
- Show your site name as the email sender: Sender name.