React Email

Getting Started with React Email in Next.js

React Emails ProFebruary 25, 20268 min read

React Email lets you build transactional emails with the same component model you use for your UI. No more wrangling raw HTML tables or debugging inline styles across dozens of email clients. In this guide, you'll go from zero to sending your first email in a Next.js project.

Prerequisites

Before you start, make sure you have:

  • Node.js 18+ installed
  • A Next.js 14 or 15 project (App Router or Pages Router both work)
  • An email sending service account — Resend, SendGrid, Postmark, or AWS SES all work

Step 1: Install React Email

Add the core packages to your project. react-email gives you the dev server for previewing templates, and @react-email/components provides the cross-client-safe primitives.

npm install react-email @react-email/components

If you're using Resend as your sending service (recommended for Next.js projects), add it too:

npm install resend

Step 2: Create Your First Template

Create an emails/ directory at the root of your project. React Email looks for templates here by default.

emails/welcome.tsx
import {
  Html,
  Head,
  Preview,
  Body,
  Container,
  Section,
  Text,
  Button,
  Hr,
} from "@react-email/components";

type WelcomeEmailProps = {
  name: string;
  loginUrl: string;
};

export default function WelcomeEmail({ name, loginUrl }: WelcomeEmailProps) {
  return (
    <Html>
      <Head />
      <Preview>Welcome to our platform, {name}!</Preview>
      <Body style={main}>
        <Container style={container}>
          <Text style={heading}>Welcome, {name}!</Text>
          <Text style={paragraph}>
            Thanks for signing up. Your account is ready to go.
          </Text>
          <Section style={buttonContainer}>
            <Button style={button} href={loginUrl}>
              Go to Dashboard
            </Button>
          </Section>
          <Hr style={hr} />
          <Text style={footer}>
            If you didn&apos;t create this account, you can ignore this email.
          </Text>
        </Container>
      </Body>
    </Html>
  );
}

const main = {
  backgroundColor: "#f6f9fc",
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
};

const container = {
  backgroundColor: "#ffffff",
  margin: "0 auto",
  padding: "40px 20px",
  maxWidth: "560px",
};

const heading = {
  fontSize: "24px",
  fontWeight: "600" as const,
  color: "#1a1a1a",
  margin: "0 0 16px",
};

const paragraph = {
  fontSize: "16px",
  lineHeight: "26px",
  color: "#484848",
};

const buttonContainer = {
  textAlign: "center" as const,
  margin: "24px 0",
};

const button = {
  backgroundColor: "#000000",
  borderRadius: "6px",
  color: "#ffffff",
  fontSize: "14px",
  fontWeight: "600" as const,
  textDecoration: "none",
  padding: "12px 24px",
};

const hr = {
  borderColor: "#e6ebf1",
  margin: "24px 0",
};

const footer = {
  fontSize: "13px",
  color: "#8898aa",
};
React Email uses inline styles instead of CSS classes because most email clients strip <style> tags. The component primitives handle the cross-client quirks for you.

Step 3: Preview Your Template

Add the preview script to your package.json:

package.json (scripts)
{
  "scripts": {
    "email": "email dev"
  }
}

Run npm run email and open localhost:3000. You'll see a live preview of your template with hot reload. Change props, tweak styles, and see results instantly.

Step 4: Send Your First Email

Create an API route that renders the template and sends it through your email provider. Here's how it looks with Resend:

app/api/send-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(request: Request) {
  const { name, email, loginUrl } = await request.json();

  const { data, error } = await resend.emails.send({
    from: "Your App <hello@yourapp.com>",
    to: email,
    subject: `Welcome to our platform, ${name}!`,
    react: WelcomeEmail({ name, loginUrl }),
  });

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

  return Response.json({ id: data?.id });
}
The react property on the send call renders your component to HTML automatically. No need to call render() yourself.

Recommended Project Structure

As your template collection grows, organize files by email type. This scales cleanly to dozens of templates:

emails/
├── components/           # Shared email components (headers, footers, buttons)
   ├── email-header.tsx
   ├── email-footer.tsx
   └── email-button.tsx
├── onboarding/
   ├── welcome.tsx
   └── verification.tsx
├── billing/
   ├── invoice.tsx
   └── payment-failed.tsx
└── notifications/
    ├── team-invite.tsx
    └── usage-alert.tsx

Shared Components

Extract repeated elements (logo headers, footer links, CTA buttons) into shared components. This keeps your templates DRY and ensures brand consistency across every email you send.

emails/components/email-header.tsx
import { Img, Section } from "@react-email/components";

export function EmailHeader({ logoUrl }: { logoUrl: string }) {
  return (
    <Section style={{ textAlign: "center", padding: "24px 0" }}>
      <Img src={logoUrl} width="120" height="36" alt="Logo" />
    </Section>
  );
}

Recommended

SaaS Essentials Pack

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

$19.95$9.95Get it

Step 5: Test Across Email Clients

Before going to production, test your templates across major clients. Here's a practical testing checklist:

  • Gmail (web + mobile) — strips most CSS, tests your inline styles
  • Outlook (desktop) — uses Word rendering engine, the toughest client to support
  • Apple Mail — generally great rendering, good baseline
  • Yahoo Mail — aggressive CSS stripping, worth testing
  • Dark mode — check that colors remain readable when clients invert backgrounds
Services like Litmus and Email on Acid let you preview across 90+ client and device combinations without manual testing. Worth the investment for production apps.

Next Steps

With your setup working, here are some areas to explore next:

  • Add TypeScript props to every template for type-safe data passing
  • Set up preview data for the React Email dev server so you can iterate without sending real emails
  • Build a shared design system for your emails (colors, typography, spacing tokens)
  • Integrate with your authentication flow (welcome emails on signup, password resets, magic links)

Building production email templates from scratch takes time — especially getting cross-client rendering right. Pre-built templates can save you weeks and give you a solid starting point that's already been tested across every major email client.

Stop building emails from scratch

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

Browse templates