.agents/skills/react-email/SKILL.md
Use when creating email templates with React - welcome emails, password resets, notifications, order confirmations, or transactional emails that need to render across email clients.
npx skillsauth add curvenote/curvenote react-emailInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build and send HTML emails using React components. A modern, component-based approach to email development that works across all major email clients by compiling to compatible HTML.
When NOT to use:
Scaffold a new React Email project:
npx create-email@latest
Equivalent commands: yarn create email, pnpm create email, bun create email
Then install dependencies and start the dev server:
cd react-email-starter
npm install
npm run dev
The server runs at localhost:3000 with a preview interface for templates in the emails folder.
Add dependencies to run the email server:
npm install react-email @react-email/preview-server -D -E
npm install @react-email/components react react-dom -E
Add a script to your package.json:
{
"scripts": {
"email:dev": "email dev"
}
}
If the emails are in a different folder, you can specify the directory:
{
"scripts": {
"email:dev": "email dev --dir src/emails"
}
}
Ensure tsconfig.json includes proper JSX support.
Create an email component with proper structure using the Tailwind component for styling:
import {
Html,
Head,
Preview,
Body,
Container,
Heading,
Text,
Button,
Tailwind,
pixelBasedPreset
} from '@react-email/components';
interface WelcomeEmailProps {
name: string;
verificationUrl: string;
}
export default function WelcomeEmail({ name, verificationUrl }: WelcomeEmailProps) {
return (
<Html lang="en">
<Tailwind
config={{
presets: [pixelBasedPreset],
theme: {
extend: {
colors: {
brand: '#007bff',
},
},
},
}}
>
<Head />
<Body className="bg-gray-100 font-sans">
<Preview>Welcome - Verify your email</Preview>
<Container className="max-w-xl mx-auto p-5">
<Heading className="text-2xl text-gray-800">
Welcome!
</Heading>
<Text className="text-base text-gray-800">
Hi {name}, thanks for signing up!
</Text>
<Button
href={verificationUrl}
className="bg-brand text-white px-5 py-3 rounded block text-center no-underline box-border"
>
Verify Email
</Button>
</Container>
</Body>
</Tailwind>
</Html>
);
}
WelcomeEmail.PreviewProps = {
name: 'John Doe',
verificationUrl: 'https://example.com/verify/abc123'
} satisfies WelcomeEmailProps;
export { WelcomeEmail };
See references/COMPONENTS.md for complete component documentation.
Core Structure:
Html - Root wrapper with lang attributeHead - Meta elements, styles, fontsBody - Main content wrapperContainer - Centers content (max-width layout)Section - Layout sectionsRow & Column - Multi-column layouts (table-based, won't stack on mobile)Tailwind - Enables Tailwind CSS utility classesContent:
Preview - Inbox preview text, place immediately after Body opening tagHeading - h1-h6 headingsText - ParagraphsButton - Styled link buttonsLink - HyperlinksImg - Images (use absolute URLs; copy local images to /emails/static/ and use dev server BASE_URL in dev, ask user for production BASE_URL)Hr - Horizontal dividersSpecialized:
CodeBlock - Syntax-highlighted codeCodeInline - Inline codeMarkdown - Render markdownFont - Custom web fonts{{name}}) directly in TypeScript code - reference props directlyFor example, if the user explicitly asks for a variable following the pattern {{variableName}}:
const EmailTemplate = (props) => {
return (
<h1>Hello, {props.variableName}!</h1>
);
}
EmailTemplate.PreviewProps = {
variableName: "{{variableName}}",
};
export default EmailTemplate;
Never write the {{variableName}} pattern directly in the component structure - explain this makes the template invalid.
See references/STYLING.md for complete styling documentation, including shared Tailwind config patterns for multiple templates.
Key rules:
pixelBasedPreset - email clients don't support rem unitsRow/Column componentssm:, md:) or theme selectors (dark:)border-solid, border-dashed)box-border on buttonsimport { render } from '@react-email/components';
import { WelcomeEmail } from './emails/welcome';
const html = await render(
<WelcomeEmail name="John" verificationUrl="https://example.com/verify" />
);
import { render } from '@react-email/components';
import { WelcomeEmail } from './emails/welcome';
const text = await render(
<WelcomeEmail name="John" verificationUrl="https://example.com/verify" />,
{ plainText: true }
);
React Email supports any email service provider. See references/SENDING.md for details.
Quick example using Resend:
import { Resend } from 'resend';
import { WelcomeEmail } from './emails/welcome';
const resend = new Resend(process.env.RESEND_API_KEY);
const { data, error } = await resend.emails.send({
from: 'Acme <[email protected]>',
to: ['[email protected]'],
subject: 'Welcome to Acme',
react: <WelcomeEmail name="John" verificationUrl="https://example.com/verify" />
});
if (error) {
console.error('Failed to send:', error);
}
Resend can receive a React component directly. If not included in the call, Resend will automatically include a plain-text version of the email.
See references/I18N.md for complete i18n documentation with examples for next-intl, react-i18next, and react-intl.
| Mistake | Fix |
|---------|-----|
| Using flexbox/grid | Use Row and Column components or tables |
| Using rem units | Use pixelBasedPreset with Tailwind |
| Using SVG images | Use PNG or JPG instead |
| Using media queries (sm:, md:) | Design mobile-first with stacked layouts |
| Template vars in JSX ({{name}}) | Use props: {props.name} |
| Missing border type | Always specify: border-solid, border-dashed, etc. |
| Fixed image dimensions on content images | Use responsive: w-full h-auto (fixed OK for small icons) |
| Emails over 102KB | Gmail clips larger emails - reduce size |
alt text. If local development, copy to emails/static/.from addresses.development
Use when setting up an email inbox for an AI agent (Moltbot, Clawdbot, or similar) - configuring inbound email, webhooks, tunneling for local development, and implementing security measures to prevent prompt injection attacks.
testing
Use when working with Resend email platform - routes to specific sub-skills for sending, receiving, audiences, or broadcasts.
development
Build full-stack React applications using React Router's framework mode. Use when configuring routes, working with loaders and actions, handling forms, handling navigation, pending/optimistic UI, error boundaries, or working with react-router.config.ts or other react router conventions.
tools
Prisma Postgres setup and operations guidance across Console, create-db CLI, Management API, and Management API SDK. Use when creating Prisma Postgres databases, working in Prisma Console, provisioning with create-db/create-pg/create-postgres, or integrating programmatic provisioning with service tokens or OAuth.