Skip to content
Next.js+Resend
Stack Integration

Next.js + Resend: Production Email Architecture

Resend pairs with Next.js App Router to deliver transactional emails via React components — typed templates, reliable delivery, and sender domain authentication in one API.

Use Cases
  1. Transactional emails triggered from Next.js API Route Handlers
  2. React Email templates shared between email and web UI components
  3. Bulk notification emails triggered by Supabase or database events
  4. Automated sequences for onboarding, trial expiry, and billing events
Implementation

Create reusable React Email components in an emails/ directory and import them into Route Handlers. Initialize Resend with the API key from a server-only environment variable. Call resend.emails.send() server-side only — never in client components or browser-facing code. Configure your sender domain's DKIM and SPF records in DNS before sending to real users; Resend's domain verification dashboard provides the exact records to add.

In detail

How the pieces connect

Resend runs entirely on the server side of Next.js. The Resend client is constructed with new Resend(process.env.RESEND_API_KEY) and only ever lives inside a Route Handler (app/api/.../route.ts), a Server Action, or a server component's data path — never in a "use client" file, because the API key would ship to the browser.

React Email is where the two halves overlap. You author templates as ordinary React components under emails/, then pass the component instance to resend.emails.send({ react: <WelcomeEmail name={name} /> }). Resend renders that component to HTML server-side before handing it to its delivery API, so the same JSX primitives you know from the web UI describe the email body. The handler returns { data, error } — check error rather than assuming success.

Production gotchas

The non-obvious failures cluster around two things: domain setup and async timing.

  • Domain verification is gating, not cosmetic. Until you add the DKIM and SPF/Return-Path records Resend generates and the dashboard flips the domain to verified, mail to real recipients either bounces or lands in spam. You can only send from onboarding@resend.dev before that.
  • Don't block the request on the send. Awaiting resend.emails.send() inline ties the user's response time to Resend's latency. For non-critical mail, kick it off with after() from next/server (or a queue) so the handler responds first.
  • Serverless cold starts mean the first send after idle is slower — fine for transactional mail, but don't rely on sub-second delivery.
  • Rate limits apply per account; batch large fan-outs with resend.batch.send() instead of looping individual calls.

Idempotency and webhooks

Two patterns keep delivery honest at scale.

First, idempotency keys. A retried Route Handler (client retry, serverless re-invocation, a webhook redelivery) can fire the same send twice. resend.emails.send(payload, { idempotencyKey: "order-1234-receipt" }) makes Resend dedupe within its window, so one logical event yields one email.

Second, event webhooks. Resend can POST email.delivered, email.bounced, and email.complained events to a Next.js Route Handler. Verify the signature before trusting the payload — Resend signs webhooks with Svix, so use the Webhook verifier with your signing secret against the raw request body and the svix-id / svix-timestamp / svix-signature headers. Read the body with req.text(), not req.json(), because parsing reshapes the bytes and breaks the signature check. Act on bounces by suppressing future sends to that address.

When this combo fits — and when it doesn't

It fits when email is transactional and event-driven: receipts, password resets, onboarding sequences, trial-expiry and billing notices fired from Route Handlers or database triggers. Sharing React components between your app UI and your email templates removes the usual drift between the two, and a Next.js app on a serverless host needs no separate mail server.

It fits less well for high-volume marketing campaigns with list management, segmentation, and unsubscribe-center tooling — that's a different product category, and you'd reach for a dedicated ESP with audience features. It's also not a fit if you need an on-prem SMTP relay for compliance, since Resend is API-first and hosted. For typical SaaS transactional mail, though, the pairing keeps templates type-checked and the send path on the server where the key belongs.

Other integration guidesView all →
Related

Need this built?