Next.js App Router & React Email

Full example demonstrating how to send React Email templates through Next.js Route Handlers.

You can render beautiful, responsive transactional templates using React Email and dispatch them through your Next.js App Router API endpoints.


1. Install Dependencies

pnpm add resend @react-email/components

2. Create the Email Template (emails/WelcomeEmail.tsx)

import * as React from 'react';
import {
  Html,
  Head,
  Preview,
  Body,
  Container,
  Section,
  Text,
  Heading,
  Button,
  Hr,
} from '@react-email/components';

interface WelcomeEmailProps {
  name: string;
  loginUrl: string;
}

export function WelcomeEmail({ name, loginUrl }: WelcomeEmailProps) {
  return (
    <Html>
      <Head />
      <Preview>Welcome to your sovereign email workspace</Preview>
      <Body style={{ backgroundColor: '#050505', fontFamily: 'sans-serif', color: '#EDEDED' }}>
        <Container style={{ margin: '0 auto', padding: '40px 20px', maxWidth: '560px' }}>
          <Section style={{ backgroundColor: '#0a0d14', borderRadius: '12px', border: '1px solid #1f2736', padding: '32px' }}>
            <Heading style={{ fontSize: '24px', fontWeight: 'bold', color: '#FF6600', marginBottom: '16px' }}>
              Welcome, {name}!
            </Heading>
            <Text style={{ fontSize: '15px', lineHeight: '24px', color: '#D1D5DB' }}>
              Your EmitMail self-hosted email infrastructure is fully configured with 2048-bit RSA DKIM cryptographic keys.
            </Text>
            <Section style={{ marginTop: '24px', marginBottom: '24px' }}>
              <Button
                href={loginUrl}
                style={{
                  backgroundColor: '#FF6600',
                  borderRadius: '8px',
                  color: '#FFFFFF',
                  fontSize: '14px',
                  fontWeight: '600',
                  padding: '12px 24px',
                  textDecoration: 'none',
                }}
              >
                Access Dashboard
              </Button>
            </Section>
            <Hr style={{ borderColor: '#1f2736', margin: '24px 0' }} />
            <Text style={{ fontSize: '12px', color: '#6B7280' }}>
              Sent through your EmitMail server.
            </Text>
          </Section>
        </Container>
      </Body>
    </Html>
  );
}

3. Next.js Route Handler (app/api/send/route.ts)

import { NextResponse } from 'next/server';
import { Resend } from 'resend';
import { WelcomeEmail } from '@/emails/WelcomeEmail';

// Set RESEND_BASE_URL to the API origin for your EmitMail deployment.
const resend = new Resend(process.env.RESEND_API_KEY, {
  baseUrl: process.env.RESEND_BASE_URL,
});

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

    const { data, error } = await resend.emails.send({
      from: 'EmitMail Team <hello@yourdomain.com>',
      to: [email],
      subject: 'Your sovereign email workspace is active',
      react: WelcomeEmail({ name, loginUrl: 'https://yourdomain.com/login' }),
    });

    if (error) {
      return NextResponse.json({ error }, { status: 400 });
    }

    return NextResponse.json({ success: true, id: data?.id });
  } catch (err: any) {
    return NextResponse.json({ error: err.message }, { status: 500 });
  }
}

On this page