Resend + React Email: The Transactional Email Stack That Doesn't Fight You
SendGrid's free tier is 100 emails/day and the dashboard is from 2013. Mailgun's API is fine but the React SDK is an afterthought. Resend was built by developers who wanted something that worked like a modern API — here's the setup that's been running in production for 8 months. Three reasons: the React SDK is first-party, the API is clean, and the free tier is 3,000 emails/month. npm install resend @react-email/components // emails/WelcomeEmail.tsx import { Body, Button, Container, Head, Heading, Html, Preview, Section, Text } from "@react-email/components" interface WelcomeEmailProps { userName: string dashboardUrl: string } export function WelcomeEmail({ userName, dashboardUrl }: WelcomeEmailProps) { return ( Welcome to whoffagents — your AI toolkit is ready Welcome, {userName} Your AI SaaS Starter Kit is ready. Here's what to do first: • Connect your Stripe account • Configure your Claude API key • Deploy to Vercel with one click Open Dashboard ) } JSX emails mean TypeScript types, prop validation, component reuse, and hot-reload previews. No more Handlebars templates or HTML string concatenation. // app/api/send-welcome/route.ts import { Resend } from "resend" import { WelcomeEmail } from "@/emails/WelcomeEmail" const resend = new Resend(process.env.RESEND_API_KEY) export async function POST(req: Request) { const { email, name } = await req.json() const { data, error } = await resend.emails.send({ from: "Atlas ", to: email, subject: "Welcome to whoffagents", react: WelcomeEmail({ userName: name, dashboardUrl: `https://whoffagents.com/dashboard` }) }) if (error) { return Response.json({ error }, { status: 400 }) } return Response.json({ id: data?.id }) } The react prop accepts a JSX element directly. Resend renders it to HTML + plain text automatically. npx email dev Opens a local server at localhost:3000 with a live preview of all emails in your emails/ directory. Hot-reloads on save. Shows both HTML and plain text views. // app/api/resend-webhook/route.ts import { Resend } from "resend" export async function POST(req: Request) { const payload = await req.json() switch (payload.type) { case "email.delivered": await db.emailEvents.insert({ emailId: payload.data.email_id, event: "delivered", timestamp: new Date(payload.data.created_at) }) break case "email.bounced": await db.users.update({ where: { email: payload.data.to[0] }, data: { emailBounced: true } }) break case "email.complained": await db.users.update({ where: { email: payload.data.to[0] }, data: { unsubscribed: true } }) break } return Response.json({ received: true }) } // Send to multiple recipients without a loop const { data, error } = await resend.batch.send([ { from: "Atlas ", to: "[email protected]", subject: "Your weekly report", react: WeeklyReport({ userId: "u1", stats: stats1 }) }, { from: "Atlas ", to: "[email protected]", subject: "Your weekly report", react: WeeklyReport({ userId: "u2", stats: stats2 }) } ]) Batch API handles up to 100 emails per call with a single HTTP request. # Add these DNS records to your domain TXT resend._domainkey v=DKIM1; k=rsa; p= TXT @ v=spf1 include:resend.com ~all CNAME mail mail.resend.dev Resend's dashboard walks you through verification. After DNS propagates, emails land in inbox consistently — no more Gmail promotions tab. Resend SendGrid Postmark React SDK ✅ first-party ❌ ❌ Free tier 3K/month 100/day 100/month API quality Modern Legacy Good Local preview ✅ ❌ ❌ Price (50K/mo) $20 $15 $57 For Next.js projects, Resend's React-native approach eliminates an entire category of template management problems. Building a Next.js SaaS? The AI SaaS Starter Kit ships with Resend pre-wired — welcome emails, password resets, and Stripe receipt notifications all working on day one.
