git clone https://github.com/NeverSight/learn-skills.dev
T=$(mktemp -d) && git clone --depth=1 https://github.com/NeverSight/learn-skills.dev "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/skills-md/agents-inc/skills/api-email-setup-resend" ~/.claude/skills/neversight-learn-skills-dev-api-email-setup-resend && rm -rf "$T"
data/skills-md/agents-inc/skills/api-email-setup-resend/SKILL.mdResend Email & React Email Setup
Quick Guide: Resend email API with React Email templates. Use the
prop to pass components directly toreact-- no manualresend.emails.send()needed. Keep email templates in a dedicated package for monorepo separation. Verify your sending domain before production. Userender()(not@react-email/render) if you need to render to HTML strings manually.@react-email/components
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
, named constants)import type
(You MUST use
environment variable -- NEVER hardcode API keys)RESEND_API_KEY
(You MUST verify your sending domain in Resend dashboard before production -- unverified domains only send to your own email)
(You MUST use
for email UI components and @react-email/components
for HTML rendering -- these are separate packages)@react-email/render
(You MUST use
as the primary sending pattern -- manual resend.emails.send({ react: MyTemplate(props) })
to HTML is only needed for non-Resend senders)render()
</critical_requirements>
Auto-detection: Resend setup, resend install, React Email setup, email templates setup, RESEND_API_KEY, domain verification, SPF DKIM DMARC, transactional email setup, email preview server, @react-email/components, react-email
When to use:
- Initial Resend + React Email setup in a project
- Configuring domain verification and DNS records
- Setting up the email preview dev server
- Structuring email templates in a monorepo
When NOT to use:
- Marketing email campaigns (use a dedicated marketing email platform)
- SMS or push notifications (different service)
- Non-JavaScript backends (this skill covers React Email templates, which require Node.js)
- Need SMTP relay (Resend is API-only)
Detailed Resources:
- examples/core.md - Client setup, sending patterns, template structure, preview server
<philosophy>
Philosophy
Resend is a developer-first email API built by the creators of React Email. React Email brings modern component patterns to email development, replacing legacy table-based HTML.
Core principles:
- Emails as React components - Write emails with JSX, Tailwind CSS, and TypeScript
- Preview before send - Local dev server shows exact email rendering
- Monorepo separation - Email templates in dedicated package, not mixed with app code
prop overreact
- Resend SDK renders components internally when you pass them via therender()
propreact
<patterns>
Core Patterns
Pattern 1: Sending with the react
Prop (Preferred)
reactThe Resend SDK accepts React components directly via the
react prop -- no manual HTML rendering needed.
const { data, error } = await resend.emails.send({ from: "Your App <noreply@yourdomain.com>", to: ["user@example.com"], subject: "Welcome!", react: WelcomeEmail({ userName: "John" }), });
Why good: No manual
render() call, SDK handles conversion internally, cleaner code
When to use
instead: Only when sending via a non-Resend email provider that needs an HTML string. Import from render()
@react-email/render, not @react-email/components.
See examples/core.md for full sending and rendering examples.
Pattern 2: Domain Verification
Verify your domain to send from custom addresses. Unverified accounts can only send to your own email.
- Go to Resend Dashboard > Domains > Add Domain
- Add the DNS records Resend provides to your DNS provider:
- SPF (TXT):
v=spf1 include:amazonses.com ~all - DKIM (3 CNAME records): Values provided by Resend
- DMARC (TXT, recommended):
v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com
- SPF (TXT):
- Click Verify -- DNS propagation can take up to 48 hours
Why this matters: Unverified domains are limited to sending to your account email only. Production sending requires verification. Proper DNS records prevent emails from landing in spam.
Pattern 3: Monorepo Package Structure
Keep email templates in a dedicated package, separate from your application code.
packages/emails/ ├── package.json ├── tsconfig.json ├── src/ │ ├── index.ts # Re-export all templates │ ├── client.ts # Resend client singleton │ ├── layouts/ │ │ └── base-layout.tsx # Shared layout wrapper │ ├── components/ │ │ ├── button.tsx # Reusable email button │ │ └── footer.tsx # Email footer │ └── templates/ │ ├── verification-email.tsx │ ├── password-reset.tsx │ └── welcome-email.tsx └── emails/ # For react-email dev server
Why good: Reusable across apps, prevents bundling issues, clean separation of concerns
See examples/core.md for full client setup and template examples.
Pattern 4: Email Error Handling
Resend returns
{ data, error } -- always check the error.
const { data, error } = await resend.emails.send(emailOptions); if (error) { console.error("[Email] Send failed:", error.name, error.message); return { success: false, error: error.message }; } return { success: true, id: data?.id };
Why good: Explicit error checking, structured logging, returns typed result. Never ignore the error response -- the SDK does not throw on send failures.
Pattern 5: Webhook Verification
Always verify webhook signatures before processing events. The
verify() method throws on invalid signatures.
const payload = await request.text(); // Raw body, NOT parsed JSON try { const event = resend.webhooks.verify({ payload, headers: { id: request.headers.get("svix-id") ?? "", timestamp: request.headers.get("svix-timestamp") ?? "", signature: request.headers.get("svix-signature") ?? "", }, webhookSecret: process.env.RESEND_WEBHOOK_SECRET!, }); // event.type: "email.sent" | "email.delivered" | "email.bounced" | etc. } catch { return new Response("Invalid webhook signature", { status: 400 }); }
Why good: SDK's built-in verification, uses raw body (not parsed JSON which breaks signature), try/catch handles invalid signatures
Gotcha: You MUST use
request.text() not request.json() -- parsing as JSON before verification breaks the cryptographic signature. The verify() method throws on failure (unlike emails.send() which returns { data, error }).
</patterns>
<red_flags>
RED FLAGS
High Priority:
- Hardcoded
in source code (security vulnerability, visible in git)RESEND_API_KEY - Sending from unverified domain in production (emails fail or go to spam)
- Importing
fromrender
(wrong package -- use@react-email/components
)@react-email/render - Not awaiting
when using it (returns Promise, email body becomesrender()
)[object Promise]
Medium Priority:
- No error handling on
(silent failures)resend.emails.send() - Email templates inside app directory instead of dedicated package (bundling issues in monorepo)
- Using
instead ofrequest.json()
for webhook payload (breaks signature verification)request.text()
Gotchas & Edge Cases:
- Resend free tier: 100 emails/day, 3000 emails/month
- Unverified domains can only send to your account's email address
- DNS propagation takes up to 48 hours for domain verification
- React Email dev server creates a
folder in your project.react-email - Using Grid, Flexbox, or
in email templates does not work in Gmail/Outlookbox-shadow - Use
units in emails --px
renders inconsistently across email clientsrem - In Resend SDK v6.1.0+, some bundlers may error on
-- add@react-email/render
to your bundler's external packages config if you see resolution errorsresend
is for UI components (Body, Button, etc.);@react-email/components
is for the@react-email/render
utility -- they are separate packagesrender()
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
(You MUST use
environment variable -- NEVER hardcode API keys)RESEND_API_KEY
(You MUST verify your sending domain in Resend dashboard before production -- unverified domains only send to your own email)
(You MUST use
for email UI components and @react-email/components
for HTML rendering -- these are separate packages)@react-email/render
(You MUST use
as the primary sending pattern -- manual resend.emails.send({ react: MyTemplate(props) })
to HTML is only needed for non-Resend senders)render()
Failure to follow these rules will cause email delivery failures or security vulnerabilities.
</critical_reminders>