Agent skill
api-email-setup-resend
Resend email setup, domain verification
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/api-email-setup-resend
SKILL.md
Resend Email & React Email Setup
Quick Guide: Resend email API with React Email templates. Use the
reactprop to pass components directly toresend.emails.send()-- no manualrender()needed. Keep email templates in a dedicated package for monorepo separation. Verify your sending domain before production. Use@react-email/render(not@react-email/components) if you need to render to HTML strings manually.
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST use RESEND_API_KEY environment variable -- NEVER hardcode API keys)
(You MUST verify your sending domain in Resend dashboard before production -- unverified domains only send to your own email)
(You MUST use @react-email/components for email UI components and @react-email/render for HTML rendering -- these are separate packages)
(You MUST use resend.emails.send({ react: MyTemplate(props) }) as the primary sending pattern -- manual render() to HTML is only needed for non-Resend senders)
</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 dedicated marketing tools)
- SMS or push notifications (different service)
- Non-JavaScript backends (consider Postmark, SendGrid)
- Need SMTP relay (Resend is API-only)
Detailed Resources:
- examples/core.md - Client setup, sending patterns, template structure, preview server
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
reactprop overrender()- Resend SDK renders components internally when you pass them via thereactprop
When to use Resend:
- Transactional emails (verification, password reset, notifications)
- React/TypeScript stack wanting best DX
- Need reliable deliverability without managing email infrastructure
When NOT to use Resend:
- Marketing campaigns with complex analytics (use Mailchimp, SendGrid Marketing)
- Very high volume (>1M emails/month) without enterprise plan
- Non-JavaScript backend (consider Postmark, SendGrid)
- Need SMTP relay (Resend is API-only)
Core Patterns
Pattern 1: Sending with the react Prop (Preferred)
The Resend SDK accepts React components directly via the react prop -- no manual HTML rendering needed.
import { Resend } from "resend";
import { WelcomeEmail } from "./templates/welcome-email";
const resend = new Resend(process.env.RESEND_API_KEY);
// Pass the component call directly -- SDK handles rendering
const { data, error } = await resend.emails.send({
from: "Your App <[email protected]>",
to: ["[email protected]"],
subject: "Welcome!",
react: WelcomeEmail({ userName: "John" }),
});
if (error) {
console.error("[Email] Send failed:", error);
}
Why good: No manual render() call, SDK handles conversion internally, cleaner code
// BAD: Unnecessary manual render step
import { render } from "@react-email/render";
const html = await render(WelcomeEmail({ userName: "John" }));
await resend.emails.send({ html, from, to, subject });
Why bad: Extra dependency and await when Resend handles it natively
When to use render() instead: Only when sending via a non-Resend email provider (e.g., Nodemailer, SendGrid) that needs an HTML string. Import from @react-email/render, not @react-email/components.
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:[email protected]
- 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
// BAD: Ignoring the error response
await resend.emails.send(emailOptions);
return { success: true }; // May have silently failed!
Why bad: No error detection, reports success even on failure, no debugging info
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 }).
<red_flags>
RED FLAGS
High Priority:
- Hardcoded
RESEND_API_KEYin source code (security vulnerability, visible in git) - Sending from unverified domain in production (emails fail or go to spam)
- Importing
renderfrom@react-email/components(wrong package -- use@react-email/render) - Not awaiting
render()when using it (returns Promise, email body becomes[object Promise])
Medium Priority:
- No error handling on
resend.emails.send()(silent failures) - Email templates inside app directory instead of dedicated package (bundling issues in monorepo)
- Using
request.json()instead ofrequest.text()for webhook payload (breaks signature verification)
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
.react-emailfolder in your project - Using Grid, Flexbox, or
box-shadowin email templates does not work in Gmail/Outlook - Use
pxunits in emails --remrenders inconsistently across email clients - In Resend SDK v6.1.0+, some bundlers may error on
@react-email/render-- addresendto your bundler's external packages config if you see resolution errors @react-email/componentsis for UI components (Body, Button, etc.);@react-email/renderis for therender()utility -- they are separate packages
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
(You MUST use RESEND_API_KEY environment variable -- NEVER hardcode API keys)
(You MUST verify your sending domain in Resend dashboard before production -- unverified domains only send to your own email)
(You MUST use @react-email/components for email UI components and @react-email/render for HTML rendering -- these are separate packages)
(You MUST use resend.emails.send({ react: MyTemplate(props) }) as the primary sending pattern -- manual render() to HTML is only needed for non-Resend senders)
Failure to follow these rules will cause email delivery failures or security vulnerabilities.
</critical_reminders>
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?