Next.js · Lesson 9 of 15
Databases with Prisma
Query Postgres from Server Components and mutate with server actions.
- Intermediate
- 17 min read
- 3 objectives
Before this lessonLesson 8: Middleware, Cookies and Sessions
What you will learn
- Define a Prisma schema
- Query in a page
- Mutate and revalidate
Your Progress
0 of 15 lessons 0%
- Lessons0 / 15
- Completed0
- Est. time left~ 4 hours
Create a free account to keep your progress on every device.
Prisma is a typed ORM that fits the App Router: generate a client, query from Server Components, mutate from server actions.
Schema and client
npm install prisma @prisma/client
npx prisma init --datasource-provider postgresql// prisma/schema.prisma
model Post {
id Int @id @default(autoincrement())
title String
body String
published Boolean @default(false)
createdAt DateTime @default(now())
}// lib/db.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
export const db = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = db;The global cache stops Next.js hot reload from opening a new connection on every save.
Read on the server
// app/posts/page.tsx
import { db } from "@/lib/db";
export default async function Posts() {
const posts = await db.post.findMany({ where: { published: true }, orderBy: { createdAt: "desc" } });
return <ul>{posts.map((p) => <li key={p.id}>{p.title}</li>)}</ul>;
}Write with a server action
"use server";
import { db } from "@/lib/db";
import { revalidatePath } from "next/cache";
import { z } from "zod";
const Input = z.object({ title: z.string().min(1).max(120) });
export async function createPost(formData: FormData) {
const parsed = Input.safeParse({ title: formData.get("title") });
if (!parsed.success) return { error: "Title required" };
await db.post.create({ data: { title: parsed.data.title, body: "" } });
revalidatePath("/posts");
}