React Email

React Email + Resend: Production Checklist for Next.js

React Emails ProFebruary 25, 20267 min read

Shipping emails isn't hard. Shipping emails that are reliable, secure, and don't land in spam is where teams lose weeks.

This is a practical checklist for using React Email with Resend in a Next.js app — the stuff you actually need before you call it production.

The baseline stack

  • Next.js (App Router)
  • React Email for template rendering
  • Resend as the SMTP/API provider
npm install resend react-email @react-email/components
If you're already sending emails via SMTP, you can still use React Email for rendering HTML. Resend just gives you a fast, friendly API + solid deliverability defaults.

1) Render server-side (and keep the client out of it)

The safest setup is: render and send emails on the server only. Don't bundle templates into client components.

app/api/email/welcome/route.ts
import { Resend } from "resend";
import WelcomeEmail from "@/emails/welcome";

const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(req: Request) {
  const { email, name } = await req.json();

  const { error } = await resend.emails.send({
    from: "Acme <hello@acme.com>",
    to: email,
    subject: `Welcome, ${name}!`,
    react: WelcomeEmail({ name }),
  });

  if (error) return Response.json({ error }, { status: 500 });
  return Response.json({ ok: true });
}

2) Environment variables: be strict

Production email failures are usually boring: missing env vars, wrong from address, or secrets in the wrong place.

  • RESEND_API_KEY only on the server
  • A verified sending domain (not a random Gmail)
  • Separate dev and prod "from" names to avoid confusion
Add a hard startup check so your app fails fast in prod. Silent misconfiguration is how you discover email is broken… from a customer.
lib/env.ts
export function requireEnv(name: string) {
  const value = process.env[name];
  if (!value) throw new Error("Missing env var: " + name);
  return value;
}

export const RESEND_API_KEY = requireEnv("RESEND_API_KEY");

3) Validate inputs and props

The email template is code — treat its props like an API contract. Validate them before sending.

lib/email/props.ts
import { z } from "zod";

export const welcomeEmailSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(80),
});

export type WelcomeEmailInput = z.infer<typeof welcomeEmailSchema>;

4) Deliverability basics (do these or don't bother)

  • Set up SPF and DKIM for your domain
  • Add DMARC (start with p=none, then tighten)
  • Use a consistent from address like hello@yourdomain.com
  • Include a plain-text fallback if your setup requires it
Don't ship transactional email from a free mailbox domain. It screams "spam" and you'll pay for it in deliverability.

5) Make sends idempotent (avoid double emails)

Most duplicate emails come from retries: webhook delivery, background jobs, users double-clicking, or serverless replays.

Tie each send to a unique business event (userId + eventId) and store a send record before you hit the provider.

Minimal pattern

  • Generate a deterministic key (ex: welcome:{userId})
  • Check DB: already sent? return early
  • Write "sending" state
  • Send
  • Write "sent" state + provider message id

6) Test what matters: rendering and links

You don't need a perfect email test suite. You need a few high-signal checks that prevent embarrassing regressions.

  • Snapshot the rendered HTML (basic regression coverage)
  • Assert every CTA link exists and uses HTTPS
  • Assert the preview text is present (it affects opens)
emails/__tests__/welcome.test.tsx
import { render } from "@react-email/render";
import WelcomeEmail from "../welcome";

test("welcome email renders a dashboard link", () => {
  const html = render(WelcomeEmail({ name: "Iso", loginUrl: "https://acme.com" }));
  expect(html).toContain("https://acme.com");
});

Production quick-check (copy/paste)

  • Domain verified + SPF/DKIM/DMARC configured
  • API routes are server-only; no templates in the client bundle
  • Input validation on every send
  • Idempotency key for every transactional email
  • At least one render/link test per template

Recommended

SaaS Essentials Pack

21+ Templates · 60+ Variations. One-time purchase, lifetime updates.

$19.95$9.95Get it

If you want the fast path: start with a small set of battle-tested templates (welcome, verification, password reset, invoice, trial ending) and iterate from there.

Stop building emails from scratch

Get production-ready React Email templates. Tested across Gmail, Outlook & Apple Mail. One-time purchase, lifetime updates.

Browse templates