Skip to main content

Basic Form

Add a contact form to any Eleventy template:
contact.njk
---
layout: base.njk
title: Contact
---

<h1>Contact Us</h1>

<form action="https://spike.ac/api/f/YOUR_FORM_SLUG" method="POST">
  <input type="text" name="_gotcha" style="display:none">
  <input type="hidden" name="_next" value="{{ site.url }}/thanks/">
  
  <div>
    <label for="name">Name</label>
    <input type="text" id="name" name="name" required>
  </div>
  
  <div>
    <label for="email">Email</label>
    <input type="email" id="email" name="email" required>
  </div>
  
  <div>
    <label for="message">Message</label>
    <textarea id="message" name="message" rows="4" required></textarea>
  </div>
  
  <button type="submit">Send Message</button>
</form>

With JavaScript

Add AJAX submission for a better user experience:
<form id="contact-form" action="https://spike.ac/api/f/YOUR_FORM_SLUG" method="POST">
  <input type="text" name="_gotcha" style="display:none">
  
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  
  <button type="submit">Send</button>
  <p id="form-status"></p>
</form>

<script>
document.getElementById('contact-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const form = e.target;
  const status = document.getElementById('form-status');
  
  status.textContent = 'Sending...';
  
  try {
    const res = await fetch(form.action, {
      method: 'POST',
      body: new FormData(form),
      headers: { 'Accept': 'application/json' }
    });
    
    if (res.ok) {
      status.textContent = 'Thanks! We\'ll be in touch.';
      form.reset();
    } else {
      status.textContent = 'Oops! Something went wrong.';
    }
  } catch (err) {
    status.textContent = 'Oops! Something went wrong.';
  }
});
</script>

Reusable Include

Create a reusable form include:
_includes/contact-form.njk
<form action="https://spike.ac/api/f/{{ formSlug }}" method="POST">
  <input type="text" name="_gotcha" style="display:none">
  {% if redirect %}
  <input type="hidden" name="_next" value="{{ redirect }}">
  {% endif %}
  
  <input type="text" name="name" placeholder="Name" required>
  <input type="email" name="email" placeholder="Email" required>
  <textarea name="message" placeholder="Message" required></textarea>
  
  <button type="submit">{{ buttonText | default("Send") }}</button>
</form>
Use it in any page:
{% include "contact-form.njk", formSlug: "abc123", redirect: "/thanks/" %}

Liquid Template

If you’re using Liquid instead of Nunjucks:
contact.liquid
---
layout: base
title: Contact
---

<form action="https://spike.ac/api/f/YOUR_FORM_SLUG" method="POST">
  <input type="text" name="_gotcha" style="display:none">
  
  <label for="email">Email</label>
  <input type="email" id="email" name="email" required>
  
  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>
  
  <button type="submit">Send</button>
</form>