Skip to content
← All posts
012 min read

Build Email Templates with React: React Email + Resend in Node.js

  • react
  • web-development
  • typescript

In 2023 I wrote about sending templated emails with SendGrid’s dynamic templates, where the template lives in a web dashboard. It works, but your templates end up outside your codebase, with no code review and no type safety.

React Email + Resend: Templated Emails in Node.js — by Chirag Mehta
React Email + Resend: Templated Emails in Node.js

React Email fixes that. Your email templates become React components that live in your repo.

Install

npm install resend @react-email/components react react-dom
npm install -D react-email

Add a preview script to package.json:

{
"scripts": {
"email:dev": "email dev"
}
}

Write a template

Create emails/WelcomeEmail.tsx:

import {
Body, Button, Container, Head, Heading, Html, Preview, Text,
} from "@react-email/components";
type Props = { name: string; dashboardUrl: string };
export function WelcomeEmail({ name, dashboardUrl }: Props) {
return (
<Html>
<Head />
<Preview>Welcome aboard, {name}</Preview>
<Body style={{ backgroundColor: "#f6f9fc", fontFamily: "Arial, sans-serif" }}>
<Container style={{ backgroundColor: "#ffffff", padding: "32px", borderRadius: "8px" }}>
<Heading>Welcome, {name}!</Heading>
<Text>Your account is ready. Click below to get started.</Text>
<Button
href={dashboardUrl}
style={{ backgroundColor: "#2563eb", color: "#fff", padding: "12px 20px", borderRadius: "6px" }}
>
Open dashboard
</Button>
</Container>
</Body>
</Html>
);
}
export default WelcomeEmail;

The components turn into the table-based HTML that email clients like Outlook need, so you don’t have to write it by hand.

Preview locally

npm run email:dev

This opens a local preview of everything in your emails folder. Edit the component and the preview updates. No more sending test emails to yourself after every change.

Send it with Resend

Resend accepts a React component directly. Pass it as a function call, not JSX (Resend docs):

import { Resend } from "resend";
import { WelcomeEmail } from "./emails/WelcomeEmail";
const resend = new Resend(process.env.RESEND_API_KEY);
const { data, error } = await resend.emails.send({
from: "My App <hello@myapp.com>",
to: ["new.user@example.com"],
subject: "Welcome to My App",
react: WelcomeEmail({ name: "Priya", dashboardUrl: "https://myapp.com/dashboard" }),
});
if (error) console.error(error);

Or render to HTML for any provider

Or render to HTML for any provider
Or render to HTML for any provider

Using Nodemailer or SES? Render the component to an HTML string first:

import { render } from "@react-email/components";
const html = await render(<WelcomeEmail name="Priya" dashboardUrl="https://myapp.com/dashboard" />);
await transporter.sendMail({ to: "new.user@example.com", subject: "Welcome", html });
Dashboard template vs. React component
Dashboard template vs. React component

Tips from moving templates into code

  • Keep props typed. If a template needs resetUrl, TypeScript won't let you forget it.
  • Use inline style objects. Many email clients ignore stylesheets.
  • Always include a Preview line. It's the gray text people see in their inbox list.
  • Make a shared Layout component for your logo and footer.

Moving templates from a dashboard into code feels small, but your emails now get reviewed, versioned and tested like the rest of your app.

Author card for Chirag Mehta, Full-Stack Developer specializing in React, Next.js and Node.js. Links: github.com/chiragmehta900, linkedin.com/in/chiragmehta900, medium.com/@chiragmehta900
Chirag Mehta

Originally published on Medium

Clap, comment or follow along there

Read on Medium →