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:

Language: bash
npx create-next-app@latest contact-form
cd contact-form

Install Dependencies

Install the necessary packages:

Language: bash
npm install @resend/react react-hook-form

Project Structure

Organize your project as follows:

Language: plain text
/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:

Language: javascript
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:

Language: plain text
RESEND_API_KEY=your_api_key_here

Use the Resend client in your API route:

Language: bash
npm install resend

Building the API Route

In pages/api/send-email.js, add the server-side logic:

Language: javascript
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

  • Ensure the onSubmit handler on the form sends data to /api/send-email.
  • Display success or error messages based on the response.

  • Testing the Contact Form

  • Run the development server:
  • Language: bash
    npm run dev
  • Open the app in your browser and test the form.
  • Check the email inbox for your recipient email address.

  • 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.