How to Setup Resend Email in Next.js 16 (2026 Complete Beginner Guide)
Sending emails is one of the most common requirements in modern web applications.
Whether you're building:
- A contact form
- Authentication system
- SaaS application
- Newsletter platform
- E-commerce store
You'll eventually need a reliable way to send emails.
In the past, developers often relied on SMTP providers and complicated email configurations. Today, services like Resend make email delivery significantly easier with a modern API-first approach.
In this guide, you'll learn how to integrate Resend with Next.js 16 using the App Router, create a contact form, send transactional emails, build reusable React Email templates, verify your domain, and deploy everything to production.
By the end of this tutorial you'll know how to:
✅ Create a Resend account
✅ Generate API keys
✅ Send emails using API Routes
✅ Send emails using Server Actions
✅ Create React Email templates
✅ Verify a custom domain
✅ Deploy to Vercel
What We'll Build
Here's the flow we'll create:
User submits form
↓
Server Action / API Route
↓
Resend API
↓
User Inbox

When a visitor submits their email address, Next.js will securely send a request to Resend, which then delivers the email to the recipient.
What is Resend?
Resend is a modern transactional email platform built specifically for developers.
Unlike traditional SMTP providers, Resend offers a simple API that allows you to send emails with minimal configuration.
Some of its key features include:
- Simple API integration
- React Email support
- Fast email delivery
- Email analytics
- Domain verification
- Excellent developer experience
- Great documentation
Common use cases include:
- Contact forms
- Welcome emails
- Password reset emails
- OTP verification emails
- SaaS notifications
- E-commerce receipts
Why Use Resend Instead of SMTP?
Traditional SMTP setups can become frustrating.
You often need to configure:
- SMTP servers
- Ports
- Authentication
- SSL/TLS settings
- Email clients
Resend eliminates most of this complexity.
Instead of configuring SMTP manually, you simply send a request like this:
await resend.emails.send({
from: "Acme <onboarding@resend.dev>",
to: "user@example.com",
subject: "Hello World",
html: "<p>Hello from Resend</p>",
});
Resend vs SMTP
| Feature | Resend | Traditional SMTP |
|---|---|---|
| Easy Setup | ✅ | ❌ |
| API-Based | ✅ | ❌ |
| React Email Support | ✅ | ❌ |
| Analytics | ✅ | Limited |
| Developer Experience | Excellent | Average |
| Modern Documentation | ✅ | Varies |
Prerequisites
Before getting started, make sure you have:
- Node.js installed
- Basic React knowledge
- Basic Next.js knowledge
- VS Code or another editor
Recommended:
- Custom domain
- Vercel account
Create a Next.js 16 Project
Create a new Next.js application:
npx create-next-app@latest resend-email-guide
For this tutorial, choose:
- TypeScript
- Tailwind CSS
- React Compiler
- src directory
Move into the project:
cd resend-email-guide
Start the development server:
npm run dev
Why These Options?
- TypeScript improves code quality and catches errors early.
- Tailwind CSS speeds up UI development.
- App Router is the recommended routing system in Next.js 16.
- React Compiler automatically memoizes components and hooks to eliminate unnecessary re-renders
Install Resend
Install the official Resend SDK:
npm install resend
This package allows your application to communicate with the Resend API.
Create a Resend Account
Visit:
https://resend.com
Then:
- Create an account
- Verify your email address
- Open the dashboard
Generate a Resend API Key
Inside the Resend dashboard:
- Open API Keys
- Click Create API Key
- Copy the generated key
Create a .env.local file:
RESEND_API_KEY=your_api_key_here
Never expose your API key in client-side code. API keys should only be used on the server.
Create a Reusable Resend Client
Instead of creating a new Resend instance everywhere, create a reusable client.
Create:
src/lib/resend.ts
import { Resend } from "resend";
export const resend = new Resend(
process.env.RESEND_API_KEY
);
Now you can import this client throughout your application.
Create Your First Email API Route
Create:
src/app/api/send/route.ts
Add the following code:
import { isValidEmail } from "@/lib/helpers";
import { resend } from "@/lib/resend";
export async function POST(request: Request) {
const { email } = await request.json();
if (!email) {
return Response.json(
{ error: "Email is required" },
{ status: 400 }
);
}
if (!isValidEmail(email)) {
return Response.json(
{ error: "Please enter a valid email" },
{ status: 400 }
);
}
try {
const data = await resend.emails.send({
from: "onboarding@resend.dev",
to: email,
subject: "Hello from Next.js 16",
html: "<p>Email sent successfully!</p>",
});
return Response.json(data);
} catch (error) {
return Response.json({ error });
}
}
Understanding the Code
Creating the Email Request
await resend.emails.send(...)
This sends an email through the Resend API.
Returning Responses
Response.json(...)
Returns a JSON response back to the frontend.
Validation
Before sending emails, we validate user input to prevent unnecessary API calls.
Create an Email Validation Helper
Create:
src/lib/helpers.ts
export const isValidEmail = (
email: string
) =>
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(
email
);
Why Validate Emails?
Validation helps:
- Improve user experience
- Reduce API usage
- Prevent invalid submissions
- Avoid unnecessary errors
Why Emails Should Be Sent Server-Side
Many beginners try sending emails directly from the frontend.
This is dangerous because:
- API keys become public
- Attackers can abuse your account
- Security risks increase
Always send emails using:
- Route Handlers
- Server Actions
- Backend APIs
Never expose API keys in client-side code.
Build a Contact Form
Create:
src/app/page.tsx
"use client";
import { useActionState } from "react";
import { isValidEmail } from "@/lib/helpers";
async function handleSubmit(
_: unknown,
formData: FormData
) {
const email = formData.get("email") as string;
if (!email) {
return {
message: "Email is required",
success: false,
};
}
if (!isValidEmail(email)) {
return {
message: "Please enter a valid email",
success: false,
email,
};
}
const response = await fetch("/api/send", {
method: "POST",
body: JSON.stringify({ email }),
headers: {
"Content-Type": "application/json",
},
});
if (response.ok) {
return {
message: "Email sent!",
success: true,
};
}
return {
message: "Something went wrong",
success: false,
email,
};
}
export default function HomePage() {
const [state, action, isPending] = useActionState(handleSubmit, { message: '', success: false, email: '' });
return (
<main className="min-h-screen flex flex-col items-center justify-center bg-gray-100 p-4">
<h1 className="text-2xl font-bold mb-4">Subscribe to our Newsletter</h1>
<form action={action}>
<input defaultValue={state.email} type="email" name="email" placeholder="Enter your email" className="mb-4 p-2 border rounded w-full" required />
<button type="submit" className="px-4 py-2 bg-blue-500 text-white rounded w-full cursor-pointer" disabled={isPending}>
{isPending ? "Sending..." : "Subscribe"}
</button>
</form>
{state.message &&
<p className={`mt-4 ${state.success ? 'text-green-500' : 'text-red-500'}`}>{state.message}</p>
}
</main>
);
}
Understanding useActionState
useActionState() helps manage form state automatically.
It provides:
- Current state
- Form action
- Loading state
Without it, you'd need multiple state variables and manual loading logic.
Test the Contact Form
Run the application:
npm run dev
Submit an email address.
Expected flow:
- User enters email
- Email is validated
- API Route executes
- Resend sends email
- User sees success message
- Email arrives in inbox
Using Server Actions Instead of API Routes
Next.js 16 encourages using Server Actions for form submissions.
Server Actions reduce boilerplate and keep logic closer to components.
API Routes vs Server Actions
| API Routes | Server Actions |
|---|---|
| Separate endpoint | Built into components |
| More boilerplate | Less boilerplate |
| Traditional approach | Modern Next.js |
| Great for APIs | Great for forms |
Create a Server Action
Create:
src/actions/send-email.ts
"use server";
import { resend } from "@/lib/resend";
import { isValidEmail } from "@/lib/helpers";
export async function sendEmail(
_: unknown,
formData: FormData
) {
const email = formData.get("email") as string;
if (!email) {
return {
message: "Email is required",
success: false,
};
}
if (!isValidEmail(email)) {
return {
message: "Please enter a valid email",
success: false,
email,
};
}
try {
await resend.emails.send({
from: "onboarding@resend.dev",
to: email,
subject: "Hello from Next.js 16",
html: "<p>Email sent successfully!</p>",
});
return {
message: "Email sent!",
success: true,
};
} catch {
return {
message: "Something went wrong",
success: false,
email,
};
}
}
Now update /src/app/page.tsx
const [state, action, isPending] = useActionState(handleSubmit, { message: '', success: false, email: '' });
to
const [state, action, isPending] = useActionState(sendEmail, { message: '', success: false, email: '' });
Now your form can call the Server Action directly without using a separate API route.
Send Beautiful Emails with React Email
While plain HTML works, React Email makes creating templates much easier.
Install the packages:
npm install react-email @react-email/components
Benefits:
- Reusable templates
- Type safety
- Responsive layouts
- Better maintainability
Create Your First Email Template
Create:
src/components/emails/welcome.tsx
import {
Html,
Body,
Container,
Heading,
Text,
Button,
} from "@react-email/components";
interface WelcomeEmailProps {
username: string;
}
export default function WelcomeEmail({
username,
}: WelcomeEmailProps) {
return (
<Html>
<Body>
<Container>
<Heading>
Welcome!
</Heading>
<Text>
Hello {username}, thanks for joining our
platform.
</Text>
<Button href="https://example.com">
Get Started
</Button>
</Container>
</Body>
</Html>
);
}
Send Dynamic Emails
Instead of hardcoding HTML:
html: "<p>Hello</p>";
Use React Email templates:
import WelcomeEmail from "@/components/emails/welcome";
await resend.emails.send({
from: "onboarding@resend.dev",
to: "user@example.com",
subject: "Welcome!",
react: WelcomeEmail({
username: "Muhammad",
}),
});
This makes your emails reusable and easier to maintain.
Verify Your Domain (Very Important)
For production applications, domain verification is essential.
Instead of:
onboarding@resend.dev
You'll eventually send emails from:
hello@yourdomain.com
Why Domain Verification Matters
Verified domains provide:
- Better deliverability
- Better branding
- Higher inbox placement
- Reduced spam risk
Add a Domain in Resend
Inside the Resend dashboard:
- Open Domains
- Click Add Domain
- Enter your domain
- Copy the DNS records
Configure DNS Records
Resend typically provides:
- SPF
- DKIM
- DMARC
These records help email providers trust your emails.
SPF
Defines which servers can send emails for your domain.
Example:
v=spf1 include:_spf.resend.com ~all
DKIM
Adds a cryptographic signature proving emails are legitimate.
DMARC
Defines how providers should handle suspicious emails.
Example:
v=DMARC1; p=none;
Testing Emails Locally
When testing locally:
- Use test email addresses
- Monitor API limits
- Verify responses
- Check inbox and spam folders
Free plans may have sending restrictions.
Common Errors and Fixes
Invalid API Key
Check:
RESEND_API_KEY=
Make sure the value is correct.
Restart the development server after changes.
Domain Not Verified
Symptoms:
- Emails fail
- Emails land in spam
- Delivery issues
Solution:
- Verify DNS records
- Wait for propagation
- Re-check configuration
Rate Limit Errors
Free plans have sending limits.
Avoid:
- Infinite loops
- Automated testing spam
- Excessive test emails
Proper Error Handling
Always wrap email requests in try/catch.
try {
await resend.emails.send();
} catch (error) {
console.error(error);
}
Good error handling makes debugging much easier.
Email Deliverability Best Practices
To avoid spam folders:
- Use verified domains
- Avoid ALL CAPS subject lines
- Keep HTML clean
- Use proper sender names
- Include text alternatives
- Avoid excessive links
Deploy to Vercel
Build your application:
npm run build
Push your code to GitHub and import the repository into Vercel.
Add Environment Variables in Vercel
Inside your Vercel dashboard:
- Open Project Settings
- Navigate to Environment Variables
- Add:
RESEND_API_KEY
Redeploy your project after adding environment variables.
Real-World Use Cases
| Use Case | Example |
|---|---|
| Contact Forms | Portfolio Websites |
| OTP Emails | Authentication Systems |
| Welcome Emails | SaaS Products |
| Password Reset | User Accounts |
| Order Receipts | E-commerce Stores |
| Notifications | Dashboards |
| Newsletters | Content Platforms |
Common Beginner Mistakes
Sending Emails From the Client
Never expose API keys publicly.
Always use server-side code.
Hardcoding API Keys
Use environment variables instead.
Skipping Validation
Always validate user input before sending emails.
Forgetting Domain Verification
This can significantly hurt email deliverability.
Frequently Asked Questions
Is Resend Free?
Yes. Resend offers a free tier suitable for development and small projects.
Can I Use Resend with Next.js Server Actions?
Absolutely. Server Actions are one of the best ways to integrate Resend with Next.js 16.
Do I Need a Custom Domain?
Not for testing. However, production applications should verify a custom domain.
Can I Send HTML Emails?
Yes. You can send raw HTML or use React Email templates.
Does Resend Work with Vercel?
Yes. Resend integrates perfectly with Vercel deployments.
What's Next?
After learning the basics, explore:
- Scheduled emails
- Email queues
- Background jobs
- Batch email sending
- Attachments
- Analytics
- Webhooks
Conclusion
Resend is one of the easiest ways to send transactional emails in Next.js 16.
Compared to traditional SMTP providers, it offers a significantly better developer experience, simpler setup, and excellent React Email integration.
In this guide, you learned how to:
- Setup Resend
- Generate API keys
- Send emails using API Routes
- Send emails using Server Actions
- Create React Email templates
- Verify domains
- Deploy to Vercel
From here, you can build:
- Authentication systems
- SaaS products
- Newsletter platforms
- E-commerce workflows
Happy coding 🚀
Helpful Resources
Continue Learning
- How to Integrate Stripe Checkout with Next.js 16 (2026 Edition)
- How to Integrate Stripe Payment Element with Next.js 16 (2026 Edition)
- Stripe Checkout vs Payment Element in 2026: Which One Should You Choose?
Source Code: https://github.com/Muhammad-Ali-sma/Nextjs16_Resend_Email_Setup