Email System

Transactional emails with Resend for authentication and notifications.

Email Types

  • • Magic link authentication
  • • Welcome emails
  • • Subscription confirmations
  • • Payment notifications
  • • Waitlist updates

Features

  • • Branded templates
  • • Dynamic content
  • • Delivery tracking
  • • Domain verification

Setup

  1. 1. Create account at resend.com
  2. 2. Create an API key
  3. 3. Verify your domain (recommended)
.env
AUTH_RESEND_KEY="re_..."
EMAIL_FROM="noreply@yourdomain.com"

Verify your domain to improve deliverability and remove the "via resend.dev" label.

Email Service

src/server/lib/emailService.ts
1import { Resend } from "resend";
2
3const resend = new Resend(process.env.AUTH_RESEND_KEY);
4
5export async function sendEmail({ to, subject, html }) {
6 const { data, error } = await resend.emails.send({
7 from: `Your SaaS <${process.env.EMAIL_FROM}>`,
8 to: [to],
9 subject,
10 html,
11 });
12
13 if (error) throw new Error(error.message);
14 return data;
15}
16
17// Send welcome email
18export async function sendWelcomeEmail(email: string, name?: string) {
19 return sendEmail({
20 to: email,
21 subject: "Welcome!",
22 html: generateWelcomeEmailHTML(name),
23 });
24}

Auth Integration

Magic link emails are handled by NextAuth.js with Resend:

1// auth.config.ts
2import Resend from "next-auth/providers/resend";
3
4export default {
5 providers: [
6 Resend({
7 apiKey: process.env.AUTH_RESEND_KEY,
8 from: process.env.EMAIL_FROM,
9 }),
10 ],
11};

Webhook Triggers

Send emails on Stripe events:

1switch (event.type) {
2 case "customer.subscription.created":
3 const subscription = event.data.object;
4 const customer = await stripe.customers.retrieve(subscription.customer);
5
6 if (customer.email) {
7 await sendSubscriptionConfirmation(customer.email, "Pro", "$20/month");
8 }
9 break;
10}

Best Practices

Deliverability

  • • Verify your domain
  • • Use clear subject lines
  • • Include unsubscribe links
  • • Monitor bounce rates

UX

  • • Keep emails mobile-friendly
  • • Consistent branding
  • • Clear calls-to-action
  • • Handle errors gracefully

Troubleshooting

Emails not sending

Check AUTH_RESEND_KEY and EMAIL_FROM. Verify domain in Resend dashboard.

Going to spam

Set up domain verification and DKIM records. Avoid spammy content.

Magic links not working

Ensure NEXTAUTH_URL matches your domain and EMAIL_FROM is verified.

Next: Theming

Color system and customization

Continue →