From 6595e2e85c0fd2c99a1fc1653750e8784e410b5a Mon Sep 17 00:00:00 2001 From: Aidan McAlister Date: Fri, 1 Aug 2025 11:38:31 -0400 Subject: [PATCH 1/5] Added Prisma Postgres --- .../databases/prisma-postgres.mdx | 196 ++++++++++++++++++ docs/integrations/overview.mdx | 6 + docs/manifest.json | 4 + 3 files changed, 206 insertions(+) create mode 100644 docs/integrations/databases/prisma-postgres.mdx diff --git a/docs/integrations/databases/prisma-postgres.mdx b/docs/integrations/databases/prisma-postgres.mdx new file mode 100644 index 0000000000..bf485afc32 --- /dev/null +++ b/docs/integrations/databases/prisma-postgres.mdx @@ -0,0 +1,196 @@ +--- +title: Integrate Prisma Postgres with Clerk +description: Learn how to integrate Clerk into your Prisma Postgres application. +--- + + + +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 + + 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 ( +
+

Prisma + Clerk Example

+ {existingMessage ? ( +
+

{existingMessage.message}

+
+ +
+
+ ) : ( +
+ + +
+ )} +
+ ) + } + ``` + + ## 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. +
diff --git a/docs/integrations/overview.mdx b/docs/integrations/overview.mdx index 4125ba5ade..def2b5aeef 100644 --- a/docs/integrations/overview.mdx +++ b/docs/integrations/overview.mdx @@ -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. + - {} + + --- + - [Shopify](/docs/integrations/shopify) - Use Clerk as your preferred Auth solution for your Shopify store. - {} diff --git a/docs/manifest.json b/docs/manifest.json index 1502e97b12..3d2ea6f2d4 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -3508,6 +3508,10 @@ { "title": "Neon", "href": "/docs/integrations/databases/neon" + }, + { + "title": "Prisma Postgres", + "href": "/docs/integrations/databases/prisma-postgres" } ] ] From b675dc06b759c9ec96deef37292aac47578d0372 Mon Sep 17 00:00:00 2001 From: Aidan McAlister Date: Tue, 16 Sep 2025 16:17:51 -0400 Subject: [PATCH 2/5] changes based on PR comments and latest Prisma updates --- .../databases/prisma-postgres.mdx | 151 +++++++++++------- 1 file changed, 89 insertions(+), 62 deletions(-) diff --git a/docs/integrations/databases/prisma-postgres.mdx b/docs/integrations/databases/prisma-postgres.mdx index bf485afc32..a38f98c89f 100644 --- a/docs/integrations/databases/prisma-postgres.mdx +++ b/docs/integrations/databases/prisma-postgres.mdx @@ -18,17 +18,20 @@ This tutorial shows you how to build a Next.js application with Clerk authentica ## 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 - ``` + 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 "@/*" + ``` + + 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 @@ -59,10 +62,17 @@ This tutorial shows you how to build a Next.js application with Clerk authentica 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 - ``` + Run the following command to start a local Prisma Postgres database: + + ```sh {{ filename: 'terminal' }} + npx prisma dev + ``` + + 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: @@ -72,48 +82,51 @@ This tutorial shows you how to build a Next.js application with Clerk authentica 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. + 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". + + ```prisma {{ filename: 'prisma/schema.prisma' }} + generator client { + // Change the provider from "prisma-client-js" to "prisma-client" + provider = "prisma-client" + output = "../app/generated/prisma" + } - ```prisma {{ filename: 'prisma/schema.prisma' }} - generator client { - provider = "prisma-client-js" - output = "../app/generated/prisma" - } + datasource db { + provider = "postgresql" + url = env("DATABASE_URL") + } - datasource db { - provider = "postgresql" - url = env("DATABASE_URL") - } + model UserMessage { + user_id String @id + create_ts DateTime @default(now()) + message String + } + ``` - model UserMessage { - user_id String @id - create_ts DateTime @default(now()) - message String - } - ``` + ## Push the schema to the database - 1. Create a reusable Prisma Client instance in `lib/prisma.ts`: + Run the following command to push the schema to the database: - ```typescript {{ filename: 'lib/prisma.ts' }} - import { PrismaClient } from '../app/generated/prisma' + ```sh {{ filename: 'terminal' }} + npx prisma db push + ``` - const globalForPrisma = globalThis as unknown as { - prisma: PrismaClient | undefined - } + ## Create a reusable Prisma Client instance - export const prisma = globalForPrisma.prisma ?? new PrismaClient() + To be able to use the Prisma Client instance globally in your code, create a reusable Prisma Client instance in `lib/prisma.ts`: - if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma + ```typescript {{ filename: 'lib/prisma.ts' }} + import { PrismaClient } from '../app/generated/prisma/client' - export default prisma - ``` + const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined + } - ## Push the schema to the database + export const prisma = globalForPrisma.prisma ?? new PrismaClient() - Run the following command to push the schema to the database: + if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma - ```sh {{ filename: 'terminal' }} - npx prisma db push + export default prisma ``` ## Create Server Actions to handle user interactions @@ -125,11 +138,11 @@ This tutorial shows you how to build a Next.js application with Clerk authentica 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: { @@ -137,15 +150,17 @@ This tutorial shows you how to build a Next.js application with Clerk authentica 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('/') } ``` @@ -170,21 +185,33 @@ This tutorial shows you how to build a Next.js application with Clerk authentica }) return ( -
-

Prisma + Clerk Example

- {existingMessage ? ( -
-

{existingMessage.message}

-
- +
+
+

Prisma + Clerk Example

+ {existingMessage ? ( +
+

{existingMessage.message}

+ + + +
+ ) : ( +
+ +
-
- ) : ( -
- - -
- )} + )} +
) } From f9247647947d76f14c4e334b880480565ebd5965 Mon Sep 17 00:00:00 2001 From: Aidan McAlister Date: Thu, 18 Sep 2025 17:50:12 -0400 Subject: [PATCH 3/5] highlighting adjusted --- docs/integrations/databases/prisma-postgres.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/integrations/databases/prisma-postgres.mdx b/docs/integrations/databases/prisma-postgres.mdx index a38f98c89f..5692ab061d 100644 --- a/docs/integrations/databases/prisma-postgres.mdx +++ b/docs/integrations/databases/prisma-postgres.mdx @@ -84,10 +84,10 @@ This tutorial shows you how to build a Next.js application with Clerk authentica 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". - ```prisma {{ filename: 'prisma/schema.prisma' }} + ```prisma {{ filename: 'prisma/schema.prisma', ins: [2], del: [3] }} generator client { - // Change the provider from "prisma-client-js" to "prisma-client" provider = "prisma-client" + provider = "prisma-client-js" output = "../app/generated/prisma" } From e2145ef5bf37c30e4ca9ab477edcb7c5acca6f78 Mon Sep 17 00:00:00 2001 From: Aidan McAlister Date: Fri, 19 Sep 2025 10:26:54 -0400 Subject: [PATCH 4/5] remove next app creation --- .../databases/prisma-postgres.mdx | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/docs/integrations/databases/prisma-postgres.mdx b/docs/integrations/databases/prisma-postgres.mdx index 5692ab061d..a107b211e3 100644 --- a/docs/integrations/databases/prisma-postgres.mdx +++ b/docs/integrations/databases/prisma-postgres.mdx @@ -5,6 +5,11 @@ description: Learn how to integrate Clerk into your Prisma Postgres application. -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. +Now that you've set up Clerk authentication in your Next.js application, let's add Prisma Postgres to store and manage user data. In this guide, you'll create a simple messaging app where users can store and manage their personal messages. - ## Create a new Next.js project + ## Integrate the Next.js Clerk SDK - Create a new Next.js project using the following command: + Follow the [Next.js quickstart](/docs/quickstarts/nextjs) to integrate the Clerk Next.js SDK into your application. - ```sh {{ filename: 'terminal' }} - npx create-next-app clerk-prisma-example --typescript --eslint --tailwind --use-npm --no-src-dir --app --import-alias "@/*" - ``` + ## Install Prisma - Navigate to the project directory and install the required dependencies: + Install Prisma and the Prisma Client: ```sh {{ filename: 'terminal' }} - cd clerk-prisma-example - npm install prisma --save-dev - npm install tsx --save-dev + npm install prisma 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. From 9458e9683e4233f7e33c9d37a7c679006e7861ef Mon Sep 17 00:00:00 2001 From: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> Date: Thu, 23 Oct 2025 18:53:05 -0400 Subject: [PATCH 5/5] docs review --- .../databases/prisma-postgres.mdx | 325 +++++++++++------- 1 file changed, 200 insertions(+), 125 deletions(-) diff --git a/docs/guides/development/integrations/databases/prisma-postgres.mdx b/docs/guides/development/integrations/databases/prisma-postgres.mdx index 5f9c4ff6ae..d663119e84 100644 --- a/docs/guides/development/integrations/databases/prisma-postgres.mdx +++ b/docs/guides/development/integrations/databases/prisma-postgres.mdx @@ -6,85 +6,65 @@ description: Learn how to integrate Clerk into your Prisma Postgres application. -Now that you've set up Clerk authentication in your Next.js application, let's add Prisma Postgres to store and manage user data. In this guide, you'll create a simple messaging app where users can store and manage their personal messages. +Integrating Prisma Postgres with Clerk gives you the benefits of using a Prisma Postgres database while leveraging Clerk's authentication, prebuilt components, and webhooks. This guide will show you how to create a simple blog application that allows users to create and read posts using Prisma Postgres and Clerk. This guide uses Next.js App Router but the same principles can be applied to other SDKs. - ## Integrate the Next.js Clerk SDK - - Follow the [Next.js quickstart](/docs/nextjs/getting-started/quickstart) to integrate the Clerk Next.js SDK into your application. - ## Install Prisma - Install Prisma and the Prisma Client: + Run the following command to install Prisma: ```sh {{ filename: 'terminal' }} npm install prisma tsx --save-dev - npm install @prisma/extension-accelerate ``` - ## Protect your application routes + ## Initialize Prisma - To ensure that only authenticated users can access your application, modify [`clerkMiddleware`](/docs/reference/nextjs/clerk-middleware) to require authentication for every route. + Run the following command to initialize Prisma: - ```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)(.*)', - ], - } + ```sh {{ filename: 'terminal' }} + npx prisma init --output ../app/generated/prisma ``` - ## Set up the application schema and database connection + This will: - Next, you'll need to initialize Prisma and set up a Prisma Postgres database. + - Create a new `prisma/` directory in your project, with a `schema.prisma` file inside of it. The `schema.prisma` file is where you will define your database models. + - Create a `prisma.config.ts` file in the root of your project. + - Update your `.env` file to include a `DATABASE_URL` environment variable, which is used to store your database connection string for your Prisma Postgres database. - Run the following command to start a local Prisma Postgres database: + ## Update the Prisma configuration - ```sh {{ filename: 'terminal' }} - npx prisma dev - ``` + Inside the `prisma.config.ts` file, add `import "dotenv/config";` so that it can load the `DATABASE_URL` environment variable from your `.env` file. - Initialize Prisma in your project: + ```ts {{ filename: 'prisma.config.ts', mark: [1] }} + import 'dotenv/config' + import { defineConfig, env } from 'prisma/config' - ```sh {{ filename: 'terminal' }} - npx prisma init --output ../app/generated/prisma + export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + engine: 'classic', + datasource: { + url: env('DATABASE_URL'), + }, + }) ``` - 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}} - ``` + ## Update the database schema - 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". + In the `prisma/schema.prisma` file, update the schema to include a new model called `Post` with the columns `id`, `title`, `content`, `published`, and `authorId`. The `id` column will be used as the post's primary key, and the `authorId` column will be used to store the user's Clerk ID. - ```prisma {{ filename: 'prisma/schema.prisma', ins: [2], del: [3] }} + ```prisma {{ filename: 'prisma/schema.prisma', mark: [[11, 17]] }} generator client { provider = "prisma-client" - provider = "prisma-client-js" output = "../app/generated/prisma" } @@ -93,16 +73,18 @@ Now that you've set up Clerk authentication in your Next.js application, let's a url = env("DATABASE_URL") } - model UserMessage { - user_id String @id - create_ts DateTime @default(now()) - message String + model Post { + id Int @id @default(autoincrement()) + title String + content String? + published Boolean @default(false) + authorId String } ``` ## Push the schema to the database - Run the following command to push the schema to the database: + Run the following command to push the updated schema to the database: ```sh {{ filename: 'terminal' }} npx prisma db push @@ -110,111 +92,204 @@ Now that you've set up Clerk authentication in your Next.js application, let's a ## 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`: + At the root of your project, create a folder called `lib`. Inside of it, create a new file called `prisma.ts` and add the following code to it. This will set up a single Prisma Client instance, which is used to interact with your database, and bind it to the global object so that only one instance of the client is created in your application. This helps resolve issues with hot reloading that can occur when using Prisma with Next.js in development mode. ```typescript {{ filename: 'lib/prisma.ts' }} - import { PrismaClient } from '../app/generated/prisma/client' + import { PrismaClient } from '@prisma/client' - const globalForPrisma = globalThis as unknown as { - prisma: PrismaClient | undefined - } + const prisma = new PrismaClient() - export const prisma = globalForPrisma.prisma ?? new PrismaClient() + const globalForPrisma = global as unknown as { prisma: typeof prisma } if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma export default prisma ``` - ## Create Server Actions to handle user interactions + ## Create the UI for the homepage - To handle form submissions for adding and deleting user messages, create two Server Actions in `app/actions.ts`. Use Clerk's [`auth()` helper](/docs/reference/nextjs/app-router/auth) to obtain the user ID, which will be used to interact with the database. + Now that all of the set up is complete, it's time to start building out your app. - ```typescript {{ filename: 'app/actions.ts' }} - 'use server' + Replace the contents of `app/page.tsx` with the following code. This page fetches all posts from your database and displays them on the homepage, showing the title and author ID for each post. It uses the [`prisma.post.findMany()`](https://www.prisma.io/docs/orm/reference/prisma-client-reference?utm_source=docs#findmany) method, which is a Prisma Client method that retrieves all records from the database. - import { auth } from '@clerk/nextjs/server' + ```tsx {{ filename: 'app/page.tsx' }} + import Link from 'next/link' 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, - }, - }) + export default async function Page() { + const posts = await prisma.post.findMany() // Query the `Post` model for all posts - 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 }, - }) + return ( +
+

Posts

+ +
+ {posts.map((post) => ( + + {post.title} + by {post.authorId} + + ))} +
- revalidatePath('/') + + Create New Post + +
+ ) } ``` - ## Create the UI for the Home Page + ## Create a new post - 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. + Create a new file called `app/posts/create/page.tsx` and add the following code to it. This page allows users to create new posts. It uses Clerk's [`auth`](/docs/reference/backend/types/auth-object) object to get the user's ID. - To retrieve the user's messages, use Clerk's [`auth()` helper](/docs/reference/nextjs/app-router/auth) to obtain the user's ID. Then, use this ID to query the database for the user's messages. + - If there is no user ID, the user is not signed in, so a sign in button is displayed. + - If the user is signed in, the "Create New Post" form is displayed. When the form is submitted, the `createPost()` function is called. This function creates a new post in the database using the [`prisma.post.create()`](https://www.prisma.io/docs/orm/reference/prisma-client-reference?utm_source=docs#create) method, which is a Prisma Client method that creates a new record in the database. - 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' + ```tsx {{ filename: 'app/posts/create/page.tsx' }} + import Form from 'next/form' import prisma from '@/lib/prisma' + import { redirect } from 'next/navigation' + import { SignInButton, useAuth } from '@clerk/nextjs' + import { revalidatePath } from 'next/cache' import { auth } from '@clerk/nextjs/server' - export default async function Home() { + export default async function NewPost() { + // The `Auth` object gives you access to properties like `userId` + // Accessing the `Auth` object differs depending on the SDK you're using + // https://clerk.com/docs/reference/backend/types/auth-object#how-to-access-the-auth-object const { userId } = await auth() - if (!userId) throw new Error('User not found') - const existingMessage = await prisma.userMessage.findUnique({ - where: { user_id: userId }, + + // Protect this page from unauthenticated users + if (!userId) { + return ( +
+

You must be signed in to create a post.

+ + + +
+ ) + } + + async function createPost(formData: FormData) { + 'use server' + + // Type check + if (!userId) return + + const title = formData.get('title') as string + const content = formData.get('content') as string + + await prisma.post.create({ + data: { + title, + content, + authorId: userId, + }, + }) + + revalidatePath('/') + redirect('/') + } + + return ( +
+

Create New Post

+
+
+ + +
+
+ +