ORM
Prisma ORM Forms
Type-safe database mutations, nested relations, and error mapping with Prisma Client in Next.js.
Preview
Prisma ORM Relations
Prisma Nested Relational Form
Create deeply nested relational database records with single-transaction type safety and automated Prisma Client validation.
Interactive responsive preview
Drag handles on right and bottom to resize
Overview
Prisma ORM provides an auto-generated, type-safe query builder based on your declarative schema.prisma. When paired with Next.js forms and Server Actions, Prisma simplifies complex nested inserts, atomic multi-table updates, and constraint error handling.
Schema Definition
// prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Workspace {
id String @id @default(cuid())
name String
slug String @unique
tier String @default("PRO")
createdAt DateTime @default(now())
projects Project[]
}
model Project {
id String @id @default(cuid())
name String
environment String @default("PRODUCTION")
workspaceId String
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
}Server Action with Prisma Mutation
'use server';
import { prisma } from '@/lib/prisma';
import { Prisma } from '@prisma/client';
import { revalidatePath } from 'next/cache';
import { z } from 'zod';
const schema = z.object({
workspaceName: z.string().min(2),
workspaceSlug: z.string().min(2),
initialProject: z.string().min(2),
});
export async function createWorkspace(formData: FormData) {
const validated = schema.parse(Object.fromEntries(formData));
try {
const workspace = await prisma.workspace.create({
data: {
name: validated.workspaceName,
slug: validated.workspaceSlug,
projects: {
create: [
{ name: validated.initialProject }
]
}
},
include: {
projects: true,
}
});
revalidatePath('/workspaces');
return { success: true, workspace };
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2002') {
return { success: false, error: 'A workspace with this slug already exists.' };
}
}
return { success: false, error: 'Failed to create workspace.' };
}
}Best Practices
- Leverage Nested Writes: Use
createinside relational models instead of performing multiple disjoint SQL queries. - Handle Known Error Codes: Intercept
PrismaClientKnownRequestErrorto turn constraint violations likeP2002(unique violation) into clear form error messages. - Connection Pooling: Use Prisma Accelerate or Supabase/Neon connection poolers for Serverless and Edge runtimes.