Building Emails with React Email and AI
Component-driven email development meets AI code generation
Priya Sharma
Frontend Email Developer
The Problem React Email Solves
Traditional HTML email development is painful. You are writing table-based markup from 2005, copy-pasting inline styles everywhere, testing across dozens of email clients, and maintaining templates that are nearly impossible to refactor. When your design team changes the primary button color, you are doing a find-and-replace across 30 template files and hoping you did not miss one.
React Email brings modern component architecture to email development. Instead of raw HTML tables, you build emails with composable React components—<Button>, <Section>, <Column>, <Heading>—that compile to battle-tested, cross-client-compatible HTML. You get TypeScript type safety, component reuse, props-based customization, and the entire React ecosystem for building and testing.
Getting Started with React Email
Install React Email and its component library, then create your first email template:
npm install react-email @react-email/components
// emails/welcome.tsx
import {
Html, Head, Body, Container, Section,
Text, Button, Heading, Hr, Preview,
} from "@react-email/components";
interface WelcomeEmailProps {
name: string;
loginUrl: string;
}
export default function WelcomeEmail({ name, loginUrl }: WelcomeEmailProps) {
return (
<Html>
<Head />
<Preview>Welcome to our platform, {name}</Preview>
<Body style={body}>
<Container style={container}>
<Heading style={h1}>Welcome, {name}</Heading>
<Text style={text}>
Thanks for signing up. Click below to get started.
</Text>
<Section style={buttonContainer}>
<Button style={button} href={loginUrl}>
Open your dashboard
</Button>
</Section>
<Hr style={hr} />
<Text style={footer}>
Questions? Reply to this email.
</Text>
</Container>
</Body>
</Html>
);
}
const body = { backgroundColor: "#f5f5f5", fontFamily: "Arial, sans-serif" };
const container = { backgroundColor: "#ffffff", margin: "0 auto", padding: "40px", maxWidth: "600px" };
const h1 = { color: "#1a1a1a", fontSize: "24px", margin: "0 0 16px" };
const text = { color: "#555", fontSize: "16px", lineHeight: "1.5" };
const buttonContainer = { textAlign: "center" as const, margin: "24px 0" };
const button = { backgroundColor: "#0066ff", color: "#fff", padding: "14px 28px", borderRadius: "6px" };
const hr = { borderColor: "#e5e5e5", margin: "24px 0" };
const footer = { color: "#999", fontSize: "13px" };Run npx react-email dev to launch a local preview server where you can see your email rendered in real time as you edit. This is a massive improvement over the traditional workflow of editing HTML, sending a test email, and checking it in multiple clients.
Pairing React Email with Resend
React Email was built alongside Resend, and the integration is seamless. You render your React component to HTML and pass it directly to the Resend API:
import { Resend } from "resend";
import { render } from "@react-email/render";
import WelcomeEmail from "./emails/welcome";
const resend = new Resend(process.env.RESEND_API_KEY);
async function sendWelcome(user: { email: string; name: string }) {
const html = await render(
WelcomeEmail({ name: user.name, loginUrl: "https://app.example.com" })
);
await resend.emails.send({
from: "onboarding@yourdomain.com",
to: user.email,
subject: `Welcome, ${user.name}`,
html,
});
}You can also use React Email templates with other ESPs. The render() function outputs standard HTML that works with SendGrid, Postmark, Mailgun, brew.new, or any other service that accepts HTML email content.
AI-Powered Email Generation
The intersection of React Email and AI is where things get particularly interesting. Because React Email templates are structured, typed code, they are ideal targets for AI generation. You can describe an email in natural language and get a well-structured React Email component back.
Brew takes this approach natively—its AI email builder generates React Email code under the hood. You describe the email you want (“a password reset email with our brand colors, a reset button, and a security notice”), and Brew generates a complete React Email component that you can export, customize, and version-control alongside your application code.
// Using brew.new to generate a React Email template
const template = await brew.templates.generateReactEmail({
description: "Password reset email with a reset button and security warning",
brandColors: { primary: "#0066ff", background: "#f5f5f5" },
variables: ["resetUrl", "userName", "expiresIn"],
});
// Returns a complete React Email component as a string
// that you can save to your project
console.log(template.code);
// export default function PasswordReset({ resetUrl, userName, expiresIn }) { ... }You can also use general-purpose AI tools (ChatGPT, Claude) with React Email. The key is to include the React Email component library documentation in your prompt context, so the model generates valid component usage rather than raw HTML tables.
Building a Component Library
As your email needs grow, build a shared component library that enforces brand consistency across all your templates:
// components/email-button.tsx
import { Button } from "@react-email/components";
interface EmailButtonProps {
href: string;
children: React.ReactNode;
variant?: "primary" | "secondary";
}
export function EmailButton({ href, children, variant = "primary" }: EmailButtonProps) {
const styles = {
primary: { backgroundColor: "#0066ff", color: "#ffffff" },
secondary: { backgroundColor: "#f0f0f0", color: "#333333" },
};
return (
<Button
href={href}
style={{
...styles[variant],
padding: "14px 28px",
borderRadius: "6px",
fontFamily: "Arial, sans-serif",
fontSize: "16px",
fontWeight: "bold",
textDecoration: "none",
display: "inline-block",
}}
>
{children}
</Button>
);
}Build components for your header, footer, button, callout box, code block, and any other pattern you use repeatedly. This is the same component-driven approach that powers modern web development, applied to email. The payoff is the same: faster iteration, fewer bugs, and consistent output.
Testing and Previewing
React Email’s dev server gives you instant local previews, but you still need to test across real email clients. The rendered HTML output should be run through a cross-client testing tool like Litmus or Email on Acid. Brew’s preview feature renders your email across 90+ client configurations so you can catch rendering issues before sending.
For automated testing, render your components in your test suite and assert on the HTML output:
import { render } from "@react-email/render";
import WelcomeEmail from "./emails/welcome";
describe("WelcomeEmail", () => {
it("renders the user name", async () => {
const html = await render(
WelcomeEmail({ name: "Alex", loginUrl: "https://example.com" })
);
expect(html).toContain("Welcome, Alex");
expect(html).toContain("https://example.com");
});
it("includes a preheader", async () => {
const html = await render(
WelcomeEmail({ name: "Alex", loginUrl: "https://example.com" })
);
expect(html).toContain("Welcome to our platform, Alex");
});
});This approach catches regressions early and pairs well with CI pipelines. When you update a shared component, your tests verify that all templates still render the expected content. Combined with visual regression testing via Brew or Litmus snapshots, you get comprehensive coverage of both content and rendering.
Priya Sharma
Frontend Email Developer
Priya makes emails look beautiful everywhere. She specializes in cross-client rendering, responsive design, and React Email components.