← スキル一覧に戻る

email-templates
by tejovanthn
⭐ 0🍴 0📅 2026年1月23日
SKILL.md
name: email-templates description: Transactional email design using React Email and integration with email providers like Resend or AWS SES
Email Templates Skill
Transactional email design using React Email and integration with email providers like Resend or AWS SES.
Core Principles
- Responsive Design: Emails work on all devices
- Accessibility: Proper semantic HTML and alt text
- Plain Text Fallback: Always include plain text version
- Deliverability: Follow best practices to avoid spam
- Testing: Preview emails before sending
Installation
# React Email
npm install react-email @react-email/components
# Email provider (choose one)
npm install resend # Recommended
npm install @aws-sdk/client-ses
React Email Setup
1. Create Email Templates Directory
emails/
├── welcome.tsx
├── reset-password.tsx
├── verify-email.tsx
├── receipt.tsx
└── components/
├── layout.tsx
└── button.tsx
2. Base Layout Component
// emails/components/layout.tsx
import {
Html,
Head,
Preview,
Body,
Container,
Section,
Text,
} from "@react-email/components"
interface LayoutProps {
preview: string
children: React.ReactNode
}
export function EmailLayout({ preview, children }: LayoutProps) {
return (
<Html>
<Head />
<Preview>{preview}</Preview>
<Body style={main}>
<Container style={container}>
{children}
<Section style={footer}>
<Text style={footerText}>
© 2026 Your Company. All rights reserved.
</Text>
</Section>
</Container>
</Body>
</Html>
)
}
const main = {
backgroundColor: "#f6f9fc",
fontFamily: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif',
}
const container = {
backgroundColor: "#ffffff",
margin: "0 auto",
padding: "20px 0 48px",
marginBottom: "64px",
}
const footer = {
color: "#8898aa",
fontSize: "12px",
lineHeight: "16px",
marginTop: "32px",
}
const footerText = {
margin: "0",
textAlign: "center" as const,
}
3. Reusable Button Component
// emails/components/button.tsx
import { Button as ReactEmailButton } from "@react-email/components"
interface ButtonProps {
href: string
children: React.ReactNode
}
export function Button({ href, children }: ButtonProps) {
return (
<ReactEmailButton href={href} style={button}>
{children}
</ReactEmailButton>
)
}
const button = {
backgroundColor: "#5469d4",
borderRadius: "4px",
color: "#fff",
fontSize: "16px",
fontWeight: "bold",
textDecoration: "none",
textAlign: "center" as const,
display: "block",
padding: "12px 24px",
}
Email Templates
Welcome Email
// emails/welcome.tsx
import {
Section,
Heading,
Text,
} from "@react-email/components"
import { EmailLayout } from "./components/layout"
import { Button } from "./components/button"
interface WelcomeEmailProps {
name: string
dashboardUrl: string
}
export default function WelcomeEmail({ name, dashboardUrl }: WelcomeEmailProps) {
return (
<EmailLayout preview={`Welcome to our platform, ${name}!`}>
<Section style={content}>
<Heading style={heading}>Welcome aboard, {name}!</Heading>
<Text style={paragraph}>
We're excited to have you on board. Your account has been successfully created.
</Text>
<Text style={paragraph}>
Here's what you can do next:
</Text>
<ul style={list}>
<li>Complete your profile</li>
<li>Explore the dashboard</li>
<li>Invite your team members</li>
</ul>
<Button href={dashboardUrl}>
Go to Dashboard
</Button>
<Text style={paragraph}>
If you have any questions, feel free to reply to this email.
</Text>
</Section>
</EmailLayout>
)
}
const content = {
padding: "24px",
}
const heading = {
fontSize: "24px",
lineHeight: "32px",
fontWeight: "700",
margin: "0 0 16px",
}
const paragraph = {
fontSize: "16px",
lineHeight: "24px",
margin: "0 0 16px",
}
const list = {
fontSize: "16px",
lineHeight: "24px",
marginBottom: "16px",
}
Password Reset Email
// emails/reset-password.tsx
import {
Section,
Heading,
Text,
Hr,
} from "@react-email/components"
import { EmailLayout } from "./components/layout"
import { Button } from "./components/button"
interface ResetPasswordEmailProps {
name: string
resetUrl: string
expiresIn: string
}
export default function ResetPasswordEmail({
name,
resetUrl,
expiresIn,
}: ResetPasswordEmailProps) {
return (
<EmailLayout preview="Reset your password">
<Section style={content}>
<Heading style={heading}>Reset your password</Heading>
<Text style={paragraph}>Hi {name},</Text>
<Text style={paragraph}>
We received a request to reset your password. Click the button below to choose a new password.
</Text>
<Button href={resetUrl}>
Reset Password
</Button>
<Text style={paragraph}>
This link will expire in {expiresIn}.
</Text>
<Hr style={hr} />
<Text style={small}>
If you didn't request a password reset, you can safely ignore this email.
</Text>
</Section>
</EmailLayout>
)
}
const content = {
padding: "24px",
}
const heading = {
fontSize: "24px",
lineHeight: "32px",
fontWeight: "700",
margin: "0 0 16px",
}
const paragraph = {
fontSize: "16px",
lineHeight: "24px",
margin: "0 0 16px",
}
const hr = {
borderColor: "#e6ebf1",
margin: "20px 0",
}
const small = {
fontSize: "14px",
lineHeight: "20px",
color: "#6b7280",
}
Receipt Email
// emails/receipt.tsx
import {
Section,
Heading,
Text,
Hr,
Row,
Column,
} from "@react-email/components"
import { EmailLayout } from "./components/layout"
interface ReceiptEmailProps {
name: string
orderId: string
date: string
items: Array<{
name: string
quantity: number
price: number
}>
total: number
}
export default function ReceiptEmail({
name,
orderId,
date,
items,
total,
}: ReceiptEmailProps) {
return (
<EmailLayout preview={`Receipt for order ${orderId}`}>
<Section style={content}>
<Heading style={heading}>Thanks for your order!</Heading>
<Text style={paragraph}>Hi {name},</Text>
<Text style={paragraph}>
Your order has been confirmed. Here's a summary:
</Text>
<Section style={orderInfo}>
<Text style={label}>Order ID: <strong>{orderId}</strong></Text>
<Text style={label}>Date: {date}</Text>
</Section>
<Hr style={hr} />
{items.map((item, index) => (
<Row key={index} style={itemRow}>
<Column>
<Text style={itemName}>{item.name}</Text>
<Text style={itemQuantity}>Qty: {item.quantity}</Text>
</Column>
<Column style={itemPriceColumn}>
<Text style={itemPrice}>${item.price.toFixed(2)}</Text>
</Column>
</Row>
))}
<Hr style={hr} />
<Row style={totalRow}>
<Column>
<Text style={totalLabel}>Total</Text>
</Column>
<Column style={totalPriceColumn}>
<Text style={totalPrice}>${total.toFixed(2)}</Text>
</Column>
</Row>
</Section>
</EmailLayout>
)
}
const content = { padding: "24px" }
const heading = { fontSize: "24px", fontWeight: "700", margin: "0 0 16px" }
const paragraph = { fontSize: "16px", margin: "0 0 16px" }
const orderInfo = { backgroundColor: "#f6f9fc", padding: "16px", borderRadius: "4px", marginBottom: "16px" }
const label = { fontSize: "14px", margin: "4px 0" }
const hr = { borderColor: "#e6ebf1", margin: "20px 0" }
const itemRow = { marginBottom: "12px" }
const itemName = { fontSize: "16px", margin: "0" }
const itemQuantity = { fontSize: "14px", color: "#6b7280", margin: "4px 0 0" }
const itemPriceColumn = { textAlign: "right" as const }
const itemPrice = { fontSize: "16px", margin: "0" }
const totalRow = { marginTop: "8px" }
const totalLabel = { fontSize: "18px", fontWeight: "700", margin: "0" }
const totalPriceColumn = { textAlign: "right" as const }
const totalPrice = { fontSize: "18px", fontWeight: "700", margin: "0" }
Sending Emails
Using Resend (Recommended)
// lib/email.server.ts
import { Resend } from "resend"
import { render } from "@react-email/render"
import WelcomeEmail from "~/emails/welcome"
const resend = new Resend(process.env.RESEND_API_KEY)
export async function sendWelcomeEmail(to: string, name: string, dashboardUrl: string) {
const html = render(<WelcomeEmail name={name} dashboardUrl={dashboardUrl} />)
await resend.emails.send({
from: "noreply@yourapp.com",
to,
subject: "Welcome to Your App!",
html,
})
}
// Alternative: Using Resend with React component directly
export async function sendWelcomeEmailDirect(to: string, name: string, dashboardUrl: string) {
await resend.emails.send({
from: "noreply@yourapp.com",
to,
subject: "Welcome to Your App!",
react: <WelcomeEmail name={name} dashboardUrl={dashboardUrl} />,
})
}
Using AWS SES
// lib/email.server.ts
import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses"
import { render } from "@react-email/render"
import WelcomeEmail from "~/emails/welcome"
const ses = new SESClient({ region: "us-east-1" })
export async function sendWelcomeEmail(to: string, name: string, dashboardUrl: string) {
const html = render(<WelcomeEmail name={name} dashboardUrl={dashboardUrl} />)
const text = render(<WelcomeEmail name={name} dashboardUrl={dashboardUrl} />, {
plainText: true,
})
const command = new SendEmailCommand({
Source: "noreply@yourapp.com",
Destination: { ToAddresses: [to] },
Message: {
Subject: { Data: "Welcome to Your App!" },
Body: {
Html: { Data: html },
Text: { Data: text },
},
},
})
await ses.send(command)
}
SST Integration
// sst.config.ts
import { Config } from "sst/constructs"
export default {
stacks(app) {
app.stack(function Email({ stack }) {
// Option 1: Resend API key
const RESEND_API_KEY = new Config.Secret(stack, "RESEND_API_KEY")
// Option 2: SES (no additional config needed)
// Lambda functions automatically get SES permissions
new RemixSite(stack, "site", {
bind: [RESEND_API_KEY],
})
})
},
}
Email Best Practices
Deliverability
// 1. Verify sender domain
// Add SPF, DKIM, DMARC records to your DNS
// 2. Use proper from address
from: "Your Name <noreply@yourapp.com>"
// 3. Include unsubscribe link
<Link href={unsubscribeUrl} style={unsubscribeLink}>
Unsubscribe
</Link>
// 4. Authenticate email domain
// With Resend: verify domain in dashboard
// With SES: verify domain and configure DKIM
Content Guidelines
// DO: Use plain, professional language
subject: "Your order #12345 has shipped"
// DON'T: Use spammy language
subject: "🔥 AMAZING DEAL!!! BUY NOW!!!"
// DO: Include clear CTAs
<Button href={url}>View Order</Button>
// DON'T: Use too many links
// Limit to 1-3 primary CTAs
// DO: Provide context
"You're receiving this because you signed up for updates on [date]"
// DON'T: Send without context
// Always explain why they're receiving the email
Accessibility
import { Img } from "@react-email/components"
// Always include alt text
<Img
src="https://yourapp.com/logo.png"
alt="Your App Logo"
width="150"
height="50"
/>
// Use semantic HTML
<Heading>Main Title</Heading>
<Text>Paragraph content</Text>
// Ensure good color contrast
const linkStyle = {
color: "#0066cc", // Good contrast with white background
textDecoration: "underline",
}
// Use readable font sizes
const text = {
fontSize: "16px", // Minimum 14px
lineHeight: "24px", // 1.5x font size
}
Testing Emails
Development Preview
# Start React Email dev server
npm run email:dev
# package.json
{
"scripts": {
"email:dev": "email dev"
}
}
# Visit http://localhost:3000 to preview emails
Send Test Emails
// scripts/test-email.ts
import { sendWelcomeEmail } from "./lib/email.server"
await sendWelcomeEmail(
"test@example.com",
"Test User",
"https://app.yourapp.com/dashboard"
)
console.log("Test email sent!")
Email Testing Tools
// Use Mailtrap for testing in development
const resend = new Resend(
process.env.NODE_ENV === "production"
? process.env.RESEND_API_KEY
: process.env.MAILTRAP_API_KEY
)
// Use Litmus or Email on Acid for rendering tests across clients
Advanced Patterns
Email with Attachments
await resend.emails.send({
from: "noreply@yourapp.com",
to: email,
subject: "Your Invoice",
react: <InvoiceEmail />,
attachments: [
{
filename: "invoice.pdf",
content: pdfBuffer,
},
],
})
Scheduled Emails
// Using EventBridge with SST
import { Cron } from "sst/constructs"
new Cron(stack, "DailySummary", {
schedule: "cron(0 9 * * ? *)", // 9 AM daily
job: "functions/send-daily-summary.handler",
})
// functions/send-daily-summary.ts
export async function handler() {
const users = await getActiveUsers()
for (const user of users) {
await sendDailySummaryEmail(user.email, user.name, user.stats)
}
}
Email Analytics
// Track opens and clicks with Resend
await resend.emails.send({
from: "noreply@yourapp.com",
to: email,
subject: "Your Report",
react: <ReportEmail />,
tags: [
{ name: "category", value: "report" },
{ name: "user_id", value: userId },
],
})
// Query analytics
const analytics = await resend.emails.get(emailId)
console.log(analytics.opens, analytics.clicks)
Common Email Types
// Welcome series
export const welcomeEmails = [
{ delay: 0, template: "welcome", subject: "Welcome!" },
{ delay: 1, template: "getting-started", subject: "Getting Started Guide" },
{ delay: 3, template: "tips", subject: "Pro Tips for Success" },
]
// Transactional
- Welcome email
- Email verification
- Password reset
- Receipt/invoice
- Shipping notification
- Account changes
// Engagement
- Weekly summary
- Achievement unlocked
- Abandoned cart
- Re-engagement
- Product updates
Resources
- React Email Documentation
- Resend Documentation
- AWS SES Best Practices
- Email on Acid
- Can I email - Email client support tables
スコア
総合スコア
40/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です