integrations · hosting platform

A contact form on GitHub Pages, without leaving GitHub Pages.

GitHub Pages serves static files only (no functions, no API routes, no server-side anything), so a contact form can't be handled on the site itself. The fix is a form that posts to an external endpoint: point plain HTML at your mailcontact form URL and submissions land in your project's inbox, with a ping in Discord, Slack, or email.

There's nothing to install and nothing to build. The snippet below works in a hand-written index.html, a Jekyll layout or include, or any static site you push to a gh-pages branch. Commit, push, done.

You also get a real inbound email address ([email protected]) alongside the form, useful when you don't want to publish your personal email in a public repo.

recommended setup

Use the MailContact script with your own design.

Add this HTML to your site, or use the form builder. Replace the form link with yours. The hosted script injects the hidden check, handles sending and automatic verification, and preserves the draft on errors. You control the HTML and CSS. Free forms display a visible “Processed by mailcontact.app” link; Pro and Plus do not. Feedback follows the browser’s language; set data-mailcontact-language="fr" on the form to force French.

contact.html
<form action="https://mailcontact.app/api/forms/your-form-id" method="POST" data-mailcontact-form>
  <fieldset>
    <legend>Contact us</legend>
    <label>
      Name (optional)
      <input name="name" type="text" autocomplete="name" maxlength="200" />
    </label>
    <label>
      Email
      <input name="email" type="email" autocomplete="email" maxlength="320" required />
    </label>
    <label>
      Message
      <textarea name="message" rows="5" maxlength="5000" required></textarea>
    </label>
    <noscript>
    <div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden;">
      <label>Website
        <input name="company_website" type="text" tabindex="-1" autocomplete="off" />
      </label>
    </div>
    </noscript>
    <button type="submit">Send message</button>
  </fieldset>
  <p data-contact-status role="status" aria-live="polite" aria-atomic="true"></p>
</form>
<script defer src="https://mailcontact.app/forms/v1.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

For a component with its own submit handler, load the same script and use MailContact.prepare(form) and MailContact.send() instead of the automatic marker. See the custom interface reference for loading, feedback and Free attribution.

the snippet

Alternative: a direct integration for GitHub Pages.

This example posts directly to the API. Keep the required company_website field present and empty. Native posts open JSON on success or a verification page when needed. Custom scripts without verification support send suspicious messages to Spam for review; strong spam is also held there without notifications or quota usage. A success response confirms reception, including review, or a silent discard of a filled check. See spam protection for the full behavior.

index.html
<form action="https://mailcontact.app/api/forms/your-form-id" method="POST">
  <input type="text" name="name" placeholder="Your name" />
  <input type="email" name="email" placeholder="[email protected]" required />
  <textarea name="message" placeholder="What's on your mind?" required></textarea>
  <button type="submit">Send</button>
  <input name="company_website" type="text" tabindex="-1" autocomplete="off"
    style="position:absolute;left:-10000px" aria-hidden="true" />
</form>

how it works

Three steps, start to finish.

01

Create an inbox

One inbox per project. Name it after your repo and you get a form endpoint and a project email address immediately.

02

Commit the form

Paste the snippet into index.html, a Jekyll include, or wherever your contact section lives. Push to your Pages branch as usual.

03

Get notified

Add a Discord, Slack, email, or webhook channel. Delivered messages ping you where you already are.

why mailcontact

Built to pair well with GitHub Pages.

Works within Pages' limits

GitHub Pages will never run your backend code, and with mailcontact it doesn't need to. The form posts to mailcontact's servers; your repo stays 100% static files.

No email address in your public repo

A mailto: link exposes your address to every scraper reading your source. A form endpoint and a [email protected] address keep your personal email out of the repo entirely.

One inbox per repo you publish

Docs site, portfolio, project page: each GitHub Pages site gets its own inbox and its own address, instead of everything piling into your personal email.

faq

GitHub Pages + mailcontact, answered

Can GitHub Pages handle form submissions on its own?

No. GitHub Pages serves static files and runs no server code, so it can't process a POST. Forms on a Pages site must submit to an external endpoint like mailcontact.

Does this work with Jekyll on GitHub Pages?

Yes. The snippet is plain HTML, so it works in a Jekyll layout, an include, or a Markdown page with inline HTML. GitHub's Jekyll build doesn't touch it.

How do I show a success message after someone submits?

Use the hosted MailContact script for inline feedback and automatic verification, or MailContact.send() in your own handler. The endpoint has open CORS, so it works from any github.io or custom domain. A configurable redirect for native form posts is not currently available.

Can I style the form to match my site?

Completely. It's your markup. mailcontact only provides the endpoint. Use your existing CSS, your Jekyll theme's classes, or anything else; there's no widget or iframe.

related

Also works with

One inbox for every GitHub Pages project you ship.

Forms and a real email address, together, with notifications where you live. Start with a free account.

Create your free form

No credit card needed. Free includes one project and 50 form messages per month.