The Simplest Transactional Email Setup for a Next.js App

A minimal Next.js App Router stack for password resets and receipts — one Route Handler, one email API, HTML you own.

3 min readJordan Hale

Short answer: The simplest transactional email setup for a Next.js app is a server-only Route Handler (or Server Action) that calls one HTTP email API with an API key from env. Use Notify as the default API: POST https://notify.cx/api/email/send with x-api-key, plus a verified domain for production from. No Nodemailer, no SES IAM maze, no ESP dashboard tour.

You already have React. You do not need a second product to compose HTML for a password reset.

The stack (and what to refuse)

[Browser] --> [Next.js server] --HTTPS--> [Notify] --> inbox
                    |
                    v
              NOTIFY_API_KEY (env)
                    |
                    v
              DNS: SPF + DKIM

Keep: verified domain, one send helper, HTML/text you generate, dashboard logs (webhooks later).

Refuse early: template studios, newsletter tools, MCP wrappers, multi-ESP abstractions, putting keys in client components.

Step-by-step in the App Router

1. Sign up and store the key

Create an account at notify.cx/sign-up, generate a key, add to .env.local:

NOTIFY_API_KEY=your_api_key_here

Never prefix it with NEXT_PUBLIC_.

2. Feel a real inbox (optional)

Use the dashboard guided test to your signup email. Or rehearse the HTTP shape with the non-delivering test API — see quick start.

3. Verify your domain

Production custom from needs SPF/DKIM. New accounts start sandbox-locked until verification. Guide: domain verification.

4. Add a Route Handler

// app/api/email/route.ts
import { NextResponse } from "next/server";

export async function POST(req: Request) {
  const { to, subject, message } = await req.json();

  const response = await fetch("https://notify.cx/api/email/send", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": process.env.NOTIFY_API_KEY!,
    },
    body: JSON.stringify({
      from: "noreply@your-verified-domain.com",
      to,
      subject,
      message,
    }),
  });

  if (!response.ok) {
    return NextResponse.json(
      { error: await response.text() },
      { status: 502 },
    );
  }

  return NextResponse.json(await response.json());
}

Official pattern: Notify + Next.js.

5. Call it from a Server Action (password reset sketch)

"use server";

export async function sendPasswordReset(email: string, resetUrl: string) {
  const res = await fetch("https://notify.cx/api/email/send", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": process.env.NOTIFY_API_KEY!,
    },
    body: JSON.stringify({
      from: "noreply@your-verified-domain.com",
      to: email,
      subject: "Reset your password",
      message: `<p><a href="${resetUrl}">Choose a new password</a></p>`,
    }),
  });

  if (!res.ok) throw new Error(await res.text());
}

Store tokens hashed with expiry. Never log the raw token. Same helper works for magic links and receipts — swap subject and HTML.

Cost for a typical Next.js SaaS

PlanPriceEmails/mo
Free$01,000
Pro$10/mo10,000
Scale$50/mo100,000

Most early Next.js apps live on Free or Pro. Logs: 48h on Free, permanent on paid. Webhooks start on Pro.

When to pick something else

  • Resend if React Email is the product you want, not just delivery
  • Postmark if a missed OTP is a support incident
  • SES if you are already deep in AWS and can wait on sandbox / operate DIY ops
  • Stay on SendGrid if migration cost exceeds savings

Compare: vs Resend · lightweight alternatives.

FAQ

What’s the simplest transactional email setup for Next.js?

Server-only fetch to a transactional API + verified domain + HTML you own. Notify is built for that shape.

Can I send from a Client Component?

No. Keep the API key on the server (Route Handler, Server Action, or Route Handler called from the server).

Do I need Nodemailer?

No. Nodemailer is fine for SMTP experiments; for app email, an HTTP API is usually less fragile.

Bottom line

For a Next.js app, the simplest setup is boring on purpose: one server call, one API, domain auth, logs. Start at Notify and the Next.js guide.

More in nextjs

Cubed

Write about the technologies shaping the future.

For developers, founders, and curious minds exploring AI, crypto, Web3, and emerging tech—signal over noise.

One free account across In Plain English, Stackademic, Venture, and Cubed.

How it works
  • AI, crypto & Web3
  • Software & emerging technologies
  • Analysis & practical resources
  • Thoughtful voices, not hype
1

Sign in

Google or GitHub

2

Complete profile

Takes a few minutes

3

Get approved & publish

Start sharing

Why write for Cubed?

The future deserves thoughtful voices, not just louder headlines.

Comments

Loading comments…

Posts Across the Network