Skip to content
Open
196 changes: 196 additions & 0 deletions docs/integrations/databases/prisma-postgres.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
---
title: Integrate Prisma Postgres with Clerk
description: Learn how to integrate Clerk into your Prisma Postgres application.
---

<TutorialHero
beforeYouStart={[
{
title: "Set up a Clerk application",
link: "/docs/quickstarts/setup-clerk",
icon: "clerk",
}
]}
/>

This tutorial shows you how to build a Next.js application with Clerk authentication and Prisma Postgres. You'll create a simple messaging app where users can store and manage their personal messages using Prisma ORM for database operations.

<Steps>
## Create a new Next.js project

1. Create a new Next.js project using the following command:
```sh {{ filename: 'terminal' }}
npx create-next-app clerk-prisma-example --typescript --eslint --tailwind --use-npm --no-src-dir --app --import-alias "@/*"
```
1. Navigate to the project directory and install the required dependencies:
```sh {{ filename: 'terminal' }}
cd clerk-prisma-example
npm install prisma --save-dev
npm install tsx --save-dev
npm install @prisma/extension-accelerate
```

## Integrate the Next.js Clerk SDK

Follow the [Next.js quickstart](/docs/quickstarts/nextjs) to integrate the Clerk Next.js SDK into your application.

## Protect your application routes

To ensure that only authenticated users can access your application, modify [`clerkMiddleware`](/docs/references/nextjs/clerk-middleware) to require authentication for every route.

```typescript {{ filename: 'middleware.ts', mark: [[3, 5]] }}
import { clerkMiddleware } from '@clerk/nextjs/server'

export default clerkMiddleware(async (auth) => {
await auth.protect()
})

export const config = {
matcher: [
// Skip Next.js internals and all static files, unless found in search params
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
// Always run for API routes
'/(api|trpc)(.*)',
],
}
```

## Set up the application schema and database connection

Next, you'll need to initialize Prisma and set up a Prisma Postgres database.

1. Initialize Prisma in your project:
```sh {{ filename: 'terminal' }}
npx prisma init --output ../app/generated/prisma
```

After initializing Prisma, your environment variable file should have the following values:

```env {{ filename: '.env' }}
DATABASE_URL=PRISMA_POSTGRES_CONNECTION_STRING
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY={{pub_key}}
CLERK_SECRET_KEY={{secret}}
```

1. Create a `schema.prisma` file in the `prisma/` directory that defines the database schema. The schema will include a table called `user_messages` with the columns `user_id`, `create_ts`, and `message`. The `user_id` column will be used to store the user's Clerk ID.

```prisma {{ filename: 'prisma/schema.prisma' }}
generator client {
provider = "prisma-client-js"
output = "../app/generated/prisma"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model UserMessage {
user_id String @id
create_ts DateTime @default(now())
message String
}
```

1. Create a reusable Prisma Client instance in `lib/prisma.ts`:

```typescript {{ filename: 'lib/prisma.ts' }}
import { PrismaClient } from '../app/generated/prisma'

const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}

export const prisma = globalForPrisma.prisma ?? new PrismaClient()

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma

export default prisma
```

## Push the schema to the database

Run the following command to push the schema to the database:

```sh {{ filename: 'terminal' }}
npx prisma db push
```

## Create Server Actions to handle user interactions

To handle form submissions for adding and deleting user messages, create two Server Actions in `app/actions.ts`. Use Clerk's [`auth()` helper](/docs/references/nextjs/auth) to obtain the user ID, which will be used to interact with the database.

```typescript {{ filename: 'app/actions.ts' }}
'use server'

import { auth } from '@clerk/nextjs/server'
import prisma from '@/lib/prisma'

export async function createUserMessage(formData: FormData) {
const { userId } = await auth()
if (!userId) throw new Error('User not found')

const message = formData.get('message') as string
await prisma.userMessage.create({
data: {
user_id: userId,
message,
},
})
}

export async function deleteUserMessage() {
const { userId } = await auth()
if (!userId) throw new Error('User not found')

await prisma.userMessage.deleteMany({
where: { user_id: userId },
})
}
```

## Create the UI for the Home Page

In your `app/page.tsx` file, add the following code to create the UI for the home page. If a message exists, the user can view and delete it; otherwise, they can add a new message.

To retrieve the user's messages, use Clerk's [`auth()` helper](/docs/references/nextjs/auth) to obtain the user's ID. Then, use this ID to query the database for the user's messages.

To enable the user to delete or add a message, use the `deleteUserMessage()` and `createUserMessage()` actions created in the previous step.

```tsx {{ filename: 'app/page.tsx' }}
import { createUserMessage, deleteUserMessage } from './actions'
import prisma from '@/lib/prisma'
import { auth } from '@clerk/nextjs/server'

export default async function Home() {
const { userId } = await auth()
if (!userId) throw new Error('User not found')
const existingMessage = await prisma.userMessage.findUnique({
where: { user_id: userId },
})

return (
<main>
<h1>Prisma + Clerk Example</h1>
{existingMessage ? (
<div>
<p>{existingMessage.message}</p>
<form action={deleteUserMessage}>
<button>Delete Message</button>
</form>
</div>
) : (
<form action={createUserMessage}>
<input type="text" name="message" placeholder="Enter a message" />
<button>Save Message</button>
</form>
)}
</main>
)
}
```

## Run the application

Run your application and open `http://localhost:3000` in your browser. Sign in with Clerk and interact with the application to add and delete user messages.
</Steps>
6 changes: 6 additions & 0 deletions docs/integrations/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ description: Learn about the available integrations with Clerk.

---

- [Prisma Postgres](/docs/integrations/databases/prisma-postgres)
- Build applications using Prisma Postgres with Clerk as your authentication provider.
- {<svg width="58" height="72" viewBox="0 0 58 72" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M0.522473 45.0933C-0.184191 46.246 -0.173254 47.7004 0.550665 48.8423L13.6534 69.5114C14.5038 70.8529 16.1429 71.4646 17.6642 71.0082L55.4756 59.6648C57.539 59.0457 58.5772 56.7439 57.6753 54.7874L33.3684 2.06007C32.183 -0.511323 28.6095 -0.722394 27.1296 1.69157L0.522473 45.0933ZM32.7225 14.1141C32.2059 12.9187 30.4565 13.1028 30.2001 14.3796L20.842 60.9749C20.6447 61.9574 21.5646 62.7964 22.5248 62.5098L48.6494 54.7114C49.4119 54.4838 49.8047 53.6415 49.4891 52.9111L32.7225 14.1141Z" fill="white"/></svg>}

---

- [Shopify](/docs/integrations/shopify)
- Use Clerk as your preferred Auth solution for your Shopify store.
- {<svg width="32" height="32" viewBox="0 0 292 292" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M223.774 57.34c-.201-1.46-1.48-2.268-2.537-2.357-1.055-.088-23.383-1.743-23.383-1.743s-15.507-15.395-17.209-17.099c-1.703-1.703-5.029-1.185-6.32-.805-.19.056-3.388 1.043-8.678 2.68-5.18-14.906-14.322-28.604-30.405-28.604-.444 0-.901.018-1.358.044C129.31 3.407 123.644.779 118.75.779c-37.465 0-55.364 46.835-60.976 70.635-14.558 4.511-24.9 7.718-26.221 8.133-8.126 2.549-8.383 2.805-9.45 10.462C21.3 95.806.038 260.235.038 260.235l165.678 31.042 89.77-19.42S223.973 58.8 223.775 57.34zM156.49 40.848l-14.019 4.339c.005-.988.01-1.96.01-3.023 0-9.264-1.286-16.723-3.349-22.636 8.287 1.04 13.806 10.469 17.358 21.32zm-27.638-19.483c2.304 5.773 3.802 14.058 3.802 25.238 0 .572-.005 1.095-.01 1.624-9.117 2.824-19.024 5.89-28.953 8.966 5.575-21.516 16.025-31.908 25.161-35.828zm-11.131-10.537c1.617 0 3.246.549 4.805 1.622-12.007 5.65-24.877 19.88-30.312 48.297l-22.886 7.088C75.694 46.16 90.81 10.828 117.72 10.828z" fill="#95BF46"/><path d="M221.237 54.983c-1.055-.088-23.383-1.743-23.383-1.743s-15.507-15.395-17.209-17.099c-.637-.634-1.496-.959-2.394-1.099l-12.527 256.233 89.762-19.418S223.972 58.8 223.774 57.34c-.201-1.46-1.48-2.268-2.537-2.357" fill="#5E8E3E"/><path d="M135.242 104.585l-11.069 32.926s-9.698-5.176-21.586-5.176c-17.428 0-18.305 10.937-18.305 13.693 0 15.038 39.2 20.8 39.2 56.024 0 27.713-17.577 45.558-41.277 45.558-28.44 0-42.984-17.7-42.984-17.7l7.615-25.16s14.95 12.835 27.565 12.835c8.243 0 11.596-6.49 11.596-11.232 0-19.616-32.16-20.491-32.16-52.724 0-27.129 19.472-53.382 58.778-53.382 15.145 0 22.627 4.338 22.627 4.338" fill="#FFF"/></svg>}
Expand Down
4 changes: 4 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3838,6 +3838,10 @@
{
"title": "Neon",
"href": "/docs/integrations/databases/neon"
},
{
"title": "Prisma Postgres",
"href": "/docs/integrations/databases/prisma-postgres"
}
]
]
Expand Down