Add a contact form to a Hugo site
Short answer: Hugo outputs static files, so nothing on your host can receive a form post. Put the form in a partial, point its action at a Sendform endpoint, and submissions arrive by email, Slack or webhook.
1. Get an endpoint
Create a free form at sendform.app and copy https://sendform.app/api/public/f/YOUR_ID.
2. Store the endpoint in your config
hugo.toml:
[params]
sendformEndpoint = "https://sendform.app/api/public/f/YOUR_ID"3. Create layouts/partials/contact-form.html
<form action="{{ site.Params.sendformEndpoint }}" method="POST">
<label>Name <input name="name" type="text" required></label>
<label>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="_redirect" value="{{ "thanks/" | absURL }}">
<button type="submit">Send</button>
</form>4. Use it
In a layout: {{ partial "contact-form.html" . }}. To use it inside Markdown content, wrap it in a shortcode (layouts/shortcodes/contact-form.html containing the partial call) and write {{< contact-form >}}.
5. Thank-you page
Create content/thanks.md. _redirect must be an absolute URL, which is why the snippet uses absURL. absURL builds the URL from the baseURL in your config, so set baseURL to your live site address (for example baseURL = "https://example.com/"). The URL must be on the site the form is posted from, one of your form's allowed domains, or your saved redirect's domain.
Spam and quota
Sendform filters spam with rate limits and optional Cloudflare Turnstile. The hidden _gotcha honeypot field in the snippet adds bot protection. Spam never counts toward your quota.
Troubleshooting
- Form posts to an empty URL:
sendformEndpointisn't set, or the theme uses a different params path. - Redirect goes to Sendform's thank-you page:
_redirectisn't absolute (checkbaseURL), or its host isn't the site the form is posted from, an allowed domain or your saved redirect's domain. - Works the same whether you host on GitHub Pages, Netlify, Vercel or Cloudflare Pages.
Plans
Free: $0, 250 submissions a month. Pro: $5/mo or $48/yr for 5,000 with autoresponder, uploads, webhooks and API.