The backend you don't deploy
Your host keeps serving flat files. The POST goes to mailcontact's servers, which validate, store, and notify: the one dynamic piece a static site is missing.
integrations · approach
You can add a working contact form to a static site without writing or hosting any backend. Point a plain HTML form's action at a form endpoint (a URL that accepts the POST for you) and every submission lands in your project's inbox with a notification on Discord, Slack, email, or a webhook. Your site stays a folder of static files.
The usual shortcut, a mailto: link, fails in two ways. It prints your email address into the page's HTML, where spam harvesters scrape it within days. And it only works if the visitor has a desktop mail client configured: on most machines the click opens nothing, or opens an app they've never signed into, and the message is silently lost.
A form endpoint fixes both. Your address never appears in the markup, and submitting is a normal HTTP POST that works in every browser. mailcontact validates the fields, stores the message, and pings the channel you chose, the same flow whether your site is hand-written HTML, a generator's output, or an old page you inherited.
recommended setup
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.
<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
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.
<form action="https://mailcontact.app/api/forms/your-form-id" method="POST">
<label for="name">Name</label>
<input id="name" type="text" name="name" />
<label for="email">Email</label>
<input id="email" type="email" name="email" required />
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" 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
One inbox per project. Name it after your site and you immediately get a form endpoint URL and a project email address. No DNS, no mail server.
Copy the snippet above into any HTML page and replace your-form-id with your endpoint. The field names (name, email, message) are all the endpoint needs.
Add a Discord, Slack, email, or webhook channel. New messages appear in the inbox and ping you the moment they arrive.
why mailcontact
Your host keeps serving flat files. The POST goes to mailcontact's servers, which validate, store, and notify: the one dynamic piece a static site is missing.
No mailto: link, no obfuscated spans, nothing for scrapers to harvest. Visitors see a form; your inbox address stays private.
The snippet is plain HTML. It works in hand-written pages and in any generator's output. No bundler, no framework, no script tag required.
faq
Completely. It's your HTML and CSS. The endpoint only cares about the field names: email and message are required, name and subject are optional; company_website must also be present and empty. Everything else about the markup is up to you.
A native form post currently shows the endpoint's JSON reply, so the best UX today is the hosted MailContact script: it sends the fields, handles verification and shows inline feedback. A configurable redirect for native posts is not currently available.
Any of them: GitHub Pages, Netlify, Vercel, Cloudflare Pages, an S3 bucket, or nginx serving a folder. The form posts to mailcontact's servers and requests are accepted from any origin, so there's nothing to configure on the host.
Free includes one project, one form and 50 submissions per month, with notification channels. Pro adds receiving email addresses, ten projects and 1,000 messages per month across the account. Form requests are limited to 20 per minute per IP.
related
Forms and a real email address, together, with notifications where you live. Start with a free account.
Create your free formNo credit card needed. Free includes one project and 50 form messages per month.