Introduction to Prisma 2 with Next.js
Tags: react, javascript, database, tutorial
Published: 2020-04-08 20:21:08

# Introduction to Prisma with Next.js
This tutorial outlines how to use [Prisma](https://www.prisma.io/) along with [Next.js](https://nextjs.org/). It assumes a basic understanding of Next.js (which, in turn, assumes basic knowledge of React). By the end of the tutorial, you will have stood up a Prisma client, a development SQLite database, and a Next.js application.

This tutorial will not cover GraphQL with Prisma. If that is something you're interested in, please refer to [my live coding video](https://youtu.be/LAbijsCMj04) where I add Prisma with GraphQL to a Next.js project.

{% youtube LAbijsCMj04 %}

## Create a New Next.js Project
From your terminal, run:
```bash
npm init next-app
# or
yarn create next-app
```
You can find more information about the commands above in the [Next.js docs](https://nextjs.org/docs/getting-started).

This will install a new Next.js project with the directory name that you specified. Run:
```bash
npm run dev
# or
yarn dev  
``` 
to start the development server.  Now visit http://localhost:3000 to see your Next.js app. Edit `/pages/index. js` to modify this page.

## Install Prisma
From your terminal, run:
```bash
npm install @prisma/client
npm install @prisma/cli --save-dev
# or
yarn add @prisma/client
yarn add @prisma/cli -D
```
This installs the [Prisma CLI](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-cli/command-reference) which we can now use to initialize Prisma.
## Initialize Prisma
From your terminal, run
```bash
npx prisma init
# or
yarn prisma init
```
This creates two new files: `/prisma/.env` and `prisma/schema.prisma`.
* *`/prisma/.env`* - Defines the environment variables used in `/schema.prisma`. Learn more [here](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/prisma-schema-file#using-env-files).
* *`/schema.prisma`* - datasource, generator and model definitions are added here. Prisma will use this to generate migrations, GraphQL schemas and TypeScript types. Learn more [here](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/prisma-schema-file).

## Add SQLite Database as Datasource
For the purposes of this tutorial, we will use a SQLite database. In `/prisma/.env`, change `DATABASE_URL` to `file:./dev.db`:
```bash
# /prisma/.env
DATABASE_URL="file:./dev.db"
```
and in `/prisma/schema.prisma` change the datasource provider to `sqlite` :
```bash
# prisma/schema.prisma
datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}
# ... the rest of the file
```
If you're interested in using `postgres` as your database, you can skip this step and, instead, replace `DATABASE_URL` with your actual postgres URL.
## Add a Data Model
For simplicity's sake, we will create a lightweight data model. In `/prisma/schema.prisma`, add the movie model:
```graphql
# prisma/schema.prisma
# ...stuff at the top of the file
model Movie {
  id           Int    @default(autoincrement()) @id
  director     String
  movieName    String
  yearReleased Int
}
```
## Generate and Run Database Migrations
With the our model all set up, we're ready to generate migrations that will add these tables to our database. First, run:
```bash
npx prisma migrate save --experimental
# or
yarn prisma migrate save --experimental
```
Since we haven't done so, it will create a SQLite database for you. It will ask for a migration name; this is optional. You can view the newly created migration in the `/prisma/migrations` folder. Take a look and you'll see that it generated all the SQL necessary to create the new `movies` table.

Note that the new table wasn't created; simply the code to create said table. To create the table, this migration needs to be run. We do this by running:
```bash
npx prisma migrate up --experimental
# or
yarn prisma migrate up --experimental
```
This command will run any migrations that have not yet been run. After this, you can use your favorite database client (I'm partial to [TablePlus](https://tableplus.com/)) to view your database.

Learn more about Prisma migrations [here](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-cli/command-reference#migrations-experimental).
## Generate the Prisma Client
The Prisma Client is a database client tailored to your database schema. This means that we will easily be able to call a function that runs CRUD operations against our database. In our case, this means the Prisma Client will have a `movies` layer with functions to perform all CRUD operations.

To generate the Prisma Client, run:
```bash
npx prisma generate
# or
yarn prisma generate
```
Our Prisma Client is ready for use.

Learn more about the Prisma Client [here](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/generating-prisma-client).
## Add a POST endpoint to Create New Movies
Let's use our newly created Prisma Client to create a `/movies/` endpoint that creates new movies. In `/pages/api/movies.js` (you'll have to create an `/api` directory and a `movies.js` file), paste the following:
```javascript
// /pages/api/movies.js
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default async function (req, res) {
  if (req.method === 'POST') {
    const { body } = req;
    const movie = await prisma.movie.create({ data: JSON.parse(body) });
    res.json(movie);
  }
}
```
Any file inside the folder `/pages/api` is mapped to `/api/*` and treated as an API endpoint. In our case, we now have an endpoint at `http://localhost:3000/api/movies`.

Stepping down the file, we:
1. Import the `PrismaClient` from `@prisma/client`. Yes, our own personal database client is saved to `node_modules`. The generated code is saved to `node_modules` and is referred to as a "smart node module." You can learn more [here](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/generating-prisma-client#how-prisma-client-compares-to-conventional-node-modules).
2. Initialize an instance of the `PrismaClient` and save it to a variable called `prisma`.
3. Use a [Next.js API Route](https://nextjs.org/docs/api-routes/introduction) and only handle POST request.
4. Use the `body` of the request and the Prisma client to create a new movie and save it to a variable called `movie`. Note that we parse the body since we will send it as a JSON string.
5. Respond with the `movie` created in the step above.

## Create a Movie Submission Form
We will use [Formik](https://jaredpalmer.com/formik/) to create our movie submission form. Please feel free to _not_ use Formik if you're more comfortable using HTML forms (or any other React forms library).

If you're using Formik, run:
```bash
npm install formik
# or
yarn add formik
```

Replace all of `pages/index.js` with:
```jsx
// /pages/index.js
import { Field, Formik, Form } from 'formik';

const Home = () => (
  <div className="container">
    <Formik
      initialValues={{
        director: '',
        movieName: '',
        yearReleased: '',
      }}
      onSubmit={(values) => {
        fetch('http://localhost:3000/api/movies', {
          method: 'POST',
          body: JSON.stringify({ ...values, yearReleased: Number(values.yearReleased) }),
        });
      }}
    >
      <Form>
        <label>
          Movie Name
          <Field name="movieName" type="text"></Field>
        </label>
        <label>
          Director
          <Field name="director" type="text"></Field>
        </label>
        <label>
          Year Released
          <Field name="yearReleased" type="text"></Field>
        </label>
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  </div>
);

export default Home;
```
The code above should be straightforward. The submit function makes a _POST_ request to our `/api/movies` endpoint. Please note that we need to cast `yearReleased` here to a `number` as the Prisma client expects an `Int` (as defined in `/prisma/schema.prisma`.

Now, create a movie and press submit. Using your database client, you can view the `movies` table and see that a new movie was created.
## Use Server-Side Rendering to Hydrate Page Props on the Server
This right here is where the beauty of Next.js comes in. We can use [`getServerSideProps`](https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering) to fetch our movie data on the server-side (using our Prisma Client). The movies will be pre-rendered on our homepage (no client-side fetching necessary!).

Normally, you might create a `GET` endpoint that uses the Prisma client to fetch a list of movies and respond with said list of movies. With `getServerSideProps`, there's no need for the endpoint. We can use the Prisma client directly in that function to get the list of movies and inject our page's props with the movies.

At the bottom of our `/pages/index.js` file, add the following code:
```javascript
// /pages/index.js

// Home component cut for brevity

export const getServerSideProps = async () => {
  const prisma = new PrismaClient();
  const movies = await prisma.movie.findMany();
  return { props: { movies } };
};
```
Here, we:
1. Instantiate our `PrismaClient`
2. Get all movies using the `prisma` instance
3. Return a `props` object that includes the `movies` we just fetched

With this code, our `Home` component now has `movies` props. For example, we can render the movies as follows:
```jsx
// /pages/index.js
const Home = ({ movies }) => (
  <div className="container">
    {movies.map((movie) => (
      <div key={movie.id}>
        <p>Name: {movie.movieName}</p>
        <p>Director: {movie.director}</p>
        <p>Year Released: {movie.yearReleased}</p>
      </div>
    ))}
    <Formik>
      {/* your movie form is here; cut for brevity */}
    </Formik>
  </div>
);
```

Again, there is NO fetching of movies on the client. It's all done on the server.

## Mission Accomplished
This tutorial should be enough to get you started with Next.js and Prisma.

If you have any questions or feedback, you can reach me on Twitter: [@aryanjabbari](https://twitter.com/AryanJabbari).