Email Integration
Learn how to send transactional emails using Resend in your application.
Setup
The boilerplate uses Resend for sending transactional emails. Follow these steps to set it up:
1. Environment Variables
Add your Resend API key to .env.local
:
RESEND_API_KEY=re_123...
2. Email Templates
Create React-based email templates in the emails
directory:
// emails/welcome.tsx
import {
Body,
Container,
Head,
Heading,
Html,
Link,
Preview,
Text,
} from "@react-email/components";
interface WelcomeEmailProps {
name: string;
loginUrl: string;
}
export default function WelcomeEmail({
name,
loginUrl,
}: WelcomeEmailProps) {
return (
<Html>
<Head />
<Preview>Welcome to Our App</Preview>
<Body style={main}>
<Container style={container}>
<Heading style={h1}>
Welcome, {name}!
</Heading>
<Text style={text}>
We're excited to have you on board. Click the button below
to get started:
</Text>
<Link
href={loginUrl}
style={button}
>
Get Started
</Link>
</Container>
</Body>
</Html>
);
}
const main = {
backgroundColor: "#ffffff",
};
const container = {
margin: "0 auto",
padding: "20px 0 48px",
};
const h1 = {
color: "#1a1a1a",
fontSize: "24px",
fontWeight: "600",
lineHeight: "40px",
margin: "0 0 20px",
};
const text = {
color: "#4a4a4a",
fontSize: "16px",
lineHeight: "24px",
margin: "0 0 40px",
};
const button = {
backgroundColor: "#000000",
borderRadius: "4px",
color: "#ffffff",
display: "inline-block",
fontSize: "16px",
padding: "12px 24px",
textDecoration: "none",
};
Sending Emails
Server-side Email Sending
Send emails from your API routes or Server Actions:
// lib/resend.ts
import { Resend } from "resend";
export const resend = new Resend(process.env.RESEND_API_KEY);
// app/api/send/route.ts
import { resend } from "@/lib/resend";
import WelcomeEmail from "@/emails/welcome";
export async function POST(request: Request) {
try {
const { name, email } = await request.json();
const data = await resend.emails.send({
from: "hello@yourdomain.com",
to: email,
subject: "Welcome to Our App!",
react: WelcomeEmail({
name,
loginUrl: `${process.env.NEXT_PUBLIC_SITE_URL}/login`,
}),
});
return Response.json(data);
} catch (error) {
return Response.json({ error }, { status: 500 });
}
}
Email Service
Create a service to handle different types of emails:
// lib/email.ts
import { resend } from "@/lib/resend";
import WelcomeEmail from "@/emails/welcome";
import PasswordResetEmail from "@/emails/password-reset";
import InvoiceEmail from "@/emails/invoice";
export const emailService = {
async sendWelcomeEmail(name: string, email: string) {
return resend.emails.send({
from: "hello@yourdomain.com",
to: email,
subject: "Welcome to Our App!",
react: WelcomeEmail({
name,
loginUrl: `${process.env.NEXT_PUBLIC_SITE_URL}/login`,
}),
});
},
async sendPasswordResetEmail(email: string, resetToken: string) {
return resend.emails.send({
from: "hello@yourdomain.com",
to: email,
subject: "Reset Your Password",
react: PasswordResetEmail({
resetUrl: `${process.env.NEXT_PUBLIC_SITE_URL}/reset-password?token=${resetToken}`,
}),
});
},
async sendInvoiceEmail(email: string, invoice: any) {
return resend.emails.send({
from: "billing@yourdomain.com",
to: email,
subject: `Invoice #${invoice.number}`,
react: InvoiceEmail({
invoice,
downloadUrl: `${process.env.NEXT_PUBLIC_SITE_URL}/invoices/${invoice.id}`,
}),
});
},
};
Testing Emails
Preview and test your email templates during development:
// app/api/preview/route.ts
import WelcomeEmail from "@/emails/welcome";
export async function GET() {
return new Response(
WelcomeEmail({
name: "John Doe",
loginUrl: "https://example.com/login",
}).toString(),
{
headers: { "Content-Type": "text/html" },
}
);
}
Visit /api/preview
to preview your email templates in the browser.
Best Practices
Email Design
- Use responsive design for better mobile experience
- Keep emails simple and focused
- Include plain text versions
- Test across different email clients
- Follow anti-spam guidelines
Error Handling
- Implement proper error handling and logging
- Set up email bounce and complaint handling
- Monitor delivery rates and engagement
- Implement retry logic for failed sends