Back to posts

Tutorial

Build contact form with Nextjs and Sendgrid

by Hafizul Hassan

July 4th 2021

Image of Contact Form

In this tutorial, we will build the contact form using Nextjs and integration with Sendgrid Email Api. We will go through each step by details.

Requirement

Before begin, these are the requirements that you need to have:

  • Nodejs - Make sure Nodejs is already installed in your computer
  • Nextjs
  • TailwindCSS
  • Sendgrid account

But don't worry we will go step-by-step with details.

Setup Nextjs

  1. Go to your project directory. Using your terminal, create a contact-form project by using this command.
npx create-next-app contact-form
# or
yarn create next-app contact-form

  1. Once the project is created, go inside your contact-form directory by using cd contact-form and run this command:
npm run dev
# or
yarn dev
  1. Open your browser and go to localhost:3000. You will see the default homepage of Nextjs.

Image of Nextjs Default Homepage

Setup TailwindCSS

  1. Now, let's setup the TailwindCSS to style our contact form. In your contact-form directory, install TailwindCSS using this command:
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
# or
yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest
  1. Next, we will generate the configuration files for TailwindCSS. This will generate two files in our contact-form directory which are tailwind.config.js and postcss.config.js
npx tailwindcss init -p
  1. Open your code editor and open the tailwind.config.js. For mine, I used VSCode.

Image of Vscode

  1. Replace this code
purge: [],

with this

mode:'jit',
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
  1. Next, we will include the TailwindCSS in our CSS. Open your globals.css in the styles directory and replace and the code with this.
@tailwind base;
@tailwind components;
@tailwind utilities;

Image of Vscode

  1. Then, remove the Home.module.css. This will break our application and we will fix it later.

Image of remove-home-module

  1. Open the index.js inside the pages directory. Remove these line:
import Image from "next/image";
import styles from '../styles/Home.module.css'
  1. Replace the entire div element with this:
<div>
  <Head>
    <title>Contact Form App</title>
    <meta name="description" content="contact form app" />
    <link rel="icon" href="/favicon.ico" />
    </Head>

    <main>Contact Form App</main>
</div>
  1. Now, your index.js file will look like this.

Image of index-js

Setup Sendgrid account

  1. Now, let's setup sendgrid account to use their api to send mail to our email. Go to SendGrid official website.

2.Click on the button Start for free and sign up using your email.

Image of sendgrid

  1. Sign into your account. Click API Keys under the Settings tab. Click on Create API key.

  2. Enter your API key name and select Full Access.

Image of apikey

  1. Once your API key created, copy the key.

  2. Go into contact-form directory and create a file called .env.local. Paste your API key with a variable SENDGRID_API_KEY. Save your file.

SENDGRID_API_KEY=pasteyourapikeyhere

Contact Form

  1. Let's create our contact form. Open your index.js file. Replace your main element with this code:
<main className="max-w-screen-md mx-auto">
  <div className="space-y-10 mx-5 mt-20">
    <h2 className="text-6xl lg:text-8xl font-medium tracking-tighter">
      contact
    </h2>
    <form className="w-full flex flex-col lg:max-w-4xl space-y-10">
      <input
        placeholder="Your name"
        className="bg-blue-50 p-5 focus:outline-none border-l-4 border-blue-500"
        required
      />
      <input
        placeholder="Your Email"
        className="bg-blue-50 p-5 focus:outline-none border-l-4 border-blue-500"
        required
      />
      <textarea
        placeholder="Message"
        className="bg-blue-50 p-5 focus:outline-none border-l-4 border-blue-500 min-h-[300px] lg:min-w-full"
        required
      />
      <button className="bg-blue-700 w-min px-10 py-4 rounded-md text-white hover:bg-blue-800 focus:outline-none">
        Send
      </button>
    </form>
  </div>
</main>
  1. As you can see from the code above, we have created our form with a button using TailwindCSS styling. Our form is not function yet at this point.

  2. Now let's make our contact form works. Let's import useState into our code.

import { useState } from "react";
  1. Inside our Home component enter the code below.
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
  1. Inside our input and textarea element. We will include two atributes: value and onChange
  • value - the value entered by user will be set into the state
  • onChange - when user typing in input, it will update the state
  1. For each input and textarea,
# For name input
<input
  placeholder="Your name"
  className="bg-blue-50 p-5 focus:outline-none border-l-4 border-blue-500"
  value={name}
  onChange={(e) => setName(e.target.value)}
  required
/>

# For email input
<input
  placeholder="Your Email"
  className="bg-blue-50 p-5 focus:outline-none border-l-4 border-blue-500"
  value={email}
  onChange={(e) => setEmail(e.target.value)}
  required
/>

# For textarea - Message input
<textarea
  placeholder="Message"
  className="bg-blue-50 p-5 focus:outline-none border-l-4 border-blue-500 min-h-[300px] lg:min-w-full"
  value={message}
  onChange={(e) => setMessage(e.target.value)}
  required
/>
  1. Now, let's add onSubmit into our form so that the user can submit the form.
  • onSubmit - User can submit using Enter keyboard and also by clicking the send button
  • e.preventDefault() - This to prevent the page from refresh when user submit the form
  • submitForm() - Function to handle the submit
<form
  className="flex flex-col lg:max-w-4xl space-y-10"
  onSubmit={(e) => {
    e.preventDefault();
    submitForm();
  }}
>
  1. So far your code will look like this.

Image of form

  1. We will create submitForm() function.
async function submitForm() {
    const form = { name, email, message };
    const json = JSON.stringify(form);

    await fetch("/api/sendMail", {
      method: "post",
      body: json,
    });

    setName("");
    setEmail("");
    setMessage("");
  }
const form = { name, email, message };
  • Set the value of input into form variable
const json = JSON.stringify(form);
  • Convert the form data into JSON format
await fetch("/api/sendMail", {
  method: "post",
  body: json,
  });
  • Send our data into sendMail api using POST method and body with our data
setName("");
setEmail("");
setMessage("");
  • Clear input field
  1. Your code will look like this now.

Image of completed-form

Handling API Route for sendMail

  1. Create a file sendMail.js inside pages/api directory.

  2. Open the sendMail.js and import sendgrid package. Before that, install the sendgrid package.

npm install @sendgrid/mail
# or
yarn add @sendgrid/mail
import mail from "@sendgrid/mail";
  1. Then, we need to use the SENDGRID_API_KEY which we have created before. We need to loaded the api key from the process.env.
mail.setApiKey(process.env.SENDGRID_API_KEY);
  1. Create an async function to handle the route.
export default async function handler(req, res) {}
  1. Inside the function, we need to parse the data that comes from the request.
  const body = JSON.parse(req.body);
  1. Next, we need to set a few configurations required for the sendgrid to the the contact data to our email. Replace youremailaddress with your real email address and yourname with your name.
const data = {
    personalizations: [
      {
        to: [
          {
            email: "youremailadress",
            name: "yourname",
          },
        ],
      },
    ],
    from: {
      email: "youremailadress",
      name: "yourname",
    },

    subject: `You have a new email from ${body.email}`,
    content: [
      {
        type: "text/html",
        value: `<p>Hello yourname!</p><p>You have a new message from a client. Here's the detail:</p><p>Name: ${body.name}</p><p>Email: ${body.email}</p><p>Message: ${body.message}</p>`,
      },
    ],
  };
  1. Once configured, we need to send the data to the sendgrid. We will use await since we are using async function.
await mail
    .send(data)
    .then(() => {
      console.log("Email sent");
    })
    .catch((error) => {
      console.error(error);
    });

  res.status(200).json({ status: "Ok" });

You can read more about this from the SendGrid API.

  1. Now your code will look like this overall.

Image of send mail

Final

Now we have completed our contact-form. Let's test our contact form now. Make sure that you check your email.

I think that's all for this tutorial. If you have any problem with the code, please contact me.

Bonus

If you want to add toast notification once a user submitted the form, you can read this tutorial.

© Hafizul Hassan. 2021