See all blogs

July 12, 2026

Set Up Prisma 7 in Next.js 15+ with Neon DB or Prisma Postgres

Set Up Prisma 7 in Next.js 15+ with Neon DB or Prisma PostgresSet Up Prisma 7 in Next.js 15+ with Neon DB or Prisma Postgres

Reference: jb.desishub.com โ€” Prisma 7 + Next.js setup guide ยท Prisma documentation

This guide follows the same kind of setup used in this app: Next.js App Router, TypeScript, Prisma 7's new driver-adapter architecture, and a Postgres database โ€” with a choice of either Neon or Prisma's own managed Postgres.

backstory

Prisma 7 changed how the client connects to your database โ€” it now goes through a driver adapter (@prisma/adapter-pg for Postgres) instead of Prisma's older built-in query engine binary. This guide walks through the setup cleanly for both of the two most common free Postgres options right now: Neon and Prisma Postgres.

The important idea is this:

Prisma 7 needs three things working together: a schema.prisma file describing your tables, a prisma.config.ts file describing how to connect and migrate, and a driver adapter that actually talks to Postgres over the wire.

Once those three pieces agree with each other, everything else โ€” seeding, querying, server actions โ€” works the same regardless of which Postgres provider you chose.


what we are building

By the end, you will have this:

app/
  generated/
    prisma/          # generated Prisma Client output
  page.tsx
 
lib/
  prisma.ts
 
prisma/
  schema.prisma
  seed.ts
 
prisma.config.ts
.env

A working connection to either:

Neon         โ†’ a serverless Postgres branch
Prisma Postgres โ†’ Prisma's own managed Postgres instance

prerequisites

Before installing Prisma 7, make sure you already have:

  • Node.js 18 or newer
  • A Next.js 15+ project using the App Router
  • TypeScript configured
  • Either a Neon account, or nothing at all if you're using Prisma Postgres (Prisma can provision one for you during prisma init)

Prisma Postgres currently offers 5 free databases per account. Neon offers 10 free projects. Pick whichever fits your workflow โ€” both work identically once connected through Prisma 7's adapter.

Check which package manager you're using before continuing โ€” every command below is shown for both npm and pnpm.


step 1: create or open your Next.js project

If you're starting fresh:

pnpm create next-app@latest my-app
cd my-app

Select these options when prompted:

  • โœ… TypeScript
  • โœ… ESLint
  • โœ… Tailwind CSS
  • โœ… App Router
  • โœ… Turbopack
  • โŒ No src directory (optional, either works with this guide)

If you already have an existing Next.js 15+ project, just cd into it and continue from Step 2.


step 2: install Prisma's dependencies

Prisma 7 splits its dependencies into dev tooling (prisma, tsx) and runtime packages (@prisma/client, the driver adapter, and the underlying pg driver).

pnpm add prisma tsx @types/pg --save-dev
pnpm add @prisma/client @prisma/adapter-pg dotenv pg

What each package does:

  • prisma โ€” the CLI (generate, db push, studio, etc.)
  • tsx โ€” runs TypeScript files directly, used for seeding
  • @prisma/client โ€” the generated, type-safe query client
  • @prisma/adapter-pg โ€” the Postgres driver adapter Prisma 7 requires
  • pg โ€” the underlying node-postgres driver the adapter wraps
  • dotenv โ€” loads .env variables into prisma.config.ts

step 3: initialize Prisma

pnpm dlx prisma init --db --output ../app/generated/prisma

The --db flag provisions a free Prisma Postgres database automatically and writes its connection string straight into .env. If you'd rather use Neon instead, skip the --db flag:

pnpm dlx prisma init --output ../app/generated/prisma

This creates:

  • prisma/schema.prisma โ€” your database schema
  • prisma.config.ts โ€” Prisma 7's new configuration file
  • .env โ€” with a placeholder or real DATABASE_URL
  • app/generated/prisma โ€” the output folder for your generated client

step 4: connect to Neon (skip this step if using Prisma Postgres)

If you initialized without --db, get your connection string from the Neon dashboard:

  1. Create a project at neon.tech
  2. Copy the connection string from your project's Connection Details panel โ€” it looks like postgresql://user:password@ep-xxxx.region.aws.neon.tech/dbname?sslmode=require
  3. Paste it into .env:
DATABASE_URL="postgresql://user:password@ep-xxxx.region.aws.neon.tech/dbname?sslmode=require"

Neon connection strings include ?sslmode=require by default โ€” keep this, since Neon requires SSL connections.


step 5: define your database schema

Update prisma/schema.prisma:

generator client {
  provider = "prisma-client"
  output   = "../app/generated/prisma"
}
 
datasource db {
  provider = "postgresql"
}
 
model Category {
  id        String   @id @default(cuid())
  title     String
  slug      String   @unique
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

Notice the datasource block has no url field here โ€” in Prisma 7, the connection URL is supplied through prisma.config.ts instead of directly in schema.prisma. That's covered next.


step 6: configure prisma.config.ts

This file is new in Prisma 7 โ€” it replaces the old pattern of putting everything inside schema.prisma and environment variable magic.

import 'dotenv/config';
import { defineConfig, env } from 'prisma/config';
 
export default defineConfig({
  schema: 'prisma/schema.prisma',
  migrations: {
    path: 'prisma/migrations',
  },
  datasource: {
    url: env('DATABASE_URL'),
  },
});

What this does:

  • import 'dotenv/config' loads your .env file before Prisma reads anything โ€” without this, env('DATABASE_URL') returns undefined.
  • datasource.url is where the actual connection string now lives, regardless of whether you're using Neon or Prisma Postgres.
  • migrations.path tells Prisma where to store migration history if you use prisma migrate later.

step 7: push your schema to the database

Prisma 7 documentation currently recommends db push over migrate dev for early development โ€” migrate dev has known issues with the new config format at the time of writing. Use migrate dev once your schema stabilizes and you want proper migration history.

pnpm dlx prisma db push

Then generate the Prisma Client:

pnpm dlx prisma generate

This writes the generated, type-safe client into app/generated/prisma, matching the output path set in Step 5.


step 8: set up the Prisma Client singleton

Create lib/prisma.ts:

mkdir -p lib && touch lib/prisma.ts
import { PrismaClient } from '../app/generated/prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';
 
const globalForPrisma = global as unknown as {
  prisma: PrismaClient;
};
 
const adapter = new PrismaPg({
  connectionString: process.env.DATABASE_URL,
});
 
const db = globalForPrisma.prisma || new PrismaClient({ adapter });
 
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db;
 
export default db;

What this does:

  • PrismaPg is the driver adapter โ€” this is the Prisma 7 way of connecting, replacing the old built-in query engine.
  • The globalForPrisma pattern prevents Next.js's hot-reload in development from spinning up a new database connection on every file save.
  • Exported as db for shorter, cleaner imports throughout your app.

step 9: create a seed file

touch prisma/seed.ts
import db from '@/lib/prisma';
import { Prisma } from '../app/generated/prisma/client';
 
const categoriesData: Prisma.CategoryCreateInput[] = [
  { title: 'Electronics', slug: 'electronics' },
  { title: 'Fashion', slug: 'fashion' },
  { title: 'Home & Garden', slug: 'home-garden' },
  { title: 'Sports', slug: 'sports' },
];
 
export async function main() {
  for (const cat of categoriesData) {
    await db.category.create({ data: cat });
  }
}
 
main();

Register the seed command inside prisma.config.ts:

import 'dotenv/config';
import { defineConfig, env } from 'prisma/config';
 
export default defineConfig({
  schema: 'prisma/schema.prisma',
  migrations: {
    path: 'prisma/migrations',
    seed: `tsx prisma/seed.ts`,
  },
  datasource: {
    url: env('DATABASE_URL'),
  },
});

Run the seed:

pnpm dlx prisma db seed

Then confirm the data landed with Prisma Studio:

pnpm dlx prisma studio

step 10: query the database from a page

import db from '@/lib/prisma';
import Link from 'next/link';
 
export default async function Home() {
  const categories = await db.category.findMany({
    orderBy: { createdAt: 'desc' },
  });
 
  return (
    <div className="min-h-screen bg-blue-50 p-8">
      <div className="flex items-center justify-between py-6">
        <h2 className="text-3xl font-semibold tracking-tight">Categories</h2>
      </div>
      <div className="grid grid-cols-1 gap-4 rounded bg-white p-8 md:grid-cols-2 lg:grid-cols-4">
        {categories.map((category) => (
          <Link
            href={`/${category.slug}`}
            key={category.id}
            className="rounded border p-4 transition-colors hover:bg-gray-50"
          >
            {category.title}
          </Link>
        ))}
      </div>
    </div>
  );
}

Run your dev server and confirm the seeded categories render:

pnpm dev

step 11: add server actions for mutations

mkdir -p controllers/actions && touch controllers/actions/category.ts
'use server';
 
import db from '@/lib/prisma';
import { revalidatePath } from 'next/cache';
 
export type CategoryFormData = {
  name: string;
};
 
export async function createCategory(data: CategoryFormData) {
  try {
    const slug = data.name.toLowerCase().trim().split(' ').join('-');
 
    await db.category.create({
      data: { title: data.name, slug },
    });
 
    revalidatePath('/');
    return { success: true, message: 'Category created successfully' };
  } catch (error) {
    console.log(error);
    return { success: false, message: 'Failed to create category' };
  }
}
 
export async function deleteCategory(id: string) {
  try {
    await db.category.delete({ where: { id } });
    revalidatePath('/');
    return { success: true, message: 'Category deleted successfully' };
  } catch (error) {
    console.log(error);
    return { success: false, message: 'Failed to delete category' };
  }
}

step 12: prepare for deployment

Add a postinstall script so Prisma Client regenerates automatically after every install on your host (Vercel, a VPS, etc.):

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "postinstall": "prisma generate",
    "start": "next start",
    "lint": "next lint"
  },
  "prisma": {
    "seed": "tsx prisma/seed.ts"
  }
}

When deploying, add DATABASE_URL as an environment variable on your host โ€” for Vercel, that's under Project Settings โ†’ Environment Variables. Use your Neon connection string or your Prisma Postgres connection string, exactly as it appears in your local .env.


step 13: understand the important files

prisma/schema.prisma

This defines every table.

It answers:

  • What models exist?
  • What generator and output path should Prisma use?

prisma.config.ts

This is Prisma 7's new configuration entry point.

It answers:

  • Where does the connection string come from?
  • Where do migrations live?
  • What command seeds the database?

lib/prisma.ts

This is the shared, type-safe client.

It answers:

  • How does the app connect through the driver adapter?
  • How is the connection reused across hot reloads in development?

prisma/seed.ts

This populates your database with starter data.

It answers:

  • What rows should exist when the database is first set up?

common errors and fixes

prisma migrate dev fails or behaves unexpectedly

At the time of writing, migrate dev has known issues with Prisma 7's new config format. Use db push during early development instead:

pnpm dlx prisma db push

env('DATABASE_URL') returns undefined

prisma.config.ts doesn't automatically load .env โ€” make sure import 'dotenv/config'; is the very first line in the file.

Turbopack dev server issues on Next.js 15.2.0 or 15.2.1 specifically

Remove --turbopack from your dev script in package.json if you're pinned to one of those two exact versions:

{
  "scripts": {
    "dev": "next dev"
  }
}

Newer Next.js 15.x and 16.x releases don't have this issue.

Cannot find module '../app/generated/prisma/client'

Run prisma generate again โ€” the generated client only exists after this command runs, and it needs to be re-run any time you change schema.prisma.


quick reference commands

pnpm dlx prisma init --db --output ../app/generated/prisma   # initialize with Prisma Postgres
pnpm dlx prisma db push                                       # push schema
pnpm dlx prisma generate                                      # generate client
pnpm dlx prisma db seed                                       # seed database
pnpm dlx prisma studio                                        # open Prisma Studio

final checklist

Use this checklist when setting up Prisma 7 in a Next.js 15+ project:

  • Create or open a Next.js 15+ App Router project
  • Install prisma, tsx, @types/pg as dev dependencies
  • Install @prisma/client, @prisma/adapter-pg, dotenv, pg as dependencies
  • Run prisma init โ€” with --db for Prisma Postgres, without it for Neon
  • If using Neon, paste your connection string into .env
  • Define your models in prisma/schema.prisma
  • Configure prisma.config.ts with dotenv/config and your datasource URL
  • Run prisma db push, then prisma generate
  • Create lib/prisma.ts with the PrismaPg adapter singleton
  • Create and run a seed file
  • Query the database from a Server Component
  • Add server actions for mutations
  • Add a postinstall script before deploying
  • Set DATABASE_URL as an environment variable on your host

conclusion

The clean mental model is:

schema.prisma
  -> prisma.config.ts (connection + migrations + seed)
  -> prisma db push
  -> prisma generate
  -> lib/prisma.ts (PrismaPg adapter singleton)
  -> your app's Server Components and Server Actions

Whether the actual database sits on Neon or Prisma Postgres makes almost no difference once you're past Step 6 โ€” both are just a DATABASE_URL pointing at a Postgres instance, and Prisma 7's driver adapter talks to either one identically.

The biggest advice is simple:

Use db push over migrate dev for now, always load dotenv/config at the top of prisma.config.ts, and re-run prisma generate every time your schema changes.

resources

  • Prisma documentation
  • Prisma driver adapters
  • Neon documentation
  • Next.js documentation
  • Reference walkthrough: jb.desishub.com โ€” Prisma 7 + Next.js setup guide

See all blogs