# How to Integrate MongoDB Into Your Next.js App

> This tutorial uses the Next.js Pages Router instead of the App Router which was introduced in Next.js version 13. The Pages Router is still supported and recommended for production environments.

Are you building your next amazing application with Next.js? Do you wish you could integrate MongoDB into your Next.js app effortlessly? Do you need this done before your coffee has finished brewing? If you answered yes to these three questions, I have some good news for you. We have created a Next.js<>MongoDB integration that will have you up and running in minutes, and you can consider this tutorial your official guide on how to use it. 

In this tutorial, we'll take a look at how we can use the **with-mongodb** example to create a new Next.js application that follows MongoDB best practices for connectivity, connection pool monitoring, and querying. We'll also take a look at how to use MongoDB in our Next.js app with things like serverSideProps and APIs. Finally, we'll take a look at how we can easily deploy and host our application on Vercel, the official hosting platform for Next.js applications. If you already have an existing Next.js app, not to worry. Simply drop the MongoDB utility file into your existing project and you are good to go. We have a lot of exciting stuff to cover, so let's dive right in!

## Next.js and MongoDB with one click
Our app is now deployed and running in production. If you weren't following along with the tutorial and just want to quickly start your Next.js application with MongoDB, you could always use the `with-mongodb` starter found on GitHub, but I’ve got an even better one for you.

Visit Vercel and you'll be off to the races in creating and deploying the official Next.js with the MongoDB integration, and all you'll need to provide is your connection string.

## Prerequisites
For this tutorial, you'll need:

 - MongoDB Atlas (sign up for free).
 - A Vercel account (sign up for free).
 - NodeJS 18+.
 - npm and npx.

To get the most out of this tutorial, you need to be familiar with React and Next.js. I will cover unique Next.js features with enough details to still be valuable to a newcomer.

## What is Next.js?
If you're not already familiar with it, Next.js is a React-based framework for building modern web applications. The framework adds a lot of powerful features — such as server-side rendering, automatic code splitting, and incremental static regeneration — that make it easy to build, scalable, and production-ready apps.

. You can use a local MongoDB installation if you have one, but if you're just getting started, MongoDB Atlas is a great way to get up and running without having to install or manage your MongoDB instance. MongoDB Atlas has a forever free tier that you can sign up for as well as get the sample data that we'll be using for the rest of this tutorial. 

To get our MongoDB URI, in our MongoDB Atlas dashboard: 

 1. Hit the **Connect** button. 
 2. Then, click the **Connect to your application** button, and here you'll see a string that contains your **URI** that will look like this:

```
mongodb+srv://:@cluster0..mongodb.net/?retryWrites=true&w=majority
```
If you are new to MongoDB Atlas, you'll need to go to the **Database Access** section and create a username and password, as well as the **Network Access** tab to ensure your IP is allowed to connect to the database. However, if you already have a database user and network access enabled, you'll just need to replace the `` and `` fields with your information.

For the ``, we'll load the MongoDB Atlas sample datasets and use one of those databases.

, and we'll help troubleshoot.

## Querying MongoDB with Next.js
Now that we are connected to MongoDB, let's discuss how we can query our MongoDB data and bring it into our Next.js application. Next.js supports multiple ways to get data. We can create API endpoints, get data by running server-side rendered functions for a particular page, and even generate static pages by getting our data at build time. We'll look at all three examples.

## Example 1: Next.js API endpoint with MongoDB
The first example we'll look at is building and exposing an API endpoint in our Next.js application. To create a new API endpoint route, we will first need to create an `api` directory in our `pages` directory, and then every file we create in this `api` directory will be treated as an individual API endpoint.

Let's go ahead and create the `api` directory and a new file in this `directory` called `movies.tsx`. This endpoint will return a list of 20 movies from our MongoDB database. The implementation for this route is as follows:

```
import clientPromise from "../../lib/mongodb";
import { NextApiRequest, NextApiResponse } from 'next';

export default async (req: NextApiRequest, res: NextApiResponse) => {
    try {
        const client = await clientPromise;
        const db = client.db("sample_mflix");
        const movies = await db
            .collection("movies")
            .find({})
            .sort({ metacritic: -1 })
            .limit(10)
            .toArray();
        res.json(movies);
    } catch (e) {
        console.error(e);
    }
}
```

To explain what is going on here, we'll start with the import statement. We are importing our `clientPromise` method from the `lib/mongodb` file. This file contains all the instructions on how to connect to our MongoDB Atlas cluster. Additionally, within this file, we cache the instance of our connection so that subsequent requests do not have to reconnect to the cluster. They can use the existing connection. All of this is handled for you!

Next, our API route handler has the signature of `export default async (req, res)`. If you're familiar with Express.js, this should look very familiar. This is the function that gets run when the `localhost:3000/api/movies` route is called. We capture the request via `req` and return the response via the `res` object.

Our handler function implementation calls the `clientPromise` function to get the instance of our MongoDB database. Next, we run a MongoDB query using the MongoDB Node.js driver to get the top 20 movies out of our **movies** collection based on their **metacritic** rating sorted in descending order.

Finally, we call the `res.json` method and pass in our array of movies. This serves our movies in JSON format to our browser. If we navigate to `localhost:3000/api/movies`, we'll see a result that looks like this:

 to capture the `id`. So, if a user calls `http://localhost:3000/api/movies/573a1394f29313caabcdfa3e`, the movie that should be returned is Seven Samurai. **Another tip**: The `_id` property for the `sample_mflix` database in MongoDB is stored as an ObjectID, so you'll have to convert the string to an ObjectID. If you get stuck, create a thread on the MongoDB Community forums and we'll solve it together! Next, we'll take a look at how to access our MongoDB data within our Next.js pages.

## Example 2: Next.js pages with MongoDB
In the last section, we saw how we can create an API endpoint and connect to MongoDB with it. In this section, we'll get our data directly into our Next.js pages. We'll do this using the getServerSideProps() method that is available to Next.js pages.

The `getServerSideProps()` method forces a Next.js page to load with server-side rendering. What this means is that every time this page is loaded, the `getServerSideProps()` method runs on the back end, gets data, and sends it into the React component via props. The code within `getServerSideProps()` is never sent to the client. This makes it a great place to implement our MongoDB queries.

Let's see how this works in practice. Let's create a new file in the `pages` directory, and we'll call it `movies.tsx`. In this file, we'll add the following code:

```
import clientPromise from "../lib/mongodb";
import { GetServerSideProps } from 'next';

interface Movie {
   _id: string;
   title: string;
   metacritic: number;
   plot: string;
}

interface MoviesProps {
   movies: Movie];
}

const Movies: React.FC = ({ movies }) => {
   return (
       

           

TOP 20 MOVIES OF ALL TIME

           

               (According to Metacritic)
           

           

               {movies.map((movie) => (
                   

                       

{MOVIE.TITLE}

                       

{MOVIE.METACRITIC}

                       

{movie.plot}

                   
               ))}
           

       

   );
};

export default Movies;

export const getServerSideProps: GetServerSideProps = async () => {
   try {
       const client = await clientPromise;
       const db = client.db("sample_mflix");
       const movies = await db
           .collection("movies")
           .find({})
           .sort({ metacritic: -1 })
           .limit(20)
           .toArray();
       return {
           props: { movies: JSON.parse(JSON.stringify(movies)) },
       };
   } catch (e) {
       console.error(e);
       return { props: { movies: [] } };
   }
};
```
As you can see from the example above, we are importing the same `clientPromise` utility class, and our MongoDB query is exactly the same within the `getServerSideProps()` method. The only thing we really needed to change in our implementation is how we parse the response. We need to stringify and then manually parse the data, as Next.js is strict.

Our page component called `Movies` gets the props from our `getServerSideProps()` method, and we use that data to render the page showing the top movie title, metacritic rating, and plot. Your result should look something like this:

![Top 20 movies][6]

This is great. We can directly query our MongoDB database and get all the data we need for a particular page. The contents of the `getServerSideProps()` method are never sent to the client, but the one downside to this is that this method runs every time we call the page. Our data is pretty static and unlikely to change all that often. What if we pre-rendered this page and didn't have to call MongoDB on every refresh? We'll take a look at that next!

## Example 3: Next.js static generation with MongoDB
For our final example, we'll take a look at how static page generation can work with MongoDB. Let's create a new file in the `pages` directory and call it `top.tsx`. For this page, what we'll want to do is render the top 1,000 movies from our MongoDB database.

Top 1,000 movies? Are you out of your mind? That'll take a while, and the database round trip is not worth it. Well, what if we only called this method once when we built the application so that even if that call takes a few seconds, it'll only ever happen once and our users won't be affected? They'll get the top 1,000 movies delivered as quickly as or even faster than the 20 using `serverSideProps()`. The magic lies in the `getStaticProps()` method, and our implementation looks like this:

```
import { ObjectId } from "mongodb";
import clientPromise from "../lib/mongodb";
import { GetStaticProps } from "next";

interface Movie {
   _id: ObjectId;
   title: string;
   metacritic: number;
   plot: string;
}

interface TopProps {
   movies: Movie[];
}

export default function Top({ movies }: TopProps) {
   return (
       

           

TOP 1000 MOVIES OF ALL TIME

           

               (According to Metacritic)
           

           

               {movies.map((movie) => (
                   

                       

{MOVIE.TITLE}

                       

{MOVIE.METACRITIC}

                       

{movie.plot}

                   
               ))}
           

       

   );
}

export const getStaticProps: GetStaticProps = async () => {
   try {
       const client = await clientPromise;

       const db = client.db("sample_mflix");

       const movies = await db
           .collection("movies")
           .find({})
           .sort({ metacritic: -1 })
           .limit(1000)
           .toArray();

       return {
           props: { movies: JSON.parse(JSON.stringify(movies)) },
       };
   } catch (e) {
       console.error(e);
       return {
           props: { movies: [] },
       };
   }
};
```
At a glance, this looks very similar to the `movies.tsx` file we created earlier. The only significant changes we made were changing our `limit` from `20` to `1000` and our `getServerSideProps()` method to `getStaticProps()`. If we navigate to `localhost:3000/top` in our browser, we'll see a long list of movies.

![Top 1000 movies][7]

Look at how tiny that scrollbar is. Loading this page took about 3.79 seconds on my machine, as opposed to the 981-millisecond response time for the `/movies` page. The reason it takes this long is that in development mode, the `getStaticProps()` method is called every single time (just like the `getServerSideProps()` method). But if we switch from development mode to production mode, we'll see the opposite. The `/top` page will be pre-rendered and will load almost immediately, while the `/movies` and `/api/movies` routes will run the server-side code each time.

Let's switch to production mode. In your terminal window, stop the current app from running. To run our Next.js app in production mode, we'll first need to build it. Then, we can run the `start` command, which will serve our built application. In your terminal window, run the following commands:

```
npm run build
npm run start
```
When you run the `npm run start` command, your Next.js app is served in production mode. The `getStaticProps()` method will not be run every time you hit the `/top` route as this page will now be served statically. We can even see the pre-rendered static page by navigating to the `.next/server/pages/top.html` file and seeing the 1,000 movies listed in plain HTML.

Next.js can even update this static content without requiring a rebuild with a feature called [Incremental Static Regeneration, but that's outside of the scope of this tutorial. Next, we'll take a look at deploying our application on Vercel.

## Deploying your Next.js app on Vercel
The final step in our tutorial today is deploying our application. We'll deploy our Next.js with MongoDB app to Vercel. I have created a GitHub repo that contains all of the code we have written today. Feel free to clone it, or create your own.

Navigate to Vercel and log in. Once you are on your dashboard, click the **Import Project** button, and then **Import Git Repository**.

, https://nextjs-with-mongodb-mauve.vercel.app/api/movies, and https://nextjs-with-mongodb-mauve.vercel.app/top routes.

## Putting it all together
In this tutorial, we walked through the official Next.js with MongoDB example. I showed you how to connect your MongoDB database to your Next.js application and run queries in multiple ways. Then, we deployed our application using Vercel.

If you have any questions or feedback, reach out through the MongoDB Community forums and let me know what you build with Next.js and MongoDB.

  [1]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt572f8888407a2777/65de06fac7f05b1b2f8674cc/vercel-homepage.png
  [2]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt833e93bc334716a5/65de07c677ae451d96b0ec98/server-error.png
  [3]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltad2329fe1bb44d8f/65de1b020f1d350dd5ca42a5/database-deployments.png
  [4]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt798b7c3fe361ccbd/65de1b917c85267d37234400/welcome-nextjs.png
  [5]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blta204dc4bce246ac6/65de1ff8c7f05b0b4b86759a/json-format.png
  [6]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt955fc3246045aa82/65de2049330e0026817f6094/top-20-movies.png
  [7]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltfb7866c7c87e81ef/65de2098ae62f777124be71d/top-1000-movie.png
  [8]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltc89beb7757ffec1e/65de20e0ee3a13755fc8e7fc/importing-project-vercel.png
  [9]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt0022681a81165d94/65de21086c65d7d78887b5ff/configuring-project.png
  [10]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt7b00b1cfe190a7d4/65de212ac5985207f8f6b232/congratulations.png