React Email
Build email templates with React Email. Use this skill when the project needs to
You are an email template specialist who builds production email templates using React Email. React Email lets you write email HTML as React components with full TypeScript support, a live preview server, and rendering to standards-compliant HTML that works across all email clients. ## Key Points - Use the Preview component — it controls inbox preview text - Always use inline styles — email clients strip `<style>` tags - Use absolute URLs for all images and links - Create shared components for header, footer, and buttons - Test in the dev server across different data scenarios - Always generate both HTML and plain text versions - Keep images small — many email clients block images by default - Using CSS classes or external stylesheets — email clients strip them - Using relative URLs for images — they break in email clients - Not including a Preview component — inbox shows raw HTML text - Building deeply nested layouts — email rendering engines have limits - Using web-only CSS features (flexbox, grid, CSS variables) in email ## Quick Example ```bash npm install @react-email/components react-email npx react-email init # Optional: scaffolds emails/ directory ``` ```bash npx react-email dev --dir ./emails --port 3001 ```
skilldb get email-services-skills/React EmailFull skill: 234 linesReact Email Template Development
You are an email template specialist who builds production email templates using React Email. React Email lets you write email HTML as React components with full TypeScript support, a live preview server, and rendering to standards-compliant HTML that works across all email clients.
Core Philosophy
Components, not string concatenation
Email HTML is notoriously brittle. React Email gives you tested, cross-client components (Button, Container, Column, Image, Link) that generate the right HTML and inline styles. No more debugging Outlook-specific table layouts by hand.
Provider-agnostic rendering
React Email templates render to plain HTML strings. Send through any provider — Resend, SendGrid, Postmark, SES, Nodemailer. The template layer is completely decoupled from the sending layer.
Preview-driven development
React Email includes a dev server that renders templates in the browser with hot reload. Design emails like you design web pages — see changes instantly.
Setup
Install
npm install @react-email/components react-email
npx react-email init # Optional: scaffolds emails/ directory
Dev server
npx react-email dev --dir ./emails --port 3001
Key Techniques
Basic template
import {
Html, Head, Body, Container, Section,
Text, Button, Img, Hr, Preview,
} from '@react-email/components';
interface WelcomeProps {
name: string;
dashboardUrl: string;
}
export default function WelcomeEmail({ name, dashboardUrl }: WelcomeProps) {
return (
<Html>
<Head />
<Preview>Welcome to the platform, {name}</Preview>
<Body style={main}>
<Container style={container}>
<Img src="https://yourdomain.com/logo.png" width={120} height={40} alt="Logo" />
<Text style={heading}>Welcome, {name}</Text>
<Text style={paragraph}>
Your account is ready. Start exploring the dashboard.
</Text>
<Button style={button} href={dashboardUrl}>
Open Dashboard
</Button>
<Hr style={hr} />
<Text style={footer}>
Questions? Reply to this email.
</Text>
</Container>
</Body>
</Html>
);
}
// Inline styles (required for email clients)
const main = { backgroundColor: '#0a0a0f', fontFamily: 'sans-serif' };
const container = { maxWidth: '560px', margin: '0 auto', padding: '32px' };
const heading = { fontSize: '22px', fontWeight: '700', color: '#e8e8ef' };
const paragraph = { fontSize: '15px', lineHeight: '1.6', color: '#c4c4cc' };
const button = {
backgroundColor: '#d4a843', color: '#08080a', padding: '12px 28px',
borderRadius: '8px', fontSize: '14px', fontWeight: '600', textDecoration: 'none',
};
const hr = { borderColor: '#222230', margin: '24px 0' };
const footer = { fontSize: '12px', color: '#555' };
Render to HTML
import { render } from '@react-email/render';
import WelcomeEmail from './emails/welcome';
// Static render (for sending)
const html = await render(WelcomeEmail({ name: 'Alice', dashboardUrl: '...' }));
// Plain text render
const text = await render(WelcomeEmail({ name: 'Alice', dashboardUrl: '...' }), {
plainText: true,
});
Send with any provider
Resend:
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: 'App <noreply@yourdomain.com>',
to: 'user@example.com',
subject: 'Welcome',
html: await render(WelcomeEmail({ name: 'Alice', dashboardUrl: '...' })),
});
Nodemailer:
await transporter.sendMail({
from: '"App" <noreply@yourdomain.com>',
to: 'user@example.com',
subject: 'Welcome',
html: await render(WelcomeEmail({ name: 'Alice', dashboardUrl: '...' })),
});
Responsive layouts with columns
import { Row, Column } from '@react-email/components';
<Row>
<Column style={{ width: '50%' }}>
<Text>Left column</Text>
</Column>
<Column style={{ width: '50%' }}>
<Text>Right column</Text>
</Column>
</Row>
Conditional content
export default function ReceiptEmail({ plan, amount, isTrial }: Props) {
return (
<Html>
<Body style={main}>
<Container style={container}>
<Text style={heading}>
{isTrial ? 'Trial Started' : 'Payment Confirmed'}
</Text>
{!isTrial && (
<Text style={paragraph}>Amount: {amount}</Text>
)}
{isTrial && (
<Text style={paragraph}>Your trial is active — no charge yet.</Text>
)}
</Container>
</Body>
</Html>
);
}
Available Components
| Component | Use for |
|---|---|
Html, Head, Body | Document structure |
Preview | Preview text shown in inbox |
Container | Centered content wrapper |
Section | Content grouping |
Row, Column | Multi-column layouts |
Text | Paragraphs and headings |
Link | Hyperlinks |
Button | Call-to-action buttons |
Img | Images (use absolute URLs) |
Hr | Horizontal rules |
CodeBlock, CodeInline | Code display |
Heading | Semantic headings |
Tailwind | Tailwind CSS wrapper (utility classes) |
Template Organization
emails/
components/
header.tsx # Shared brand header
footer.tsx # Shared legal footer
button.tsx # Branded CTA button
auth/
welcome.tsx
verify-email.tsx
password-reset.tsx
billing/
receipt.tsx
payment-failed.tsx
subscription-canceled.tsx
product/
feature-announcement.tsx
weekly-summary.tsx
marketing/
newsletter.tsx
Best Practices
- Use the Preview component — it controls inbox preview text
- Always use inline styles — email clients strip
<style>tags - Use absolute URLs for all images and links
- Create shared components for header, footer, and buttons
- Test in the dev server across different data scenarios
- Always generate both HTML and plain text versions
- Keep images small — many email clients block images by default
Anti-Patterns
- Using CSS classes or external stylesheets — email clients strip them
- Using relative URLs for images — they break in email clients
- Not including a Preview component — inbox shows raw HTML text
- Building deeply nested layouts — email rendering engines have limits
- Using web-only CSS features (flexbox, grid, CSS variables) in email
- Not testing with empty/missing props — emails should degrade gracefully
Install this skill directly: skilldb add email-services-skills
Related Skills
AWS Ses
Send email at scale with Amazon SES (Simple Email Service). Use this skill when
Brevo
Send transactional and marketing email with Brevo (formerly Sendinblue). Use this
Courier
Send transactional notifications including email with Courier. Use this skill when
Customerio
Send transactional and marketing email with Customer.io. Use this skill when the
Email Deliverability
Optimize email deliverability across any provider. Use this skill when the project
Loops
Send transactional and marketing email with Loops. Use this skill when the project