Skip to main content
Chapter 6 Database Integration with Prisma

Prisma Setup and Schema Definition

22 min read Lesson 21 / 28

Getting Started with Prisma

Prisma is the TypeScript ORM of choice for Next.js applications. It generates a fully typed client from your schema, making database operations safe and self-documenting.

Installation

npm install prisma @prisma/client
npx prisma init --datasource-provider postgresql

This creates prisma/schema.prisma and adds DATABASE_URL to .env.

Defining the Schema

// prisma/schema.prisma
generator client {
    provider = "prisma-client-js"
}

datasource db {
    provider = "postgresql"
    url      = env("DATABASE_URL")
}

model User {
    id            String    @id @default(cuid())
    name          String?
    email         String    @unique
    emailVerified DateTime?
    image         String?
    password      String?
    role          Role      @default(USER)
    createdAt     DateTime  @default(now())
    updatedAt     DateTime  @updatedAt

    posts         Post[]
    comments      Comment[]
    accounts      Account[]
    sessions      Session[]

    @@index([email])
}

enum Role {
    USER
    EDITOR
    ADMIN
}

model Post {
    id          String    @id @default(cuid())
    title       String
    slug        String    @unique
    content     String
    excerpt     String?
    published   Boolean   @default(false)
    publishedAt DateTime?
    createdAt   DateTime  @default(now())
    updatedAt   DateTime  @updatedAt

    authorId    String
    author      User      @relation(fields: [authorId], references: [id], onDelete: Cascade)

    categoryId  String?
    category    Category? @relation(fields: [categoryId], references: [id])

    tags        Tag[]
    comments    Comment[]

    @@index([slug])
    @@index([authorId])
    @@index([published, publishedAt])
}

model Category {
    id    String @id @default(cuid())
    name  String @unique
    slug  String @unique
    posts Post[]
}

model Tag {
    id    String @id @default(cuid())
    name  String @unique
    posts Post[]
}

model Comment {
    id        String   @id @default(cuid())
    body      String
    createdAt DateTime @default(now())

    authorId  String
    author    User     @relation(fields: [authorId], references: [id], onDelete: Cascade)

    postId    String
    post      Post     @relation(fields: [postId], references: [id], onDelete: Cascade)
}

Running Migrations

npx prisma migrate dev --name init    # Create and apply migration
npx prisma migrate deploy             # Apply in production
npx prisma db push                    # Sync schema without migration (prototyping)
npx prisma studio                     # Open GUI to browse data

Prisma Client Singleton

Prevent multiple client instances in development due to hot reloading:

// lib/db.ts
import { PrismaClient } from '@prisma/client';

const globalForPrisma = globalThis as unknown as {
    prisma: PrismaClient | undefined;
};

export const db =
    globalForPrisma.prisma ??
    new PrismaClient({
        log: process.env.NODE_ENV === 'development'
            ? ['query', 'error', 'warn']
            : ['error'],
    });

if (process.env.NODE_ENV !== 'production') {
    globalForPrisma.prisma = db;
}