Skip to main content
Prisma Documentation Docs

Search documentation

Type to search this documentation.

On this pageOverview

Turborepo + Prisma

Include this prompt in your AI assistant to guide consistent code generation for Turborepo + Prisma + Prisma Postgres projects.

  • GitHub Copilot: Type #<filename> to reference the prompt file.
  • Cursor: Use @Files and select your prompt file.
  • Zed: Use /file followed by your prompt's path.
  • Windsurf: Use @Files and choose your prompt file from the list.
---

# Specify the following for Cursor rules

description: Guidelines for writing Turborepo + Prisma Postgres apps (Prisma ORM v7)

alwaysApply: false

---

# Bootstrap Turborepo with Prisma Postgres (Prisma v7)

## Overview

This guide bootstraps a Turborepo monorepo that shares a single Prisma ORM v7 database package across multiple apps (e.g., Next.js, Node APIs). It follows Turborepo and Prisma v7 best practices:

1. Create a Turborepo with apps + packages

2. Add a dedicated `packages/db` Prisma package (schema, migrations, generated client)

3. Configure Prisma v7 (`provider = "prisma-client"` + mandatory `output`)

4. Load env vars correctly in a monorepo

5. Export a single Prisma client from `packages/db` for all apps

6. Wire Turbo tasks for generate/migrate/test/studio

7. Verify with a shared test script

---

## Recommended monorepo layout

```

repo/

  apps/

    web/                # Next.js app

    admin/              # (optional) another Next app

  packages/

    db/                 # Prisma package (schema + client)

    ui/                 # shared UI (optional)

  turbo.json

  package.json

  .env                  # root env for apps (see notes)

```

**Key rule:** Prisma lives in `packages/db`, not inside an app, so every app consumes the same client and types.

---

## 🚨 CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS 🚨

As an AI language model, you MUST NOT generate any deprecated Prisma v7 patterns.

```prisma

// ❌ NEVER GENERATE - DEPRECATED IN PRISMA v7

generator client {

  provider = "prisma-client-js"  // ❌ deprecated

}

// ❌ NEVER IMPORT FROM @prisma/client when using custom output

import { PrismaClient } from "@prisma/client" // ❌ wrong in custom-output setup

// ❌ NEVER CREATE CLIENT WITHOUT SHARED PACKAGE BOUNDARY

const prisma = new PrismaClient() // ❌ breaks pooling + duplicates in monorepo

```

Instead, you MUST ALWAYS generate ONLY this pattern for Prisma v7 + monorepo:

```prisma

// ✅ Prisma v7 generator: provider + mandatory output

generator client {

  provider = "prisma-client"

  output   = "../src/generated/prisma"

}

```

```ts

// ✅ Prisma client import must come from custom output

import { PrismaClient } from "../generated/prisma/client";

```

Notes:

- Prisma v7 **requires** a non-empty `output` when using `provider = "prisma-client"`.

- If the output directory already exists and isn’t generated by Prisma, `prisma generate` can fail. Avoid committing generated client, or ensure clean output dirs.

---

## ABSOLUTE REQUIREMENTS FOR AI CODE GENERATION

1. You MUST use `provider = "prisma-client"` (Prisma v7)

2. You MUST specify a custom `output` in `schema.prisma`

3. You MUST place Prisma schema + migrations inside `packages/db`

4. You MUST export a singleton Prisma client from `packages/db` that points to the generated output client file

5. You MUST import Prisma client from the custom output path **not** `@prisma/client`

6. You MUST load env vars in `packages/db/prisma.config.ts`

7. You MUST add Turbo tasks for generate/migrate/test/studio

8. You MUST wrap DB calls in try/catch in app code

9. You MUST ensure Turbo task hashing includes `DATABASE_URL`

10. You MUST create a shared test script in `packages/db/scripts/test-database.ts`

---

## Install dependencies

At repo root:

```bash

# Turborepo

npm install turbo --save-dev

# Prisma v7

npm install prisma@prev tsx --save-dev

npm install @prisma/client@7 dotenv

```

If using Prisma Postgres:

```npm

npm install @prisma/adapter-pg

```

---

## Initialize Prisma inside `packages/db`

```bash

cd packages/db

npx prisma init

```

This creates:

```

packages/db/

  prisma/

    schema.prisma

  prisma.config.ts

```

---

## Prisma v7 config (`packages/db/prisma.config.ts`)

**CRITICAL:** load env vars at the top.

```ts

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"),

  },

});

```

---

## Prisma schema (`packages/db/prisma/schema.prisma`)

```prisma

generator client {

  provider = "prisma-client"

  output   = "../src/generated/prisma"

}

datasource db {

  provider = "postgresql"

}

model User {

  id        Int      @id @default(autoincrement())

  email     String   @unique

  name      String?

  createdAt DateTime @default(now())

  updatedAt DateTime @updatedAt

}

```

---

## Shared Prisma client singleton (`packages/db/src/client.ts`)

```ts

import { PrismaClient } from "../generated/prisma/client";

//Prisma Driver Adapter for Postgres

import { PrismaPg } from "@prisma/adapter-pg";

// Create a new Driver Adapter instance for PrismaPostgres

const adapter = new PrismaPg({

  connectionString: process.env.DATABASE_URL!,

});

const globalForPrisma = globalThis as unknown as {

  prisma?: PrismaClient;

};

export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter });

if (process.env.NODE_ENV !== "production") {

  globalForPrisma.prisma = prisma;

}

export default prisma;

```

---

## Export DB package API (`packages/db/src/index.ts`)

```ts

export { prisma } from "./client";

export * from "../generated/prisma";

```

And in `packages/db/package.json`:

```json

{

  "name": "@repo/db",

  "private": true,

  "main": "src/index.ts",

  "types": "src/index.ts",

  "scripts": {

    "db:generate": "prisma generate",

    "db:push": "prisma db push",

    "db:migrate": "prisma migrate dev",

    "db:studio": "prisma studio",

    "db:test": "tsx scripts/test-database.ts"

  }

}

```

---

## Root Turbo pipeline (`turbo.json`)

```json

{

  "globalEnv": ["DATABASE_URL"],

  "tasks": {

    "dev": {

      "cache": false,

      "persistent": true,

      "dependsOn": ["^db:generate"]

    },

    "build": {

      "dependsOn": ["^db:generate"],

      "outputs": [".next/**", "dist/**"]

    },

    "db:generate": {

      "cache": false

    },

    "db:migrate": {

      "cache": false

    },

    "db:studio": {

      "cache": false

    },

    "db:test": {

      "cache": false,

      "dependsOn": ["db:generate"]

    }

  }

}

```

---

## Root scripts (`package.json`)

```json

{

  "scripts": {

    "dev": "turbo dev",

    "build": "turbo build",

    "lint": "turbo lint",

    "db:generate": "turbo run db:generate",

    "db:push": "turbo run db:push",

    "db:migrate": "turbo run db:migrate",

    "db:studio": "turbo run db:studio",

    "db:test": "turbo run db:test"

  }

}

```

---

## Shared test script (`packages/db/scripts/test-database.ts`)

```ts

import "dotenv/config";

import prisma from "../src/client";

async function testDatabase() {

  console.log("🔍 Testing Prisma Postgres connection...\n");

  try {

    console.log("✅ Connected to database!");

    console.log("\n📝 Creating a test user...");

    const newUser = await prisma.user.create({

      data: {

        email: "demo@example.com",

        name: "Demo User",

      },

    });

    console.log("✅ Created user:", newUser);

    console.log("\n📋 Fetching all users...");

    const allUsers = await prisma.user.findMany();

    console.log(`✅ Found ${allUsers.length} user(s):`);

    allUsers.forEach((user) => {

      console.log(`   - ${user.name} (${user.email})`);

    });

    console.log("\n🎉 All tests passed! Your database is working.\n");

  } catch (error) {

    console.error("❌ Error:", error);

    process.exit(1);

  } finally {

    await prisma.$disconnect();

  }

}

testDatabase();

```

---

## Using Prisma in apps (example: `apps/web` Next.js)

In any app, add a dependency on `@repo/db` (workspace):

```json

{

  "dependencies": {

    "@repo/db": "*"

  }

}

```

Then in server-side code:

```ts

import { prisma } from "@repo/db";

import { NextResponse } from "next/server";

export async function GET() {

  try {

    const users = await prisma.user.findMany();

    return NextResponse.json(users);

  } catch (e) {

    console.error(e);

    return NextResponse.json({ error: "Failed to fetch users" }, { status: 500 });

  }

}

```

---

## Complete setup workflow

1. **Create Turborepo** (or use existing):

   ```npm

   npx create-turbo@latest

   ```

2. **Add `packages/db`**, install Prisma v7 deps.

3. **Initialize Prisma in `packages/db`**:

   ```bash

   cd packages/db

   npx prisma init

   ```

4. **Update `prisma.config.ts`** to include `import "dotenv/config"`.

5. **Update schema** with Prisma v7 generator + output.

6. **Create `src/client.ts`** singleton and export via `src/index.ts`.

7. **Wire Turbo tasks** in `turbo.json`.

8. **Add `.env`** at root **and/or** `packages/db/.env`.

9. **Push schema**:

   ```bash

   npm run db:push

   ```

10. **Test**:

    ```bash

    npm run db:test

    ```

11. **Start dev**:

    ```bash

    npm run dev

    ```

---

## AI Model verification checklist

Before generating any code, verify:

1. `provider = "prisma-client"`?

2. `output   = "../src/generated/prisma"` present?

3. All Prisma files in `packages/db`?

4. Client imports from `../generated/prisma/client` (or via `@repo/db`)?

5. `import "dotenv/config"` in `packages/db/prisma.config.ts`?

6. Turbo tasks depend on `db:generate`?

7. `DATABASE_URL` listed in `globalEnv`?

8. All DB ops wrapped in try/catch?

9. Test script exists in `packages/db/scripts/test-database.ts`?

No exceptions. If any check fails, STOP and FIX.

---

## AI MODEL RESPONSE TEMPLATE (UPDATED FOR TURBOREPO + PRISMA v7)

When asked about implementing Prisma v7 inside a Turborepo monorepo (with any framework such as Next.js, Node, etc.), you MUST:

1. **Assume Prisma lives in a shared package**

   - Always place schema, config, and migrations in `packages/db`.

   - Never suggest adding Prisma directly into an app unless the user explicitly says they don’t want a shared package.

2. **Use only Prisma v7 generator patterns**

   - The schema MUST include:

     ```prisma

     generator client {

       provider = "prisma-client"

       output   = "./generated/prisma"

     }

     ```

   - Never use `prisma-client-js`.

3. **Use correct import paths for custom output**

   - Any PrismaClient import MUST come from the generated output:

     ```ts

     import { PrismaClient } from "./generated/prisma/client";

     ```

   - If importing from apps, you MUST import via the package boundary:

     ```ts

     import { prisma } from "@repo/db";

     ```

   - Never import from `@prisma/client` in this setup.

4. **Always include a shared singleton client in `packages/db`**

   - Provide a `packages/db/src/client.ts` with global caching for dev hot-reload.

   - If Accelerate is requested or implied, use `$extends(withAccelerate())`.

   - If Accelerate is not requested, omit it.

5. **Always load environment variables properly**

   - `packages/db/prisma.config.ts` MUST start with `import "dotenv/config"`.

   - Use `process.env.DATABASE_URL` in runtime code.

   - Remind users that `.env` should exist at root and/or `packages/db`.

6. **Always wire Turbo dependencies**

   - Turbo tasks `dev` and `build` MUST depend on `^db:generate`.

   - `DATABASE_URL` MUST be listed in `globalEnv` to ensure correct task hashing.

7. **Provide correct repo-level scripts**

   - Root scripts should proxy to Turbo (`turbo run db:*`).

   - The Prisma package `packages/db` should own `db:generate`, `db:migrate`, `db:studio`, and `db:test`.

8. **Include a real verification step**

   - Provide (or reference) `packages/db/scripts/test-database.ts`.

   - Ensure it imports dotenv and disconnects Prisma on completion.

9. **Use safe runtime patterns**

   - All DB calls in apps MUST be wrapped in try/catch.

   - In Next.js App Router examples, use server-only imports and return `NextResponse`.

10. **Self-verify before replying**

- Re-check all items in the “AI Model verification checklist.”

- If any item is missing or incorrect, STOP and FIX before responding.

Remember: There are NO exceptions to these rules. Every requirement is mandatory for a correct Turborepo + Prisma v7 setup.

Run the application locally:

1. Generate the Prisma Client:

npx turbo db:generate

2. View your database in Prisma Studio:

bunx turbo db:studio
Bash
pnpm dlx turbo db:studio
Bash
yarn dlx turbo db:studio
Bash
npx turbo db:studio

Prisma Studio opens at localhost:5555 where you can inspect your User table and see the test user stored in your database.

Prisma Studio opens at localhost:5555 where you can inspect your User table and see the test user stored in your database.

Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu