Build Scalable Web Apps with Next.js & Prisma ORM

blog-banner

Next.js is a React framework, which is used to build fast and scalable web applications. It provides various features like server-side rendering, API routes, and components for building a web application. You can easily manage your database by using Prisma as ORM tool with it, which is a type-safe and easy to manage database and organize the code. With Prisma, you can define your schema in one place and using that you can generate fully typed database queries automatically, write cleaner and maintainable backend logic.

Prisma generates a client based on your schema, which you can use to interact with your database safely and reliably. It works great with Next.js. You can plug it right into your server actions to read, write, update, or remove data without much hassle. With Prisma and Next.js together, you've got pretty much everything you need to build a complete full-stack app without a bunch of extra setup. This is exactly how SurekhaTech builds modern web solutions efficiently.

Prerequisites

  1. Basic understanding in JavaScript & React 
  2. Node.js (>=18) and npm/yarn/pnpm 
  3. Understanding of relational database (MySQL, Posgress) 

In this blog, we will walk through:

  1. Integrating Prisma with Next.js
  2. Creating full CRUD server actions with Prisma
  3. Important Prisma CLI Commands

Integrating Prisma with Next.js

Step 1: Create Your Next.js Project

  1. npx create-next-app@latest nextjs-prisma-app –typescript 
  2. cd nextjs-prisma-app 

Step 2: Install Dependencies

  1. npm install prisma --save-dev 
  2. npm install @prisma/client

Step 3: Initialize Prisma 

  1. npx prisma init 
  2. This creates: 

prisma/schema.prisma 

`.env` with placeholder `DATABASE_URL` 

Step 4: Connect to MySQL 

  1. Update your.env file:

DATABASE_URL="mysql://username:password@localhost:3306/mydatabase" 

Prisma supports various popular relational databases. So, you can use PostgreSQL, SQL Server (MSSQL) and SQLite.

Step 5: Define schema models in schema.prisma file

 generator client { 

  provider = "prisma-client-js" 

} 

datasource db { 

  provider = "mysql" 

  url             = env("DATABASE_URL") 

} 

enum UserType { 

  DEALER 

  DISTRIBUTOR 

  ADMIN 

  CUSTOMER 

} 

model Role { 

  id    Int    @id @default(autoincrement()) 

  name      String 

  users      User[] 

}

model User { 

  id                    Int                     @id @default(autoincrement()) 

  name           String 

  email           String               @unique 

  type              UserType 

  roleId           Int 

  role               Role                 @relation(fields: [roleId], references: [id]) 

  createdAt  DateTime       @default(now()) 

}

Step 6: Apply your migration:

  1. npx prisma migrate dev --name add-user-role-type 

This will create another timestamped folder inside prisma/migrations/ with the SQL migration script.

Looking For Expert Next.Js Developer

Creating full CRUD server actions with Prisma

Let’s create server actions that you can use in your application and the required types. We can use prisma client relational database queries for CRUD, searching and filtering records from database using prisma client models. 

Create type.ts file to define types for CRUD

 export type CreateUserInput = {

  name: string;

  email: string;

  roleId: number;

  type: 'DEALER' | 'DISTRIBUTOR' | 'ADMIN' | 'CUSTOMER';

};

export type UpdateUserInput = {

  name?: string;

  email?: string;

  roleId?: number;

  type?: 'DEALER' | 'DISTRIBUTOR' | 'ADMIN' | 'CUSTOMER';

};

export type UserQueryOptions = {

  search?: string; 
  sortBy?: 'name' | 'email' | 'createdAt';

  sortOrder?: 'asc' | 'desc';

  page?: number;

  pageSize?: number;

};

Server Actions (app/actions/user-role.ts)

'use server'; 

import { prisma } from '@/lib/prisma'; 

import { revalidatePath } from 'next/cache'; 

  

export async function getRoles() { 

  return prisma.role.findMany(); 

} 

  

export async function createRole(name: string) { 

  const role = await prisma.role.create({ data: { name } }); 

  revalidatePath('/users'); 

  return role; 

} 

  

export async function getUsers(options: UserQueryOptions = {}) { 

  const { 

    search = '', 

    sortBy = 'createdAt', 

    sortOrder = 'desc', 

    page = 1, 

    pageSize = 10, 

  } = options; 

  const where = search 

    ? { 

        OR: [ 

          { name: { contains: search, mode: 'insensitive' } }, 

          { email: { contains: search, mode: 'insensitive' } }, 

        ], 

      } 

    : {}; 

  const users = await prisma.user.findMany({ 

    where, 

    include: { role: true }, 

    orderBy: { [sortBy]: sortOrder }, 

    skip: (page - 1) * pageSize, 

    take: pageSize, 

  }); 

  

  const total = await prisma.user.count({ where }); 

  

  return { 

    data: users, 

    total, 

    page, 

    pageSize, 

    totalPages: Math.ceil(total / pageSize), 

  }; 

} 

  
export async function createUser(data: CreateUserInput) { 

  const user = await prisma.user.create({ data }); 

  revalidatePath('/users'); 

  return user; 

} 


export async function updateUser(id: number, data: UpdateUserInput) { 

  const user = await prisma.user.update({ where: { id }, data }); 

  revalidatePath('/users'); 

  return user; 

} 


export async function deleteUser(id: number) { 

  const user = await prisma.user.delete({ where: { id } }); 

  revalidatePath('/users'); 

  return user; 

} 

Use server action in your component

'use client'; 

import { useEffect, useState } from 'react'; 

import { getUsers } from '../actions/user-role'; 

  

export default function UsersPage() { 

  const [users, setUsers] = useState([]); 

  const [search, setSearch] = useState(''); 

  const [page, setPage] = useState(1); 

  

  useEffect(() => { 

    getUsers({ search, page, pageSize: 5 }).then((res) => { 

      setUsers(res.data); 

    }); 

  }, [search, page]); 

  

  return ( 

    <div> 

      <h1>All Users</h1> 

      <input 

        type="text" 

        placeholder="Search users..." 

        value={search} 

        onChange={(e) => setSearch(e.target.value)} 

      /> 

      <ul> 

        {users.map((user) => ( 

<li key={user.id}> 

            {user.name} ({user.email}) - {user.type} - Role: {user.role?.name} 

          </li> 

        ))} 

      </ul> 

      <button disabled={page === 1} onClick={() => setPage((p) => p - 1)}>Previous</button> 

      <button onClick={() => setPage((p) => p + 1)}>Next</button> 

    </div> 

  ); 

} 

Not Sure Where to Start With Next.Js

Important Prisma CLI Commands

`npx prisma migrate dev --name init` 
 
In accordance with the schema, this command creates a Prisma Client and performs a database migration. In the 'prisma/migrations' folder, a new folder will be created. A timestamped migration folder and a.sql file will be included in the new folder. 'prisma/migrations/20250703125434_init/migration.sql' is one example.   
 
The Prisma schema migration changes are reflected in the SQL file. As a result, versioning and tracking database changes is simple. 

`npx prisma db pull`
 
This command will inspect the current schema from the database and change your `schema.prisma` file appropriately if you're dealing with an existing database.  It lets you use Prisma and create types without having to manually define database schema models. 

npx prisma generate
 
With this command, your database's TypeScript/JavaScript interface, known as the Prisma Client, is renewed. This command is helpful when you manually edit the Prisma schema by adding or changing columns, relationships, building a new schema model, etc. It guarantees that your code can access the most recent types and queries.

Conclusion

Using Next.js & Prisma ORM makes it easier to build modern, type-safe, and scalable applications with minimal configuration. Using Prisma improves safety and makes it easy to use with Next.js server actions for managing your database.

If you're interested in how Next.js is transforming modern web development, check out our related post: Next.js: A Real Game Changer for Upcoming Web App Development

Contact us

For Your Business Requirements

Contact us