A contact form for GitHub Pages (no server required)
July 21, 2026
GitHub Pages will host your site forever, for free, on one condition: it never runs a single line of server code. That rules out every "just add a backend" tutorial on the internet. It doesn't rule out a contact form, though. A form doesn't need your server. It just needs a URL to POST to.
1. Get the URL
Create a NormForms form. It's free.
You'll get an endpoint like https://normforms.com/f/x7Kp2mQ9RtLw.
2. Add the form to your page
Whether your Pages site is hand-written HTML or Jekyll, the markup's the same:
<form action="https://normforms.com/f/YOUR_TOKEN" method="POST"> <label for="nf-name">Name</label> <input id="nf-name" type="text" name="name" autocomplete="name" required> <label for="nf-email">Email</label> <input id="nf-email" type="email" name="email" autocomplete="email" required> <label for="nf-message">Message</label> <textarea id="nf-message" name="message" required></textarea> <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off"> <button type="submit">Send</button> </form>
Commit, push, done. The form works as soon as Pages rebuilds. The hidden
_gotcha field is the spam honeypot. Leave it exactly as it is.
3. Lock it to your domain
In your form's settings, set your site's domain:
username.github.io or your custom domain. Submissions from
any other origin get silently dropped. That's what shuts down the bots
that POST straight at endpoints without ever loading your page.
One honest catch
Your form endpoint URL sits right in your repo if it's public. That's fine. It's by design: the URL is already on your live page, and it only accepts submissions from your own domain anyway. What you should never commit anywhere is an email password or SMTP credential, which is exactly the thing this setup means you'll never have.
Don't want to touch HTML at all? Every NormForms form doubles as a hosted page at that same URL. Link to it straight from your README.