# Embedded Prisma Studio (with Next.js) (/docs/guides/integrations/embed-studio) > For the complete Prisma documentation index, see [llms.txt](https://www.prisma.io/docs/llms.txt). A markdown version of any docs page is available by appending `.md` to its URL. Learn how to embed Prisma Studio directly in your Next.js application for database management Location: Guides > Integrations > Embedded Prisma Studio (with Next.js) > [!NOTE] > This guide uses Prisma ORM 7 > > The commands and code on this page target Prisma ORM 7, which remains fully supported. To start a new Prisma ORM 8 project, see [Create a new app with PostgreSQL](https://www.prisma.io/docs/prisma-orm/quickstart/postgresql); to add Prisma ORM 8 to an existing app, see [Add Prisma ORM to an existing PostgreSQL database](https://www.prisma.io/docs/prisma-orm/add-to-existing-project/postgresql). A Prisma ORM 8 version of this guide is planned. Prisma Studio can be embedded directly into your Next.js application using the [`@prisma/studio-core`](https://www.npmjs.com/package/@prisma/studio-core) package. This guide walks you through the setup so you can manage your database from within your app instead of running Prisma Studio separately. After completing the guide, you'll have a Next.js app with Prisma Studio embedded, allowing you to browse and edit your database directly from your application interface: ![Prisma Studio embedded in Next.js app](https://www.prisma.io/img/guides/embedded-studio.gif) Embedding Prisma Studio can be useful in scenarios such as: * Building a quick admin dashboard for editing data * Supporting multi-tenant applications where each user has their own database * Giving users a UI to view and edit their own data > [!NOTE] > [**Embeddable Prisma Studio**](https://www.prisma.io/docs/studio/integrations/embedding) is *free* and licensed under Apache 2.0. > > ✔️ Free to use in production > ⚠️ Prisma branding must remain visible and unchanged > 🔐 To remove branding or learn about upcoming partner-only features, reach out at [partnerships@prisma.io](mailto\:partnerships@prisma.io) > > Currently, Embedded Prisma Studio supports **PostgreSQL, SQLite, and MySQL** databases. ## Prerequisites [#prerequisites] * [Node.js 20+](https://nodejs.org) * Basic knowledge of React and Next.js * A database (PostgreSQL, SQLite, or MySQL) ## 1. Setting up Next.js [#1-setting-up-nextjs] First, create a new Next.js project from the directory where you want to build your app: #### bun ```bash bunx create-next-app@latest nextjs-studio-embed ``` #### pnpm ```bash pnpm dlx create-next-app@latest nextjs-studio-embed ``` #### yarn ```bash yarn dlx create-next-app@latest nextjs-studio-embed ``` #### npm ```bash npx create-next-app@latest nextjs-studio-embed ``` You will be prompted to answer a few questions about your project. Select all of the defaults. > [!NOTE] > For reference, those are: > > * TypeScript > * ESLint > * Tailwind CSS > * No `src` directory > * App Router > * Turbopack > * Select default import alias Then, navigate to the project directory: ```bash cd nextjs-studio-embed ``` ## 2. Setting up Prisma ORM and Prisma Postgres [#2-setting-up-prisma-orm-and-prisma-postgres] ### 2.1. Install Prisma dependencies [#21-install-prisma-dependencies] Install the required Prisma packages: ### Prisma Postgres (PostgreSQL) [#prisma-postgres-postgresql] #### bun ```bash bun add prisma@prev tsx @types/pg --dev bun add @prisma/extension-accelerate @prisma/client@7 @prisma/adapter-pg dotenv pg ``` #### pnpm ```bash pnpm add prisma@prev tsx @types/pg --save-dev pnpm add @prisma/extension-accelerate @prisma/client@7 @prisma/adapter-pg dotenv pg ``` #### yarn ```bash yarn add prisma@prev tsx @types/pg --dev yarn add @prisma/extension-accelerate @prisma/client@7 @prisma/adapter-pg dotenv pg ``` #### npm ```bash npm install prisma@prev tsx @types/pg --save-dev npm install @prisma/extension-accelerate @prisma/client@7 @prisma/adapter-pg dotenv pg ``` ### SQLite [#sqlite] #### bun ```bash bun add prisma@prev tsx --dev bun add @prisma/client@7 @prisma/adapter-sqlite dotenv better-sqlite3 ``` #### pnpm ```bash pnpm add prisma@prev tsx --save-dev pnpm add @prisma/client@7 @prisma/adapter-sqlite dotenv better-sqlite3 ``` #### yarn ```bash yarn add prisma@prev tsx --dev yarn add @prisma/client@7 @prisma/adapter-sqlite dotenv better-sqlite3 ``` #### npm ```bash npm install prisma@prev tsx --save-dev npm install @prisma/client@7 @prisma/adapter-sqlite dotenv better-sqlite3 ``` ### MySQL [#mysql] #### bun ```bash bun add prisma@prev tsx @types/mysql2 --dev bun add @prisma/client@7 @prisma/adapter-mysql dotenv mysql2 ``` #### pnpm ```bash pnpm add prisma@prev tsx @types/mysql2 --save-dev pnpm add @prisma/client@7 @prisma/adapter-mysql dotenv mysql2 ``` #### yarn ```bash yarn add prisma@prev tsx @types/mysql2 --dev yarn add @prisma/client@7 @prisma/adapter-mysql dotenv mysql2 ``` #### npm ```bash npm install prisma@prev tsx @types/mysql2 --save-dev npm install @prisma/client@7 @prisma/adapter-mysql dotenv mysql2 ``` > [!NOTE] > For more information, see [Database drivers](https://www.prisma.io/docs/orm/v7/core-concepts/supported-databases/database-drivers). ### 2.2. Initialize Prisma with Prisma Postgres [#22-initialize-prisma-with-prisma-postgres] Initialize Prisma in your project: ### Prisma Postgres (PostgreSQL) [#prisma-postgres-postgresql-1] #### bun ```bash bunx --bun prisma init --output ../app/generated/prisma ``` #### pnpm ```bash pnpm prisma init --output ../app/generated/prisma ``` #### yarn ```bash yarn prisma init --output ../app/generated/prisma ``` #### npm ```bash npx prisma init --output ../app/generated/prisma ``` ### SQLite [#sqlite-1] #### bun ```bash bunx --bun prisma init --datasource-provider sqlite --output ../app/generated/prisma ``` #### pnpm ```bash pnpm prisma init --datasource-provider sqlite --output ../app/generated/prisma ``` #### yarn ```bash yarn prisma init --datasource-provider sqlite --output ../app/generated/prisma ``` #### npm ```bash npx prisma init --datasource-provider sqlite --output ../app/generated/prisma ``` ### MySQL [#mysql-1] #### bun ```bash bunx --bun prisma init --datasource-provider mysql --output ../app/generated/prisma ``` #### pnpm ```bash pnpm prisma init --datasource-provider mysql --output ../app/generated/prisma ``` #### yarn ```bash yarn prisma init --datasource-provider mysql --output ../app/generated/prisma ``` #### npm ```bash npx prisma init --datasource-provider mysql --output ../app/generated/prisma ``` > [!NOTE] > `prisma init` creates the Prisma scaffolding and a local `DATABASE_URL`. If you choose Prisma Postgres below, create a database in the next step and replace that value with a direct `postgres://...` connection string. The `prisma init` command creates: * A `prisma/` directory with your `schema.prisma` file * A `prisma.config.ts` file for configuring Prisma * A `.env` file with your `DATABASE_URL` * An output directory at `app/generated/prisma` for the Prisma Client If you're using Prisma Postgres, create a database and replace the generated `DATABASE_URL` in your `.env` file with the `postgres://...` connection string from the CLI output: #### bun ```bash bunx create-db ``` #### pnpm ```bash pnpm dlx create-db ``` #### yarn ```bash yarn dlx create-db ``` #### npm ```bash npx create-db ``` ### 2.3. Define your database schema [#23-define-your-database-schema] Open `prisma/schema.prisma` and replace the content with: ```prisma title="prisma/schema.prisma" generator client { provider = "prisma-client" output = "../app/generated/prisma" } datasource db { provider = "postgresql" // this will change depending on the --datasource-provider flag used in the init command } // [!code ++] model User { // [!code ++] id Int @id @default(autoincrement()) // [!code ++] name String // [!code ++] email String @unique // [!code ++] posts Post[] // [!code ++] } // [!code ++] // [!code ++] model Post { // [!code ++] id Int @id @default(autoincrement()) // [!code ++] title String // [!code ++] content String? // [!code ++] published Boolean @default(false) // [!code ++] authorId Int // [!code ++] author User @relation(fields: [authorId], references: [id]) // [!code ++] createdAt DateTime @default(now()) // [!code ++] } // [!code ++] // [!code ++] ``` ### 2.4 Add `dotenv` to `prisma.config.ts` [#24-add-dotenv-to-prismaconfigts] To get access to the variables in the `.env` file, they can either be loaded by your runtime, or by using `dotenv`. Include an import for `dotenv` at the top of the `prisma.config.ts` ```ts import "dotenv/config"; // [!code ++] import { defineConfig, env } from "prisma/config"; export default defineConfig({ schema: "prisma/schema.prisma", migrations: { path: "prisma/migrations", }, datasource: { url: env("DATABASE_URL"), }, }); ``` ### 2.5. Apply the schema to your database [#25-apply-the-schema-to-your-database] Generate the Prisma Client and apply the schema: #### bun ```bash bunx prisma migrate dev --name init ``` #### pnpm ```bash pnpm prisma migrate dev --name init ``` #### yarn ```bash yarn prisma migrate dev --name init ``` #### npm ```bash npx prisma migrate dev --name init ``` #### bun ```bash bunx prisma generate ``` #### pnpm ```bash pnpm prisma generate ``` #### yarn ```bash yarn prisma generate ``` #### npm ```bash npx prisma generate ``` This creates the tables in your Prisma Postgres database and generates the Prisma Client. > [!NOTE] > If you are using SQLite or MySQL, this creates the tables in your database and generates the Prisma Client. ### 2.6. Seed your database (optional) [#26-seed-your-database-optional] Create a seed file to add some sample data. Create a `seed.ts` file in the `prisma` folder and add the following code: #### Prisma Postgres (PostgreSQL) ```typescript title="prisma/seed.ts" import { PrismaClient } from "../app/generated/prisma/client"; import { PrismaPg } from "@prisma/adapter-pg"; const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL!, }); const prisma = new PrismaClient({ adapter, }); async function main() { // Create users const user1 = await prisma.user.create({ data: { name: "Alice Johnson", email: "alice@example.com", }, }); const user2 = await prisma.user.create({ data: { name: "Bob Smith", email: "bob@example.com", }, }); // Create posts await prisma.post.create({ data: { title: "Getting Started with Next.js", content: "Next.js is a powerful React framework...", published: true, authorId: user1.id, }, }); await prisma.post.create({ data: { title: "Database Management with Prisma", content: "Prisma makes database management easy...", published: false, authorId: user2.id, }, }); console.log("Database seeded successfully!"); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); }); ``` #### SQLite ```typescript title="prisma/seed.ts" import { PrismaClient } from "../app/generated/prisma/client"; import { PrismaSQLite } from "@prisma/adapter-sqlite"; const adapter = new PrismaSQLite({ connectionString: process.env.DATABASE_URL!, }); const prisma = new PrismaClient({ adapter, }); async function main() { // Create users const user1 = await prisma.user.create({ data: { name: "Alice Johnson", email: "alice@example.com", }, }); const user2 = await prisma.user.create({ data: { name: "Bob Smith", email: "bob@example.com", }, }); // Create posts await prisma.post.create({ data: { title: "Getting Started with Next.js", content: "Next.js is a powerful React framework...", published: true, authorId: user1.id, }, }); await prisma.post.create({ data: { title: "Database Management with Prisma", content: "Prisma makes database management easy...", published: false, authorId: user2.id, }, }); console.log("Database seeded successfully!"); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); }); ``` #### MySQL ```typescript title="prisma/seed.ts" import { PrismaClient } from "../app/generated/prisma/client"; import { PrismaMySQL } from "@prisma/adapter-mysql"; const adapter = new PrismaMySQL({ connectionString: process.env.DATABASE_URL!, }); const prisma = new PrismaClient({ adapter, }); async function main() { // Create users const user1 = await prisma.user.create({ data: { name: "Alice Johnson", email: "alice@example.com", }, }); const user2 = await prisma.user.create({ data: { name: "Bob Smith", email: "bob@example.com", }, }); // Create posts await prisma.post.create({ data: { title: "Getting Started with Next.js", content: "Next.js is a powerful React framework...", published: true, authorId: user1.id, }, }); await prisma.post.create({ data: { title: "Database Management with Prisma", content: "Prisma makes database management easy...", published: false, authorId: user2.id, }, }); console.log("Database seeded successfully!"); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); }); ``` Add a seed script to your `prisma.config.ts`: #### Prisma Postgres (PostgreSQL) ```ts title="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("DIRECT_URL"), }, }); ``` #### SQLite ```ts title="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"), }, }); ``` #### MySQL ```ts title="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 script: #### bun ```bash bunx prisma db seed ``` #### pnpm ```bash pnpm prisma db seed ``` #### yarn ```bash yarn prisma db seed ``` #### npm ```bash npx prisma db seed ``` ## 3. Setting up the embedded Prisma Studio in your app [#3-setting-up-the-embedded-prisma-studio-in-your-app] Now that you have Prisma ORM and Prisma Postgres set up, you can embed Prisma Studio in your Next.js app. ### 3.1. Install the Prisma Studio Core package [#31-install-the-prisma-studio-core-package] Install the [`@prisma/studio-core` package](https://www.npmjs.com/package/@prisma/studio-core) that provides the embeddable components: #### bun ```bash bun add @prisma/studio-core ``` #### pnpm ```bash pnpm add @prisma/studio-core ``` #### yarn ```bash yarn add @prisma/studio-core ``` #### npm ```bash npm install @prisma/studio-core ``` > [!NOTE] > If you encounter a dependency resolution error while installing `@prisma/studio-core`, you can force the install with: > > > > > #### bun > ```bash > bun add @prisma/studio-core --force > ``` > > > #### pnpm > ```bash > pnpm add @prisma/studio-core --force > ``` > > > #### yarn > ```bash > yarn add @prisma/studio-core --force > ``` > > > #### npm > ```bash > npm install @prisma/studio-core --force > ``` > > > > If you are using yarn, pnpm, or another package manager, use the equivalent flag for your tool. The `@prisma/studio-core` provides `Studio`, a React component which renders Prisma Studio for your database. The `Studio` component accepts an *executor* which accesses a custom endpoint in your backend. The backend uses your API key to identify the correct Prisma Postgres instance and sends the SQL query to it. ### 3.2. Create a Studio wrapper component [#32-create-a-studio-wrapper-component] Create a `components` folder and add a new file called `StudioWrapper.tsx`. This file will wrap the Studio component and provide a consistent layout: ```tsx title="components/StudioWrapper.tsx" "use client"; import "@prisma/studio-core/ui/index.css"; import { ReactNode } from "react"; interface StudioWrapperProps { children: ReactNode; } export default function StudioWrapper({ children }: StudioWrapperProps) { return (

Database Studio

Powered by Prisma Studio
{children}
); } ``` ### 3.3. Create an API endpoint to send the SQL queries to Prisma Studio [#33-create-an-api-endpoint-to-send-the-sql-queries-to-prisma-studio] Next, set up a backend endpoint that Prisma Studio can communicate with. This endpoint receives SQL queries from the embedded Studio UI, forwards them to your Prisma Postgres database, and then returns the results (or errors) back to the frontend. > [!NOTE] > If you are using SQLite or MySQL, you can still embed Studio, but your `/api/studio` implementation needs to use the correct executor for your database. To do this, create a new folder called `api` inside the `app` directory. Inside it, add a `studio` folder with a `route.ts` file. This file will handle all requests sent to `/api/studio` and act as the bridge between the Studio component in your frontend and the database in your backend: #### PostgreSQL ```typescript title="app/api/studio/route.ts" import "dotenv/config"; import { createPrismaPostgresHttpClient } from "@prisma/studio-core/data/ppg"; import { serializeError } from "@prisma/studio-core/data/bff"; const CORS_HEADERS = { "Access-Control-Allow-Origin": "*", // Change to your domain in production "Access-Control-Allow-Methods": "GET, POST, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization", }; // Use dynamic rendering for database operations export const dynamic = "force-dynamic"; export async function GET() { return Response.json({ message: "Studio API endpoint is running" }, { headers: CORS_HEADERS }); } export async function POST(request: Request) { try { const body = await request.json(); const query = body.query; if (!query) { return Response.json([serializeError(new Error("Query is required"))], { status: 400, headers: CORS_HEADERS, }); } const url = process.env.DATABASE_URL; if (!url) { const message = "❌ Environment variable DATABASE_URL is missing."; return Response.json([serializeError(new Error(message))], { status: 500, headers: CORS_HEADERS, }); } const [error, results] = await createPrismaPostgresHttpClient({ url, }).execute(query); if (error) { return Response.json([serializeError(error)], { headers: CORS_HEADERS, }); } return Response.json([null, results], { headers: CORS_HEADERS }); } catch (err) { return Response.json([serializeError(err)], { status: 400, headers: CORS_HEADERS, }); } } // Handle preflight requests for CORS export async function OPTIONS() { return new Response(null, { status: 204, headers: CORS_HEADERS }); } ``` #### SQLite ```typescript title="app/api/studio/route.ts" import "dotenv/config"; import { createNodeSQLiteExecutor } from "@prisma/studio-core/data/node-sqlite"; import { serializeError } from "@prisma/studio-core/data/bff"; import DatabaseSync from "better-sqlite3"; const CORS_HEADERS = { "Access-Control-Allow-Origin": "*", // Change to your domain in production "Access-Control-Allow-Methods": "GET, POST, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization", }; // Use dynamic rendering for database operations export const dynamic = "force-dynamic"; export async function GET() { return Response.json({ message: "Studio API endpoint is running" }, { headers: CORS_HEADERS }); } export async function POST(request: Request) { try { const body = await request.json(); const query = body.query; if (!query) { return Response.json([serializeError(new Error("Query is required"))], { status: 400, headers: CORS_HEADERS, }); } const url = process.env.DATABASE_URL; if (!url) { const message = "❌ Environment variable DATABASE_URL is missing."; return Response.json([serializeError(new Error(message))], { status: 500, headers: CORS_HEADERS, }); } const dbPath = url.replace("file:", ""); const database = new DatabaseSync(dbPath); const [error, results] = await createNodeSQLiteExecutor(database).execute(query); if (error) { return Response.json([serializeError(error)], { headers: CORS_HEADERS, }); } return Response.json([null, results], { headers: CORS_HEADERS }); } catch (err) { return Response.json([serializeError(err)], { status: 400, headers: CORS_HEADERS, }); } } // Handle preflight requests for CORS export async function OPTIONS() { return new Response(null, { status: 204, headers: CORS_HEADERS }); } ``` #### MySQL ```typescript title="app/api/studio/route.ts" import "dotenv/config"; import { createMySQL2Executor } from "@prisma/studio-core/data/mysql2"; import { serializeError } from "@prisma/studio-core/data/bff"; import mysql from "mysql2/promise"; const CORS_HEADERS = { "Access-Control-Allow-Origin": "*", // Change to your domain in production "Access-Control-Allow-Methods": "GET, POST, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization", }; // Use dynamic rendering for database operations export const dynamic = "force-dynamic"; export async function GET() { return Response.json({ message: "Studio API endpoint is running" }, { headers: CORS_HEADERS }); } export async function POST(request: Request) { try { const body = await request.json(); const query = body.query; if (!query) { return Response.json([serializeError(new Error("Query is required"))], { status: 400, headers: CORS_HEADERS, }); } const url = process.env.DATABASE_URL; if (!url) { const message = "❌ Environment variable DATABASE_URL is missing."; return Response.json([serializeError(new Error(message))], { status: 500, headers: CORS_HEADERS, }); } const pool = mysql.createPool(url); const [error, results] = await createMySQL2Executor(pool).execute(query); if (error) { return Response.json([serializeError(error)], { headers: CORS_HEADERS, }); } return Response.json([null, results], { headers: CORS_HEADERS }); } catch (err) { return Response.json([serializeError(err)], { status: 400, headers: CORS_HEADERS, }); } } // Handle preflight requests for CORS export async function OPTIONS() { return new Response(null, { status: 204, headers: CORS_HEADERS }); } ``` ### 3.4. Create the main Studio page [#34-create-the-main-studio-page] Open the `app/page.tsx` file and replace the existing code to render the embedded Studio with the following: #### PostgreSQL ```tsx title="app/page.tsx" "use client"; import dynamic from "next/dynamic"; import { createPostgresAdapter } from "@prisma/studio-core/data/postgres-core"; import { createStudioBFFClient } from "@prisma/studio-core/data/bff"; import { useMemo, Suspense } from "react"; import StudioWrapper from "@/components/StudioWrapper"; // Dynamically import Studio with no SSR to avoid hydration issues const Studio = dynamic(() => import("@prisma/studio-core/ui").then((mod) => mod.Studio), { ssr: false, }); // Loading component const StudioLoading = () => (

Loading Studio...

); // Client-only Studio component const ClientOnlyStudio = () => { const adapter = useMemo(() => { // Create the HTTP client that communicates with our API endpoint const executor = createStudioBFFClient({ url: "/api/studio", }); // Create the Postgres adapter using the executor return createPostgresAdapter({ executor }); }, []); return ; }; export default function App() { return ( }> ); } ``` #### SQLite ```tsx title="app/page.tsx" "use client"; import dynamic from "next/dynamic"; import { createSQLiteAdapter } from "@prisma/studio-core/data/sqlite-core"; import { createStudioBFFClient } from "@prisma/studio-core/data/bff"; import { useMemo, Suspense } from "react"; import StudioWrapper from "@/components/StudioWrapper"; // Dynamically import Studio with no SSR to avoid hydration issues const Studio = dynamic(() => import("@prisma/studio-core/ui").then((mod) => mod.Studio), { ssr: false, }); // Loading component const StudioLoading = () => (

Loading Studio...

); // Client-only Studio component const ClientOnlyStudio = () => { const adapter = useMemo(() => { // Create the HTTP client that communicates with our API endpoint const executor = createStudioBFFClient({ url: "/api/studio", }); // Create the SQLite adapter using the executor return createSQLiteAdapter({ executor }); }, []); return ; }; export default function App() { return ( }> ); } ``` #### MySQL ```tsx title="app/page.tsx" "use client"; import dynamic from "next/dynamic"; import { createMySQLAdapter } from "@prisma/studio-core/data/mysql-core"; import { createStudioBFFClient } from "@prisma/studio-core/data/bff"; import { useMemo, Suspense } from "react"; import StudioWrapper from "@/components/StudioWrapper"; // Dynamically import Studio with no SSR to avoid hydration issues const Studio = dynamic(() => import("@prisma/studio-core/ui").then((mod) => mod.Studio), { ssr: false, }); // Loading component const StudioLoading = () => (

Loading Studio...

); // Client-only Studio component const ClientOnlyStudio = () => { const adapter = useMemo(() => { // Create the HTTP client that communicates with our API endpoint const executor = createStudioBFFClient({ url: "/api/studio", }); // Create the MySQL adapter using the executor return createMySQLAdapter({ executor }); }, []); return ; }; export default function App() { return ( }> ); } ``` ### 3.5. Start your development server and test the embedded Studio [#35-start-your-development-server-and-test-the-embedded-studio] Start your Next.js development server: #### bun ```bash bun run dev ``` #### pnpm ```bash pnpm run dev ``` #### yarn ```bash yarn dev ``` #### npm ```bash npm run dev ``` Open your browser and go to `http://localhost:3000`. You should now see Prisma Studio running inside your application: ![Prisma Studio embedded in Next.js app](https://www.prisma.io/img/guides/embedded-studio.gif) Here's what to look for: 1. **Prisma Studio interface**: The full Prisma Studio UI should render within your app layout. 2. **Your data**: The `User` and `Post` tables you defined (plus any seeded data) should appear. 3. **Interactive features**: * Browse and filter records in your tables * Edit values inline by double-clicking cells * Add new records using the "Add record" button * Delete records you no longer need * Explore relationships by navigating between related tables Verify whether everything works by testing the basics: * Click on different tables to confirm your data loads. * Update a record to check that changes are saved. * Add a new record and confirm it appears instantly. * Try filtering data to make sure queries run correctly. * Navigate through relationships (for example, view a user's posts) to confirm associations work. Once these actions work as expected, your embedded Prisma Studio is set up and connected to your database. ## Next steps [#next-steps] At this point you have Prisma Studio running inside your Next.js application and connected to your database. You can browse, edit, and manage your data without leaving your app. To make this setup production-ready, consider these improvements: 1. **Add authentication**: Currently, anyone who can open your app has access to Prisma Studio. [Add user authentication](https://www.prisma.io/docs/studio/integrations/embedding#adding-user-authentication) and only allow specific roles (for example, admins) to use the embedded Studio. You can do this by checking authentication tokens in your `/api/studio` endpoint before running queries. 2. **Use environment-specific configuration**: In development you may want a test database, while in production you'll need a separate live database. Update your `.env` file to use different `DATABASE_URL` values for each environment, and confirm that your `/api/studio` endpoint is reading the correct one. 3. **Apply custom styling**: The Studio component ships with a default look. Pass in [your own theme](https://www.prisma.io/docs/studio/integrations/embedding#custom-styling) and adjust colors, typography, or branding to match the rest of your application. This helps Studio feel like a native part of your app rather than a standalone tool. By adding authentication, environment-specific settings, and styling, you move from a working demo to a production setup. For more patterns and examples, see the [Prisma Studio Core demo repository](https://github.com/prisma/studio-core-demo), which includes an alternative implementation using Hono.js and React. If you prefer a guided walkthrough, watch the YouTube video: [\*\*Use Prisma Studio in Your Own Applications \*\*](https://www.youtube.com/watch?v=Up5vG2YHPvc). ## Related pages - [`AI SDK (with Next.js)`](https://www.prisma.io/docs/guides/integrations/ai-sdk): Build a chat application with AI SDK, Prisma ORM, and Next.js that stores chat sessions and messages in Prisma Postgres. - [`Datadog`](https://www.prisma.io/docs/guides/integrations/datadog): Learn how to configure Datadog tracing for a Prisma ORM project. Capture spans for every query using the @prisma/instrumentation package, dd-trace, and view them in Datadog - [`GitHub Actions`](https://www.prisma.io/docs/guides/integrations/github-actions): Provision a Prisma Postgres database for every pull request with GitHub Actions and the Prisma CLI, apply your migrations and seed data to it, and delete it when the pull request closes. - [`Permit.io`](https://www.prisma.io/docs/guides/integrations/permit-io): Learn how to implement access control with Prisma ORM with Permit.io - [`pgfence`](https://www.prisma.io/docs/guides/integrations/pgfence): Analyze Prisma Migrate SQL files for dangerous lock patterns, risk levels, and safe rewrite recipes before deploying to production