Skip to content

Resend Guide

Resend is a cloud-based email service for sending transactional emails. This guide covers the basic setup, configuration, and usage within this application. Adjust any steps to fit your workflow or security needs.


1. Overview & Prerequisites

  • Resend Account: You’ll need an account at resend.dev.
  • API Key: Generated from your Resend dashboard (keep this secret).
  • Email Templates: The system uses React-based email templates in the /emails directory.

Note: This guide assumes you have a Node.js/Next.js environment with environment variables set up (e.g., .env.local).


2. Initial Setup

  1. Create or log in to your Resend account at resend.dev.
  2. Obtain your Resend API key from your Resend dashboard (e.g., RESEND_API_KEY=...).
  3. (Optional) Verify your domain if you want to send emails from your own domain (recommended for brand consistency and deliverability). Follow Resend’s domain verification docs.

3. Configuration

  1. Add credentials to your .env.local file:

    Terminal window
    RESEND_API_KEY=your_resend_api_key
    RESEND_AUDIENCE_ID=your_audience_id

    Tip: The RESEND_AUDIENCE_ID might be optional depending on your usage.

  2. Configure default email settings in config.ts (or your chosen config file):

    export const config = {
    resend: {
    fromNoReply: `CompanyName <noreply@resend.dev>`,
    fromAdmin: `Admin <admin@resend.dev>`,
    supportEmail: 'support@yourdomain.io',
    forwardRepliesTo: 'replies@yourdomain.io',
    },
    // ...other config
    };
    • Adjust the from addresses to match your verified domain, if applicable.
    • Update any other fields relevant to your application.

4. Sending Emails

A data-access function /data-access/resend.ts handles server-side email sending with validation. Below is a simplified example:

import { Resend } from 'resend';
import config from '@/config';
import { ReactNode } from 'react';
import { z } from 'zod';
import { PublicError } from '@/lib/errors';
const resend = new Resend(process.env.RESEND_API_KEY);
// Validation schema
const EmailSchema = z.object({
email: z.string().email('Invalid email address'),
});
type EmailData = z.infer<typeof EmailSchema>;
export const createContact = async (email: string) => {
const resendResponse = await resend.contacts.create({
email,
unsubscribed: false,
audienceId: process.env.RESEND_AUDIENCE_ID!,
});
if (resendResponse.error) throw resendResponse.error;
return resendResponse.data;
}
export const sendResendEmail = async ({
to,
subject,
react
}: {
to: string;
subject: string;
react: ReactNode;
}) => {
const data = {
from: config.resend.fromNoReply,
to,
subject,
react,
};
const emailData: EmailData = {
email: to as string,
}
// Validate input
const validationResult = EmailSchema.safeParse(emailData)
if (!validationResult.success) {
throw new PublicError('Invalid email address');
}
const response = await resend.emails.send(data);
if (response.error) throw response.error;
return response.data;
};

Note: This snippet uses Zod for validation and Upstash Redis for rate limiting. Adjust as needed.


5. Email Templates

Your email templates are React components located in the /emails directory. Each file exports a default React component representing the email body. For example:

/emails/welcome-email.tsx
import { Body, Container, Head, Html, Text } from '@react-email/components';
interface WelcomeEmailProps {
username: string;
}
export default function WelcomeEmail({ username }: WelcomeEmailProps) {
return (
<Html>
<Head />
<Body>
<Container>
<Text>Welcome, {username}! Thanks for joining us.</Text>
</Container>
</Body>
</Html>
);
}
  • Styling: You can use inline styles or CSS-in-JS solutions (depending on library support).
  • Metadata: Add previewText, subject suggestions, or placeholders for dynamic data.

6. Usage Examples

6.1 Sending a Welcome Email

import WelcomeEmail from '@/emails/welcome-email';
import { sendResendEmail } from '@/data/actions/sendResendEmail';
await sendResendEmail({
to: user.email,
subject: 'Welcome to Our Service!',
react: <WelcomeEmail username={user.name} />,
ip: req.ip, // or however you capture the user's IP
});

6.2 Sending a Newsletter

import NewsletterEmail from '@/emails/newsletter';
import { sendResendEmail } from '@/data/actions/sendResendEmail';
await sendResendEmail({
to: subscriber.email,
subject: 'Your Weekly Digest',
react: (
<NewsletterEmail
username={subscriber.name}
previewText="Catch up on our latest news!"
/>
),
ip: req.ip,
});

7. Error Handling & Best Practices

  1. Validation: Verify recipients’ emails with a schema (e.g., Zod).
  2. Rate Limiting: Use Upstash or another service to prevent abuse (e.g., spamming).
  3. Environment Variables:
    • Store RESEND_API_KEY securely.
    • Avoid committing sensitive keys to version control.
  4. Testing Emails:
    • Use a local or staging environment to verify templates before sending to real users.
    • Consider capturing emails in a test mailbox or using a dedicated test environment.
  5. Monitoring:
    • Monitor bounce/spam rates.
    • Ensure domain reputation if using a custom sending domain.

8. Final Checklist

  • Resend Account created and domain verified (if custom domain is used).
  • API Key set in .env.local (and any necessary environment variables).
  • Email Templates tested to confirm they render correctly.
  • Rate Limiting configured to prevent spam.
  • Error Handling for invalid email addresses or service outages.
  • Production environment variables updated (e.g., in Vercel, Docker secrets, etc.).
  • Logs & Monitoring set up to track email send status and bounce rates.

Additional Resources


Congratulations! You’ve set up Resend to send transactional emails using React-based templates. With proper configuration and error handling, you can ensure reliable email delivery for your application’s users. If you need more advanced features like analytics or domain management, consult the official Resend documentation.