integrations · framework

A contact form for Next.js, without writing an API route.

You don't need an API route, a mail provider SDK, or SMTP credentials to receive messages from a Next.js site. Point a plain HTML form at your mailcontact endpoint and submissions land in your project's inbox, with a notification in Discord, Slack, or a webhook.

It works the same in the App Router and the Pages Router, in server and client components, and even with static export, because it's just a form action, not a framework plugin.

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 Next.js.

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.

app/contact/page.tsx
export default function ContactPage() {
  return (
    <form action="https://mailcontact.app/api/forms/your-form-id" method="POST">
      <input type="text" name="name" placeholder="Your name" required />
      <input type="email" name="email" placeholder="[email protected]" required />
      <textarea name="message" placeholder="What's on your mind?" required />
      <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 app and you get a form endpoint and a project email address immediately.

02

Paste the form

Drop the component above anywhere in your app: a page, a footer, a modal. Style it however you like; it's your markup.

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 Next.js.

No API route to babysit

No /api/contact handler, no nodemailer config, no environment variables leaking into another deploy. Delete a whole category of glue code.

Static export friendly

Because the form posts to an external endpoint, it keeps working with output: 'export' and on any static host, no server functions required.

One inbox per app you ship

Shipping several Next.js projects? Each gets its own inbox and its own address, instead of everything piling into your personal email.

faq

Next.js + mailcontact, answered

Does this work with both the App Router and the Pages Router?

Yes. The snippet is a plain HTML form, so it renders identically from app/ or pages/, in a server component or a client component.

Can I submit with fetch instead of a native form post?

Yes. POST the same fields as FormData (or JSON) to your endpoint from an onSubmit handler to keep visitors on the page. Native posts currently return a JSON response, and a configurable redirect is not currently available.

Does it work with next build && output: 'export' (static hosting)?

Yes, that's the point. The form posts to mailcontact's servers, so your Next.js site can be fully static with no API routes or server functions.

How do I show a thank-you message after submitting?

Use the hosted MailContact script for automatic sending, or call MailContact.send() in an onSubmit handler for a custom interface. A configurable redirect for native form posts is not currently available.

related

Also works with

One inbox for every Next.js 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.