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;
}