| name | react-email |
| description | React Email v5 — escribir emails transaccionales con componentes React + Tailwind 4. Resend lo creó. Soporta dark mode, MJML internamente, preview server local. Trigger: email, transactional, resend, mailgun, sendgrid, welcome email, password reset, invoice email.
|
| when_to_use | Emails transaccionales (welcome, password reset, invoice, magic link).
Newsletters con HTML rico.
Integración con Resend/Mailgun/SendGrid/Postmark.
Preview server local para diseñar emails.
|
| when_NOT_to_use | Marketing emails masivos (usá Mailchimp/Beehiv directo).
Mass send sin opt-in (legal: GDPR/CAN-SPAM).
|
React Email v5
Emails transaccionales con DX premium — React + Tailwind, dark mode, preview local.
Install
pnpm add react-email @react-email/components
pnpm dlx react-email dev
pnpm add -D @react-email/render
Estructura proyecto
emails/
welcome.tsx <- componentes React
password-reset.tsx
invoice.tsx
src/
lib/email.ts <- helper de send
Email básico
import { Html, Head, Body, Container, Heading, Text, Button, Tailwind } from "@react-email/components";
export default function WelcomeEmail({ name }: { name: string }) {
return (
<Html>
<Head />
<Tailwind>
<Body className="bg-white font-sans">
<Container className="mx-auto max-w-[560px] p-6">
<Heading className="text-2xl font-bold text-gray-900">Bienvenido, {name}</Heading>
<Text className="text-base text-gray-700">Gracias por registrarte. Confirmá tu cuenta:</Text>
<Button
href="https://app.com/verify?token=abc"
className="rounded-md bg-black px-6 py-3 text-white"
>
Confirmar email
</Button>
</Container>
</Body>
</Tailwind>
</Html>
);
}
Send con Resend
pnpm add resend
import { Resend } from "resend";
import WelcomeEmail from "../../emails/welcome";
const resend = new Resend(process.env.RESEND_API_KEY);
export async function sendWelcome(to: string, name: string) {
await resend.emails.send({
from: "App <hello@app.com>",
to,
subject: "Bienvenido a App",
react: WelcomeEmail({ name }),
});
}
Preview server (dev)
pnpm dlx react-email dev
Hot-reload automático, soporte dark mode toggle, mobile preview.
Render a HTML/text (SSR o cron)
import { render } from "@react-email/render";
const html = await render(WelcomeEmail({ name: "Nico" }));
const text = await render(WelcomeEmail({ name: "Nico" }), { plainText: true });
Componentes built-in
| Componente | Uso |
|---|
<Html> <Head> <Body> | Wrapper obligatorio |
<Container> | Box centrado max-width |
<Section> | Bloque vertical |
<Heading> | h1-h6 con styling email-safe |
<Text> | p con line-height email-safe |
<Button> | Botón table-based (Outlook compat) |
<Img> | Image con width/height obligatorio |
<Link> | Anchor styled |
<Hr> | Divider |
<Tailwind> | Habilita className Tailwind |
<Preview> | Texto preheader (lo que ve antes de abrir) |
<CodeBlock> <CodeInline> | Para emails dev |
Reglas no negociables
<Tailwind> o nada — sin él los className Tailwind se ignoran.
- Width images obligatorio — Outlook rompe sin
width=.
<Preview> siempre como primer hijo de <Body> — controla preheader.
- Inline styles con Tailwind — React Email los convierte automático. NO uses
<style> en <Head> salvo media queries.
- Dark mode: usá
dark: prefix de Tailwind. Probá en Apple Mail (mejor cliente para dark).
- Test en: Gmail (web/iOS), Outlook (Windows), Apple Mail (macOS), Yahoo. Usá Litmus o Email on Acid.
- Subject + preheader siempre distintos — no repitas.
Anti-patrones
- ❌ Usar componentes React custom complejos — emails NO son apps SPA.
- ❌ Animaciones / gradientes sin fallback — Outlook los descarta.
- ❌ Background images sin VML fallback — Outlook no las soporta.
- ❌ Fuentes web sin fallback —
font-family: 'Inter', system-ui, sans-serif mínimo.
Recursos