Building a Contact Form with Next.js and Resend
Saturday, February 8, 2025
A contact form is a fundamental feature of most websites, enabling seamless communication between users and site administrators. In this tutorial, we'll walk through how to create a functional contact form using Next.js and Resend, a powerful tool for sending transactional emails. By the end, you'll have a fully working contact form integrated with Resend to handle email submissions efficiently.
Setting Up the Project
Initialize a Next.js Project
If you don’t already have a Next.js project, create one:
npx create-next-app@latest contact-form
cd contact-form
Install Dependencies
Install the necessary packages:
npm install @resend/react react-hook-form
Project Structure
Organize your project as follows:
/pages
/api
send-email.js # API route for sending emails
index.js # Main contact form page
Creating the Contact Form UI
Create a simple contact form in pages/index.js:
import { useForm } from 'react-hook-form';
export default function ContactForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = async (data) => {
const response = await fetch('/api/send-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await response.json();
alert(result.message);
};
return (
<div className="max-w-md mx-auto mt-10">
<h1 className="text-2xl font-bold mb-4">Contact Us</h1>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
<div>
<label className="block text-sm font-medium">Name</label>
<input
{...register('name', { required: true })}
className="w-full border p-2 rounded"
placeholder="Your Name"
/>
{errors.name && <p className="text-red-500 text-sm">Name is required.</p>}
</div>
<div>
<label className="block text-sm font-medium">Email</label>
<input
{...register('email', { required: true, pattern: /^[^@\s]+@[^@\s]+\.[^@\s]+$/ })}
className="w-full border p-2 rounded"
placeholder="Your Email"
/>
{errors.email && <p className="text-red-500 text-sm">Valid email is required.</p>}
</div>
<div>
<label className="block text-sm font-medium">Message</label>
<textarea
{...register('message', { required: true })}
className="w-full border p-2 rounded"
placeholder="Your Message"
/>
{errors.message && <p className="text-red-500 text-sm">Message is required.</p>}
</div>
<button type="submit" className="bg-blue-500 text-white px-4 py-2 rounded">Send</button>
</form>
</div>
);
}
Setting Up the Resend API
Sign Up and Get Your API Key
Visit Resend and create an account. Once signed in, generate an API key.
Configure the Resend Client
Store your API key in an environment variable. Create a .env.local file:
RESEND_API_KEY=your_api_key_here
Use the Resend client in your API route:
npm install resend
Building the API Route
In pages/api/send-email.js, add the server-side logic:
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
export default async function handler(req, res) {
if (req.method === 'POST') {
const { name, email, message } = req.body;
try {
await resend.sendEmail({
to: 'your-email@example.com',
from: email,
subject: `New Contact Form Submission from ${name}`,
text: message,
});
res.status(200).json({ message: 'Email sent successfully!' });
} catch (error) {
res.status(500).json({ message: 'Failed to send email.', error: error.message });
}
} else {
res.status(405).json({ message: 'Method Not Allowed' });
}
}
Connecting the Frontend to the API
Testing the Contact Form
npm run dev
Deploying Your App
Deploy to Vercel: Push your code to GitHub and deploy on Vercel.
Set Environment Variables: Configure the RESEND_API_KEY in the Vercel dashboard.
Conclusion
You've successfully built a fully functional contact form using Next.js and Resend. This setup can be extended to include additional features like CAPTCHA for spam prevention or saving submissions to a database.