Integrate Prisma Postgres with Clerk
Before you start
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.
Create a new Next.js project
Create a new Next.js project using the following command:
npx create-next-app clerk-prisma-example --typescript --eslint --tailwind --use-npm --no-src-dir --app --import-alias "@/*"
Navigate to the project directory and install the required dependencies:
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 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 to require authentication for every route.
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.
Run the following command to start a local Prisma Postgres database:
npx prisma dev
Initialize Prisma in your project:
npx prisma init --output ../app/generated/prisma
After initializing Prisma, your environment variable file should have the following values:
DATABASE_URL=PRISMA_POSTGRES_CONNECTION_STRING
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY
CLERK_SECRET_KEY=YOUR_SECRET_KEY
You will find the file schema.prisma
in the prisma/
directory, this defines the database schema. Add to the schema a new table called UserMessage
with the columns user_id
, create_ts
, and message
. The user_id
column will be used to store the user's Clerk ID. You will need to change the provider from "prisma-client-js" to "prisma-client".
generator client {
// Change the provider from "prisma-client-js" to "prisma-client"
provider = "prisma-client"
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
}
Push the schema to the database
Run the following command to push the schema to the database:
npx prisma db push
Create a reusable Prisma Client instance
To be able to use the Prisma Client instance globally in your code, create a reusable Prisma Client instance in lib/prisma.ts
:
import { PrismaClient } from '../app/generated/prisma/client'
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
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 to obtain the user ID, which will be used to interact with the database.
'use server'
import { auth } from '@clerk/nextjs/server'
import prisma from '@/lib/prisma'
import { revalidatePath } from 'next/cache'
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,
},
})
revalidatePath('/')
}
export async function deleteUserMessage() {
const { userId } = await auth()
if (!userId) throw new Error('User not found')
await prisma.userMessage.deleteMany({
where: { user_id: userId },
})
revalidatePath('/')
}
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 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.
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 className="grid justify-center p-4">
<div className="w-full max-w-md space-y-6">
<h1 className="text-3xl font-bold text-center">Prisma + Clerk Example</h1>
{existingMessage ? (
<div className="space-y-4 text-center">
<p className="bg-neutral-800 text-white p-3 rounded">{existingMessage.message}</p>
<form action={deleteUserMessage}>
<button className="bg-red-500 text-white px-4 py-2 rounded w-full">
Delete Message
</button>
</form>
</div>
) : (
<form action={createUserMessage} className="space-y-4">
<input
type="text"
name="message"
placeholder="Enter a message"
className="w-full p-2 border rounded"
required
/>
<button className="bg-blue-500 text-white px-4 py-2 rounded w-full">
Save Message
</button>
</form>
)}
</div>
</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.
Feedback
Last updated on