diff --git a/apps/docs/content/docs/(index)/getting-started.mdx b/apps/docs/content/docs/(index)/getting-started.mdx index 287bc1b163..11cf24d101 100644 --- a/apps/docs/content/docs/(index)/getting-started.mdx +++ b/apps/docs/content/docs/(index)/getting-started.mdx @@ -1,34 +1,33 @@ --- -title: Choose a setup path -description: Choose the fastest path to start using Prisma ORM, Prisma Postgres, or Prisma Compute in a new or existing TypeScript project. +title: Prisma 7 setup paths +description: Choose the fastest path to start using Prisma ORM 7, Prisma Postgres, or Prisma Compute in a new or existing TypeScript project. url: /getting-started -metaTitle: Prisma getting started -metaDescription: Choose the fastest path to start using Prisma ORM, Prisma Postgres, or Prisma Compute in a new or existing TypeScript project. +metaTitle: Prisma 7 getting started +metaDescription: Choose the fastest Prisma 7 setup path. Quickstarts and existing-project guides for Prisma ORM 7, Prisma Postgres, and Prisma Compute, plus an agent prompt. --- -Prisma gives you a few starting points depending on what you want to do first: deploy an app, create a database, use Prisma ORM locally, or add Prisma to an existing project. +Prisma 7 is the current generally available release of Prisma ORM, and `npx prisma@latest init` installs it. This page collects the Prisma 7 starting points: start a new project, add Prisma to an existing one, then deploy. -## Choose your path +:::note -### Deploy a full-stack app with a database +Starting a new project? [Prisma Next](/next) is the recommended path for new apps. It is the next major version of Prisma ORM (soon Prisma 8), available now in Early Access. The [getting started page](/) covers it. -Use this path if you want to deploy a TypeScript app with Prisma Compute and run it alongside Prisma Postgres. +::: -- [Deploy your first app](/prisma-compute/deploy) on [Prisma Compute](/compute), currently in Public Beta, to run it next to your Prisma Postgres database +## Start a new project -### Start a new project +The recommended path is the [Quickstart with Prisma Postgres](/prisma-orm/quickstart/prisma-postgres): it provisions a managed PostgreSQL database for you and gets you from install to first query in about five minutes. -Use this path if you are creating a new app and want to set up Prisma from the beginning. +Working with a specific database instead? -- [Quickstart with Prisma Postgres](/prisma-orm/quickstart/prisma-postgres) for the fastest end-to-end path with a managed PostgreSQL database -- [Quickstart with PostgreSQL](/prisma-orm/quickstart/postgresql) if you want to work with PostgreSQL +- [Quickstart with PostgreSQL](/prisma-orm/quickstart/postgresql) - [Quickstart with SQLite](/prisma-orm/quickstart/sqlite) for a lightweight local setup -- [Quickstart with MySQL](/prisma-orm/quickstart/mysql) if your application uses MySQL -- [Quickstart with MongoDB](/prisma-orm/quickstart/mongodb) if your application uses MongoDB +- [Quickstart with MySQL](/prisma-orm/quickstart/mysql) +- [Quickstart with MongoDB](/prisma-orm/quickstart/mongodb) -### Add Prisma to an existing project +## Add Prisma to an existing project -Use this path if you already have an application or database and want to add Prisma ORM. +Use these guides if you already have an application or database and want to add Prisma ORM: - [Add Prisma ORM to an existing PostgreSQL project](/prisma-orm/add-to-existing-project/postgresql) - [Add Prisma ORM to an existing MySQL project](/prisma-orm/add-to-existing-project/mysql) @@ -36,36 +35,44 @@ Use this path if you already have an application or database and want to add Pri - [Add Prisma ORM to an existing MongoDB project](/prisma-orm/add-to-existing-project/mongodb) - [Add Prisma ORM to an existing Prisma Postgres project](/prisma-orm/add-to-existing-project/prisma-postgres) -## What you will do +## Deploy to Prisma Compute -Most Prisma ORM and Prisma Postgres guides follow the same basic flow: +Once your app runs locally, [Prisma Compute](/compute) (currently in Public Beta) runs it next to your Prisma Postgres database: -1. Define a database connection and data model in your [Prisma schema](/orm/prisma-schema/overview). -2. Set up your database, either with [Prisma Postgres](/postgres) or another supported database. -3. Install Prisma CLI and [Prisma Client](/orm/prisma-client). -4. Run `prisma generate` to create a type-safe client for your schema. -5. Create or introspect your database. -6. Start sending queries from your application. +1. Sign in with `npx @prisma/cli@latest auth login`. +2. Run `npx @prisma/cli@latest app deploy` from your app directory to get a live URL, adding `--env .env` so environment variables like `DATABASE_URL` reach the deployment. +3. `--env .env` applies to that one deployment. Persist variables for future deploys with `npx @prisma/cli@latest project env add --file .env --role production`; see [environment variables](/compute/environment-variables). +4. Keep deploying from the CLI, or [connect GitHub](/compute/github) to deploy on push. -Then you can deploy your app to [Prisma Compute](/compute). The flow is: +The [deploy guide](/prisma-compute/deploy) covers build settings, frameworks, and troubleshooting. -1. Sign in with `npx @prisma/cli@latest auth login`. -2. Run `npx @prisma/cli@latest app deploy` from your app directory to get a live URL. -3. Connect your app to [Prisma Postgres](/postgres) or another database with [environment variables](/compute/environment-variables). -4. Redeploy to apply the environment variables. -5. Keep deploying from the CLI, or [connect GitHub](/compute/github) to deploy on push. +## Use with your agent + +To hand the full Prisma 7 stack to your coding agent, copy this prompt. The commands below install Prisma 7, not Prisma Next: + + + +```text +Set up the Prisma 7 stack: Prisma ORM 7, Prisma Postgres, and Prisma Compute. + +If I have not told you which framework template to use, stop and ask. + +1. Scaffold a new app non-interactively: `npx create-prisma@latest --name my-app --template [next|hono|nuxt|astro|nest|svelte|tanstack-start|elysia|turborepo] --provider postgresql --no-deploy`. Or add Prisma 7 to an existing app with `npx prisma@latest init --db`, which provisions a Prisma Postgres database; before that, check `npx @prisma/cli@latest auth whoami` and stop and ask me to run `auth login` if I am not signed in, because provisioning can open a browser. +2. From the project directory, define a small schema in `prisma/schema.prisma`, then run `npx prisma migrate dev --name init` and `npx prisma generate`. If migrate dev asks to reset the database, stop and ask me first. +3. Update the seed and app code to query the schema, and verify locally with the dev script. +4. Deploy with Prisma Compute: check `npx @prisma/cli@latest auth whoami` first. If I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`, because that step opens a browser. Then run `npx @prisma/cli@latest app deploy --create-project my-app --env .env` so DATABASE_URL reaches the deployment, and verify the deployed URL with curl. + +Current docs: https://www.prisma.io/docs/getting-started.md and https://www.prisma.io/docs/llms.txt. +``` + + ## Next steps After setup, these pages are usually the next ones people need: - [Prisma Client overview](/orm/prisma-client) -- [Generating Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client) - [Prisma Migrate getting started](/orm/prisma-migrate/getting-started) - [Prisma schema overview](/orm/prisma-schema/overview) - -## If you want the fastest path - -- [Quickstart with Prisma Postgres](/prisma-orm/quickstart/prisma-postgres) if you want Prisma to provision the database layer for you -- [Open Prisma Studio](/studio/getting-started) if you want to inspect and edit data visually once your app is running -- [Review pricing](https://www.prisma.io/pricing) if you're evaluating Prisma Postgres or other paid workflows for a team +- [Open Prisma Studio](/studio/getting-started) to inspect and edit data visually +- [Review pricing](https://www.prisma.io/pricing) if you're evaluating Prisma Postgres for a team diff --git a/apps/docs/content/docs/(index)/index.mdx b/apps/docs/content/docs/(index)/index.mdx index 7cd04a6092..d097f23090 100644 --- a/apps/docs/content/docs/(index)/index.mdx +++ b/apps/docs/content/docs/(index)/index.mdx @@ -1,66 +1,199 @@ --- -title: Introduction to Prisma -description: Build, deploy, and iterate on TypeScript applications with Prisma ORM, Prisma Postgres, and Prisma Compute. +title: Get started with Prisma +description: Scaffold an app with Prisma Next, create or connect Prisma Postgres, and deploy on Prisma Compute. One integrated TypeScript stack, from first query to live URL. url: / metaTitle: Get started with Prisma -metaDescription: "Build, deploy, and iterate on TypeScript applications with Prisma ORM, Prisma Postgres, and Prisma Compute." +metaDescription: Scaffold an app with Prisma Next, create or connect Prisma Postgres, and deploy it on Prisma Compute. Quick setup, guided setup, and agent prompts. +hideSidebar: true +full: true --- -[**Prisma ORM**](/orm) is an open-source ORM that provides fast, type-safe access to Postgres, MySQL, SQLite, and other databases, and runs smoothly across Node.js, Bun, and Deno. + + + Prisma is a complete TypeScript stack for building with data: [Prisma ORM](/orm) to model and query it, [Prisma Postgres](/postgres) to store it, and [Prisma Compute](/compute) to run your app next to it. Start new projects with [Prisma Next](/next), the next major version of the ORM and soon Prisma 8: one scaffold command wires up all three, for you or your coding agent. + + + }> + Deploy and host your app. Public Beta. + + }> + Model and query your data. The next Prisma ORM, soon Prisma 8. Early Access. + + + Store your data, provisioned during setup. + + + + +The tutorial's journey, condensed: hand the prompt to your coding agent, or run the CLI steps yourself. + + + +```text +Create a new [framework] application with Prisma Next, seed it, and run it locally. -```npm -npx prisma@latest init +If I have not told you which framework, stop and ask before scaffolding. Valid --template values: next, hono, nuxt, astro, nest, svelte, tanstack-start, elysia. + +1. Scaffold the app: `npx create-prisma@next create my-app --template [framework] --provider postgres --prisma-postgres --yes`. The `--prisma-postgres` flag provisions a Prisma Postgres database. If I give you a connection string, pass `--database-url ""` instead of `--prisma-postgres`. +2. From the project directory, apply the starter contract and seed: `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts`, `src/prisma/users.ts`, and any route files that query `db.orm`, then rerun. +3. Edit the starter contract under `src/prisma/` into a small schema for my use case, then run `npm run contract:emit` and plan and apply the migration: `npx prisma-next migration plan`, then `npx prisma-next migrate --yes`. Migration planning diffs the emitted contract, so the emit step is required. +4. Update the seed script and the app routes to query the new schema, start `npm run dev` in the background, and verify with a request against the running app. For the `nest` template, if routes return 500s with `reading 'findAll'` in the logs, add explicit `@Inject()` tokens as shown in https://www.prisma.io/docs/guides/next/frameworks/nestjs.md. +5. Deploy with Prisma Compute. First apply the framework's deploy requirement from the guide at https://www.prisma.io/docs/guides/next/frameworks/[guide].md, where [guide] is the template name except: template `next` → guide `nextjs`, `nest` → `nestjs`, `svelte` → `sveltekit`. The requirements: Next.js needs `output: "standalone"` in `next.config.ts` (without it the deployed app returns 504s), TanStack Start needs the nitro build plugin, Astro needs the `@astrojs/node` adapter plus `--env HOST=0.0.0.0`, and Elysia needs `--framework bun --entry src/index.ts` on the deploy command. If the template is `svelte`, skip this step; Compute does not support SvelteKit yet. Check `npx @prisma/cli@latest auth whoami`. If I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`, because that step opens a browser. Then run `npx @prisma/cli@latest app deploy --create-project my-app --env .env` so DATABASE_URL reaches the deployment, and verify the deployed URL with curl. + +Use the installed Prisma Next skills and the current Prisma docs: https://www.prisma.io/docs/llms.txt (append `.md` to any docs URL for a markdown version). ``` -[**Prisma Postgres**](/postgres) is a fully managed PostgreSQL database that scales to zero, integrates with [Prisma ORM](/orm) and [Prisma Studio](/studio), and includes a [generous free tier](https://www.prisma.io/pricing). + + + + + + + + + + + + + + + + + +If you're using Express or another Node.js server, follow the [existing-project path](/next/add-to-existing-project/postgresql) instead. + + + + + + + } /> + } /> + + + -```npm -npx create-db@latest + + +{/* ModalRow keeps the collapsed paths mounted in the served HTML for crawlers + and agents; opening them in a modal never shifts the layout below. */} + +} +> + +}> + +```text +Add Prisma Next to this existing project. + +This flow is for PostgreSQL. If the project uses MongoDB, follow https://www.prisma.io/docs/next/add-to-existing-project/mongodb.md instead; for other databases, stop and tell me. + +1. Run `npx prisma-next@latest init`. It writes `prisma-next.config.ts`, a starter contract and `db.ts` under `src/prisma/`, and installs Prisma Next skills for you. +2. Set `DATABASE_URL` in `.env` to my database. If I did not give you one, create a Prisma Postgres database with `npx create-db@latest`, put its connection string in `.env`, and show me the claim URL it prints so I can keep the database. +3. If the database already has tables, infer the contract from it: `npx prisma-next contract infer`, then `npx prisma-next contract emit`, then sign it with `npx prisma-next db sign`. If the database is empty, keep the starter contract and run `npx prisma-next db init`. +4. Write one query with the generated `db` client in an existing code path, run it, and show me the returned rows. + +Follow https://www.prisma.io/docs/next/add-to-existing-project/postgresql.md and the installed Prisma Next skills. ``` -[**Prisma Compute**](/compute) is TypeScript app hosting for running your app next to your Prisma Postgres database. It is currently in [Public Beta](/console/more/feature-maturity#public-beta). Deploy Next.js, Hono, TanStack Start, and Bun apps, with an isolated preview for every branch. + + +}> + +```text +Create a new [framework] application with Prisma Next against my existing PostgreSQL database. -```npm -npx @prisma/cli@latest app deploy +If I have not given you a connection string, stop and ask; do not invent one. Valid --template values: next, hono, nuxt, astro, nest, svelte, tanstack-start, elysia. + +1. Scaffold: `npx create-prisma@next create my-app --template [framework] --provider postgres --database-url "" --yes`. +2. From the project directory: `npm run db:init`, then `npm run db:seed`, then start `npm run dev` in the background and verify the sample query returns data. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts`, `src/prisma/users.ts`, and any route files that query `db.orm`, then rerun. +3. Evolve the starter contract under `src/prisma/` into my schema, then run `npm run contract:emit`, `npx prisma-next migration plan`, and `npx prisma-next migrate --yes`. + +Do not provision any hosted database. Use the installed Prisma Next skills and https://www.prisma.io/docs/llms.txt for current docs. ``` -:::note + -Curious what's next? [Prisma Next](/next) is the next major version of Prisma ORM, available now in Early Access. Explore the new developer experience whenever you're ready. +}> -::: +```text +Add Prisma ORM 7 to this project with my existing database. - - } - > - Deploy and run your TypeScript app next to your database, with a live - preview for every branch. - - - - - } - > - Get started with your favorite framework and Prisma Postgres as the - database. - - +If I have not given you a database connection string and none exists in the project, stop and ask. + +1. Run `npx prisma@latest init` (Prisma 7). For an existing database, set DATABASE_URL in `.env` and introspect it with `npx prisma db pull`; for a new schema, define models in `prisma/schema.prisma` and run `npx prisma migrate dev --name init`. If migrate dev asks to reset the database, stop and ask me first. +2. Install the driver adapter for the database (Prisma 7 requires one), e.g. `npm install @prisma/adapter-pg` for PostgreSQL, and pass it to `new PrismaClient({ adapter })`. Generate the client with `npx prisma generate` and write one query in an existing code path. +3. Run the query (e.g. with `npx tsx`) and show me the output, the schema, and the query you added. + +Current docs: https://www.prisma.io/docs/orm.md and https://www.prisma.io/docs/llms.txt. +``` + + + +}> + +```text +Create a Prisma Postgres database for this project. + +1. Run `npx create-db@latest`. It creates a temporary Prisma Postgres database without an account and prints a connection string plus a claim URL. +2. Put the connection string in `.env` as DATABASE_URL and wire it into whichever of Prisma ORM, Kysely, Drizzle, TypeORM, or node-postgres the project already uses (detect it from package.json; if none, ask me). Verify the connection with one trivial query such as `select 1`. +3. Remind me to open the claim URL to keep the database in my Prisma workspace. + +Current docs: https://www.prisma.io/docs/postgres.md. +``` + + + +}> + +```text +Deploy this app to Prisma Compute using `npx @prisma/cli@latest`. + +Compute supports Next.js (with `output: "standalone"` in its config), Nuxt, Astro, Hono, NestJS, TanStack Start, and plain Bun servers; for a Bun or Elysia server pass `--framework bun --entry `. If the app is none of these, stop and tell me. + +1. Confirm I am signed in with `npx @prisma/cli@latest auth whoami`; if not, stop and ask me to run `npx @prisma/cli@latest auth login`. +2. Run `npx @prisma/cli@latest app deploy` from the project directory. If the app reads env vars from `.env` (like DATABASE_URL), add `--env .env`. If deploy fails with `PROJECT_SETUP_REQUIRED` (the directory is not pinned to a project yet), rerun with `--create-project `, or `--project ` for an existing project. Add `--db` only if it needs a brand-new database; Compute then provisions Prisma Postgres and wires the connection string. +3. Fetch the deployed URL with curl and confirm the app responds. If it does not, read `npx @prisma/cli@latest app logs` briefly (it streams; stop it after reading). + +Current docs: https://www.prisma.io/docs/prisma-compute/deploy.md. +``` + + + +If you're using MongoDB, follow the [MongoDB quickstart](/next/quickstart/mongodb) or [add Prisma Next to an existing MongoDB app](/next/add-to-existing-project/mongodb). If you work with [Kysely](/prisma-postgres/quickstart/kysely), [Drizzle](/prisma-postgres/quickstart/drizzle-orm), or [TypeORM](/prisma-postgres/quickstart/typeorm), the Prisma Postgres quickstarts cover those tools. + + + + + + + + + } /> + } /> + } /> + } /> + } /> + } /> + + + diff --git a/apps/docs/content/docs/(index)/meta.json b/apps/docs/content/docs/(index)/meta.json index c7375e791a..01ed38e66b 100644 --- a/apps/docs/content/docs/(index)/meta.json +++ b/apps/docs/content/docs/(index)/meta.json @@ -4,18 +4,19 @@ "pages": [ "---Getting Started---", "index", - "getting-started", - "---Get started with Prisma Next---", + "---Prisma Next (recommended)---", "next/index", "next/getting-started", - "---Prisma Next---", + "next/full-stack-tutorial", "next/quickstart", "next/add-to-existing-project", - "---Prisma ORM---", - "...prisma-orm", + "next/prisma-postgres", "---Prisma Postgres---", "...prisma-postgres", "---Prisma Compute---", - "...prisma-compute" + "...prisma-compute", + "---Prisma 7---", + "getting-started", + "...prisma-orm" ] } diff --git a/apps/docs/content/docs/(index)/next/full-stack-tutorial.mdx b/apps/docs/content/docs/(index)/next/full-stack-tutorial.mdx new file mode 100644 index 0000000000..8a79bd98e3 --- /dev/null +++ b/apps/docs/content/docs/(index)/next/full-stack-tutorial.mdx @@ -0,0 +1,134 @@ +--- +title: Build and deploy the full Prisma stack +description: A single tutorial from empty directory to live URL, with Prisma Next, Prisma Postgres, and Prisma Compute. +url: /next/full-stack-tutorial +metaTitle: "Tutorial: the full Prisma stack" +metaDescription: Scaffold an app with Prisma Next, provision Prisma Postgres, seed and query it, then deploy to Prisma Compute for a live URL. Every step verified. +badge: early-access +--- + +This tutorial takes you through the whole recommended stack in one sitting: scaffold an app with [Prisma Next](/next), store data in [Prisma Postgres](/postgres), query it over HTTP, and deploy to [Prisma Compute](/compute) for a live URL. About 15 minutes. + +It uses the `hono` template so you get a small API you can verify with curl at every step. The same journey works for the other templates; the [framework guides](/guides/next) cover each one. + +## Prerequisites + +- Node.js 24 or later (or Bun) +- A [Prisma Data Platform account](https://pris.ly/pdp) for the deploy step, free to create +- No database needed: setup provisions Prisma Postgres for you + +## Use with your agent + +Prefer to delegate? This is the same journey as the prompt on the [getting started page](/), with the `hono` template chosen for you: + + + +```text +Create a new Hono API with Prisma Next, seed it, and deploy it to Prisma Compute. + +1. Scaffold: `npx create-prisma@next create my-app --template hono --provider postgres --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-app`, run `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun. +3. Start `npm run dev` in the background and verify `curl http://localhost:3000/users` returns the seeded users. +4. Deploy: check `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`. Then run `npx @prisma/cli@latest app deploy --create-project my-app --env .env` and verify the live URL's /users endpoint with curl. + +Use the installed Prisma Next skills. +``` + + + +## 1. Scaffold the app + +One command creates the app, wires up Prisma Next, and can provision the database: + +```npm +npx create-prisma@next create my-app --template hono --provider postgres +``` + +Pick **Prisma Postgres** at the database prompt to have a database created for you, or paste your own connection string. Then enter the project: + +```npm +cd my-app +``` + +The scaffold writes `DATABASE_URL` to `.env`, generates a Hono server in `src/index.ts` with `GET /` and `GET /users` routes, puts the Prisma Next setup under `src/prisma/`, and installs [Prisma Next skills](/ai/tools/skills) for your coding agent. If the database was provisioned without a signed-in CLI, `.env` also contains a `CLAIM_URL`; open it within 24 hours to claim the database into your account and keep it. + +## 2. Initialize and seed the database + +`db:init` applies the starter contract to Prisma Postgres and signs the database; `db:seed` inserts sample users: + +```npm +npm run db:init +npm run db:seed +``` + +```text no-copy +"summary": "Applied 5 operation(s) across 1 space(s), database signed" +Seeded 3 users. +``` + +:::note + +Seeing `Cannot read properties of undefined (reading 'where')`? The current template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun `db:seed`. + +::: + +## 3. Run it and query your data + +```npm +npm run dev +``` + +The server starts on port 3000 (set `PORT` if something else is already using it). Confirm the API serves the seeded rows from Prisma Postgres: + +```bash +curl http://localhost:3000/users +``` + +```json no-copy +[ + { "id": "1", "email": "alice@prisma.io", "username": "alice", "name": "Alice", "createdAt": "2026-07-27T13:31:56.993Z" }, + { "id": "2", "email": "bob@prisma.io", "username": "bob", "name": "Bob", "createdAt": "2026-07-27T13:31:57.021Z" }, + { "id": "3", "email": "carol@prisma.io", "username": "carol", "name": "Carol", "createdAt": "2026-07-27T13:31:57.049Z" } +] +``` + +The route handler in `src/index.ts` is ordinary Hono code calling an ordinary Prisma Next query. Change the starter contract in `src/prisma/` when you are ready to model your own data; the [fundamentals](/orm/next/fundamentals/reading-data) cover the query patterns. + +## 4. Deploy to Prisma Compute + +Sign in once (it opens your browser): + +```npm +npx @prisma/cli@latest auth login +``` + +Deploy from the project directory. The first deploy asks you to pick or create a project; pass `--create-project my-app` to skip the prompt (agents and CI need it, since there is no interactive picker). The `--env .env` flag passes your `DATABASE_URL` to the deployment, so the live API talks to the same database: + +```npm +npx @prisma/cli@latest app deploy --env .env +``` + +```text no-copy +First deploy of "my-app" -- promoting to production. +Building locally... + Built 0.9 MB +Uploading... +Deploying... +Live in 7.5s +https://.ewr.prisma.build +``` + +## 5. Verify the live URL + +```bash +curl https://.ewr.prisma.build/users +``` + +The same three users come back, now served from production next to your database. The first deploy pins the directory to your project in a gitignored `.prisma/local.json` and promotes to production automatically. + +## Next steps + +- [Pick your framework](/guides/next): the same journey for Next.js, Nuxt, Astro, NestJS, TanStack Start, and more. +- [Branching and previews](/compute/branching): every Git branch gets an isolated deployment. +- [Learn the fundamentals](/orm/next/fundamentals/reading-data): reading, writing, relations, and transactions. +- [Deploy on push](/compute/github): connect GitHub so every commit deploys itself. diff --git a/apps/docs/content/docs/(index)/next/getting-started.mdx b/apps/docs/content/docs/(index)/next/getting-started.mdx index c4adfa7ac8..ea935cc621 100644 --- a/apps/docs/content/docs/(index)/next/getting-started.mdx +++ b/apps/docs/content/docs/(index)/next/getting-started.mdx @@ -1,5 +1,5 @@ --- -title: Choose a setup path +title: Choose a Prisma Next setup path description: Choose the fastest path to try Prisma Next in a new or existing project. url: /next/getting-started metaTitle: Prisma Next getting started @@ -16,33 +16,38 @@ npx create-prisma@next ``` - }> - Create the app, choose PostgreSQL, initialize the database, seed data, and run the first query. + }> + The whole journey in one sitting: scaffold, Prisma Postgres, first query, and a Prisma Compute deploy. + + }> + Create the app, pick Prisma Postgres (provisioned for you) or your own PostgreSQL, seed data, and run the first query. }> Create the app, choose MongoDB, start or connect to MongoDB, seed data, and run the first query. -## Use Prisma Postgres + -```npm -npx create-prisma@next +```text +Create a new [framework] application with Prisma Next, seed it, and run it locally. + +If I have not told you which framework, stop and ask before scaffolding. Valid --template values: next, hono, nuxt, astro, nest, svelte, tanstack-start, elysia. + +1. Scaffold the app: `npx create-prisma@next create my-app --template [framework] --provider postgres --prisma-postgres --yes`. The `--prisma-postgres` flag provisions a Prisma Postgres database. If I give you a connection string, pass `--database-url ""` instead of `--prisma-postgres`. +2. From the project directory, apply the starter contract and seed: `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts`, `src/prisma/users.ts`, and any route files that query `db.orm`, then rerun. +3. Edit the starter contract under `src/prisma/` into a small schema for my use case, then run `npm run contract:emit` and plan and apply the migration: `npx prisma-next migration plan`, then `npx prisma-next migrate --yes`. Migration planning diffs the emitted contract, so the emit step is required. +4. Update the seed script and the app routes to query the new schema, start `npm run dev` in the background, and verify with a request against the running app. For the `nest` template, if routes return 500s with `reading 'findAll'` in the logs, add explicit `@Inject()` tokens as shown in https://www.prisma.io/docs/guides/next/frameworks/nestjs.md. + +Use the installed Prisma Next skills and the current Prisma docs: https://www.prisma.io/docs/llms.txt (append `.md` to any docs URL for a markdown version). ``` - - }> - Create a Prisma Next app and let setup provision Prisma Postgres for the first run. - - }> - Start from the command line when you want the Prisma Postgres path without browsing Console first. - - + ## Add to an existing project ```npm -npx prisma-next init +npx prisma-next@latest init ``` @@ -54,6 +59,23 @@ npx prisma-next init + + +```text +Add Prisma Next to this existing project. + +This flow is for PostgreSQL. If the project uses MongoDB, follow https://www.prisma.io/docs/next/add-to-existing-project/mongodb.md instead; for other databases, stop and tell me. + +1. Run `npx prisma-next@latest init`. It writes `prisma-next.config.ts`, a starter contract and `db.ts` under `src/prisma/`, and installs Prisma Next skills for you. +2. Set `DATABASE_URL` in `.env` to my database. If I did not give you one, create a Prisma Postgres database with `npx create-db@latest`, put its connection string in `.env`, and show me the claim URL it prints so I can keep the database. +3. If the database already has tables, infer the contract from it: `npx prisma-next contract infer`, then `npx prisma-next contract emit`, then sign it with `npx prisma-next db sign`. If the database is empty, keep the starter contract and run `npx prisma-next db init`. +4. Write one query with the generated `db` client in an existing code path, run it, and show me the returned rows. + +Follow https://www.prisma.io/docs/next/add-to-existing-project/postgresql.md and the installed Prisma Next skills. +``` + + + ## After setup - Use the generated app scripts for the first run. diff --git a/apps/docs/content/docs/(index)/next/index.mdx b/apps/docs/content/docs/(index)/next/index.mdx index 695e6c1002..8939130a15 100644 --- a/apps/docs/content/docs/(index)/next/index.mdx +++ b/apps/docs/content/docs/(index)/next/index.mdx @@ -3,8 +3,9 @@ title: Introduction to Prisma Next description: Prisma Next is the next major version of Prisma ORM, available in Early Access. url: /next metaTitle: Introduction to Prisma Next -metaDescription: Prisma Next is the next major version of Prisma ORM, available in Early Access. +metaDescription: Start here for Prisma Next, the Early Access rebuild of Prisma ORM. Quickstarts, framework guides, and agent prompts. badge: early-access +hideSidebar: true --- Prisma Next is a ground-up rebuild of Prisma ORM, covering the runtime, query APIs, migration flow, and project setup. @@ -17,7 +18,7 @@ If you want to stay on the current generally available version of Prisma ORM, yo ::: -Use Prisma Next when you want to try the new developer experience before it becomes the default Prisma ORM path. +Prisma Next is the recommended starting point for new projects: the new developer experience today, and the path to Prisma 8. ```npm npx create-prisma@next @@ -26,30 +27,52 @@ npx create-prisma@next Start with the setup page when you want a guided first run. - }> + }> + Scaffold, provision Prisma Postgres, query, and deploy to Prisma Compute in one sitting. + + }> Pick a new-project quickstart or add Prisma Next to an existing app. -## What you can try +## Use with your agent - - }> - Create a Prisma Next app, initialize the database, seed data, and run the first query. - - }> - Create a Prisma Next app with a local MongoDB replica set or your own MongoDB deployment. - - }> - Add Prisma Next to an existing PostgreSQL app with `prisma-next init`. - - }> - Add Prisma Next to an existing MongoDB app and model the collections you want to query first. - - }> - Create a Prisma Next app backed by Prisma Postgres. - - +Copy this prompt, replace the placeholders, and hand it to your coding agent. The scaffold installs [Prisma Next skills](/ai/tools/skills) into `.claude/skills/` and `.agents/skills/`: + + + +```text +Create a new [framework] application with Prisma Next, seed it, and run it locally. + +If I have not told you which framework, stop and ask before scaffolding. Valid --template values: next, hono, nuxt, astro, nest, svelte, tanstack-start, elysia. + +1. Scaffold the app: `npx create-prisma@next create my-app --template [framework] --provider postgres --prisma-postgres --yes`. The `--prisma-postgres` flag provisions a Prisma Postgres database. If I give you a connection string, pass `--database-url ""` instead of `--prisma-postgres`. +2. From the project directory, apply the starter contract and seed: `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts`, `src/prisma/users.ts`, and any route files that query `db.orm`, then rerun. +3. Edit the starter contract under `src/prisma/` into a small schema for my use case, then run `npm run contract:emit` and plan and apply the migration: `npx prisma-next migration plan`, then `npx prisma-next migrate --yes`. Migration planning diffs the emitted contract, so the emit step is required. +4. Update the seed script and the app routes to query the new schema, start `npm run dev` in the background, and verify with a request against the running app. For the `nest` template, if routes return 500s with `reading 'findAll'` in the logs, add explicit `@Inject()` tokens as shown in https://www.prisma.io/docs/guides/next/frameworks/nestjs.md. +5. Deploy with Prisma Compute. First apply the framework's deploy requirement from the guide at https://www.prisma.io/docs/guides/next/frameworks/[guide].md, where [guide] is the template name except: template `next` → guide `nextjs`, `nest` → `nestjs`, `svelte` → `sveltekit`. The requirements: Next.js needs `output: "standalone"` in `next.config.ts` (without it the deployed app returns 504s), TanStack Start needs the nitro build plugin, Astro needs the `@astrojs/node` adapter plus `--env HOST=0.0.0.0`, and Elysia needs `--framework bun --entry src/index.ts` on the deploy command. If the template is `svelte`, skip this step; Compute does not support SvelteKit yet. Check `npx @prisma/cli@latest auth whoami`. If I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`, because that step opens a browser. Then run `npx @prisma/cli@latest app deploy --create-project my-app --env .env` so DATABASE_URL reaches the deployment, and verify the deployed URL with curl. + +Use the installed Prisma Next skills and the current Prisma docs: https://www.prisma.io/docs/llms.txt (append `.md` to any docs URL for a markdown version). +``` + + + +## Add Prisma Next to your framework + +Each guide runs the same journey for a specific framework: scaffold, connect Prisma Postgres, query, and deploy where the framework is supported on Compute. + + + + + + + + + + + + + ## Learn the fundamentals diff --git a/apps/docs/content/docs/(index)/prisma-compute/deploy.mdx b/apps/docs/content/docs/(index)/prisma-compute/deploy.mdx index e50d47cc0a..846c2f99c7 100644 --- a/apps/docs/content/docs/(index)/prisma-compute/deploy.mdx +++ b/apps/docs/content/docs/(index)/prisma-compute/deploy.mdx @@ -3,7 +3,7 @@ title: Deploy your first app description: Take a TypeScript app from your terminal to a live URL on Prisma Compute, either by scaffolding a new one or deploying a project you already have. url: /prisma-compute/deploy metaTitle: "Quickstart: Deploy your first app on Prisma Compute" -metaDescription: Deploy a TypeScript app to Prisma Compute with the @prisma/cli beta package. Scaffold a new app with create-prisma or deploy an existing project, then verify it at a live URL. +metaDescription: Deploy a TypeScript app to Prisma Compute with @prisma/cli. Scaffold a new app with create-prisma or deploy an existing project, then verify the live URL. --- [Prisma Compute](/compute) is serverless hosting for TypeScript apps. It runs your app right next to your Prisma Postgres database, so the trip from app to data stays short. @@ -25,7 +25,7 @@ Before you start, make sure you have: :::info -Next.js apps should set `output: "standalone"` in their Next.js config. The `create-prisma` template already sets this for you. +Next.js apps must set `output: "standalone"` in their Next.js config, or the deployed app never boots and every request returns a 504. The `create-prisma@latest` (Prisma 7) template already sets this for you; the `create-prisma@next` (Prisma Next) template does not yet, so add it before deploying. ```ts title="next.config.ts" export default { output: "standalone" }; @@ -69,7 +69,7 @@ It asks for a template, a database provider, and a few options, then asks **"Dep So your deployed app has a database from its first request. -To skip the prompts, pass your choices as flags. Compute deploys are available for the `hono`, `elysia`, `next`, and `tanstack-start` templates: +To skip the prompts, pass your choices as flags. Compute deploys are available for every template except `svelte` (that is `hono`, `elysia`, `nest`, `next`, `astro`, `nuxt`, `tanstack-start`, and `turborepo`): ```npm npx create-prisma@latest --name my-api --template hono --provider postgresql --deploy @@ -88,7 +88,7 @@ npx @prisma/cli@latest app deploy In one pass, the CLI: 1. **Detects your framework** from your project files, whether that is Next.js, Nuxt, Astro, Hono, NestJS, TanStack Start, or a plain Bun server. To choose it yourself, pass `--framework` (use `--framework bun` for a Bun or Elysia server). -2. **Sets up a project** the first time you deploy from this directory, then writes [`.prisma/local.json`](/compute/getting-started#link-an-existing-project) to pin the directory to that project. That file is a gitignored local cache, not committed config. If your team already has a project, [link it first](/compute/getting-started#link-an-existing-project). +2. **Sets up a project** the first time you deploy from this directory: it asks you to pick or create one (pass `--create-project ` to skip the prompt, which non-interactive runs need), then writes [`.prisma/local.json`](/compute/getting-started#link-an-existing-project) to pin the directory to that project. That file is a gitignored local cache, not committed config. If your team already has a project, [link it first](/compute/getting-started#link-an-existing-project). 3. **Resolves the target branch.** Inside a Git repository, the CLI uses your current Git branch name; otherwise it falls back to `main`. Pass `--branch ` to choose explicitly. Because each branch is its own isolated environment, this decides where the deploy lands. 4. **Builds and uploads your app**, provisions it, and prints a live URL. @@ -164,6 +164,14 @@ You can let a coding agent do the deploying. Sign in once yourself ([step 1](#1- ```text Build [what you want] in [framework] and deploy it to Prisma Compute using `npx @prisma/cli@latest`. + +Notes: +- Before deploying, run `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login` (it opens a browser). +- Run every CLI command as `npx @prisma/cli@latest `, and add `--json` for structured output. +- Compute supports Next.js, Nuxt, Astro, Hono, NestJS, TanStack Start, and plain Bun servers. If you build a Next.js app, set `output: "standalone"` in its config before deploying. For a Bun or Elysia server pass `--framework bun --entry ` on the deploy. +- On the first deploy, the CLI creates the project and prints a live URL. Fetch it with curl and confirm the app responds. The first deploy is promoted to production automatically. +- To give the app a database, add `--db` to the deploy so Compute provisions and wires a Prisma Postgres database. +- If the app needs config or secrets, scope them to the environment you are deploying: `npx @prisma/cli@latest project env add KEY=value --role production` (or `--role preview`), then redeploy. Full scoping rules: https://www.prisma.io/docs/compute/environment-variables.md ``` For example: @@ -172,13 +180,7 @@ For example: Build a Hono API with a /todos endpoint backed by an in-memory list. Deploy it to Prisma Compute using `npx @prisma/cli@latest`. ``` -Notes for your agent: - -- Run every CLI command as `npx @prisma/cli@latest `, and add `--json` for structured output. -- Check login state with `npx @prisma/cli@latest auth whoami`. -- On the first deploy, the CLI creates the project and prints a live URL. Open it and confirm the app responds. The first deploy is promoted to production automatically. -- To give the app a database, add `--db` to the deploy so Compute provisions and wires a Prisma Postgres database. -- If the app needs config or secrets, scope them to the environment you're deploying. Use `--role production` for production deploys and `--role preview` for preview branches, then redeploy: `npx @prisma/cli@latest project env add KEY=value --role production` (or `--role preview`). Don't write production config to the preview scope. For the full scoping rules, see [Environment variables](/compute/environment-variables). +The notes travel with the prompt, so your agent checks sign-in state, verifies the live URL, and scopes environment variables correctly. For the full scoping rules in the docs, see [Environment variables](/compute/environment-variables). ## What's next diff --git a/apps/docs/content/docs/(index)/prisma-orm/quickstart/prisma-postgres.mdx b/apps/docs/content/docs/(index)/prisma-orm/quickstart/prisma-postgres.mdx index 38998322a2..7d6d5fe0e9 100644 --- a/apps/docs/content/docs/(index)/prisma-orm/quickstart/prisma-postgres.mdx +++ b/apps/docs/content/docs/(index)/prisma-orm/quickstart/prisma-postgres.mdx @@ -10,6 +10,9 @@ metaDescription: Create a new TypeScript project from scratch by connecting Pris ## Prerequisites +- [Node.js](https://nodejs.org) v20.19 or later +- No database needed: you create a Prisma Postgres database with one command in step 4 + ## 1. Create a new project ```shell @@ -123,7 +126,7 @@ datasource db { Create a Prisma Postgres database and replace the generated `DATABASE_URL` in your `.env` file with the `postgres://...` connection string from the CLI output: ```npm -npx create-db +npx create-db@latest ``` ## 5. Define your data model diff --git a/apps/docs/content/docs/(index)/prisma-postgres/quickstart/prisma-orm.mdx b/apps/docs/content/docs/(index)/prisma-postgres/quickstart/prisma-orm.mdx index 2144e33406..e6a5430f12 100644 --- a/apps/docs/content/docs/(index)/prisma-postgres/quickstart/prisma-orm.mdx +++ b/apps/docs/content/docs/(index)/prisma-postgres/quickstart/prisma-orm.mdx @@ -2,8 +2,8 @@ title: Prisma ORM description: Create a new TypeScript project from scratch by connecting Prisma ORM to Prisma Postgres and generating a Prisma Client for database access url: /prisma-postgres/quickstart/prisma-orm -metaTitle: 'Quickstart: Prisma ORM with Prisma Postgres (5 min)' -metaDescription: Create a new TypeScript project from scratch by connecting Prisma ORM to Prisma Postgres and generating a Prisma Client for database access. +metaTitle: 'Quickstart: Prisma Postgres with Prisma ORM (5 min)' +metaDescription: Set up Prisma Postgres in a new TypeScript project with Prisma ORM. Create the database, connect, and run your first type-safe queries. --- [Prisma Postgres](/postgres) is a fully managed PostgreSQL database that scales to zero and integrates smoothly with both Prisma ORM and Prisma Studio. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to Prisma Postgres using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. diff --git a/apps/docs/content/docs/compute/getting-started.mdx b/apps/docs/content/docs/compute/getting-started.mdx index 45e00284f2..3c77a03d32 100644 --- a/apps/docs/content/docs/compute/getting-started.mdx +++ b/apps/docs/content/docs/compute/getting-started.mdx @@ -72,7 +72,7 @@ Now `npm run deploy` does the same thing. ## Link an existing project -On your first deploy, the CLI creates a project for you. If your team already has one, link to it before you deploy instead: +On your first deploy, the CLI asks you to pick or create a project; pass `--create-project ` to skip the prompt. If your team already has one, link to it before you deploy instead: ```npm npx @prisma/cli@latest project link my-app diff --git a/apps/docs/content/docs/compute/index.mdx b/apps/docs/content/docs/compute/index.mdx index d6daa75b1a..ffbabc3e66 100644 --- a/apps/docs/content/docs/compute/index.mdx +++ b/apps/docs/content/docs/compute/index.mdx @@ -7,7 +7,7 @@ metaTitle: Prisma Compute | TypeScript app hosting for Prisma Postgres metaDescription: Learn how Prisma Compute deploys TypeScript apps alongside Prisma Postgres, with isolated branch previews, database branches, and CLI-first workflows. --- -Prisma Compute is TypeScript app hosting built to run alongside [Prisma Postgres](/postgres). You model your data with [Prisma ORM](/orm), store it in Prisma Postgres, and deploy your app with Prisma Compute, so your schema, database, hosting, and branch previews work together in one Prisma project. +Prisma Compute is TypeScript app hosting built to run alongside [Prisma Postgres](/postgres). It is the last step of the [recommended Prisma stack](/): you model your data with [Prisma Next](/next) or [Prisma ORM](/orm), store it in Prisma Postgres, and deploy your app with Prisma Compute, so your schema, database, hosting, and branch previews work together in one Prisma project. :::info[Public Beta] @@ -20,11 +20,16 @@ Prisma Compute is in [Public Beta](/console/more/feature-maturity#public-beta) a The best way to understand Compute is to deploy an app. The quickstart takes a TypeScript app to a live URL in a few minutes, then connects GitHub so every push can deploy automatically. - + }> The quickstart: sign in, deploy, verify, and connect GitHub. + }> + No app yet? Scaffold one with Prisma Next and Prisma Postgres first. + +Working with a coding agent? The deploy quickstart ends with a ready-to-copy prompt in [Hand it to your agent](/prisma-compute/deploy#hand-it-to-your-agent). + To learn how Compute works, [the model](#the-model) below shows how each branch gets isolated app and database resources, so preview work never touches production. ## The model diff --git a/apps/docs/content/docs/guides/next/frameworks/astro.mdx b/apps/docs/content/docs/guides/next/frameworks/astro.mdx index 7b6526e9d3..6ddedb6dcd 100644 --- a/apps/docs/content/docs/guides/next/frameworks/astro.mdx +++ b/apps/docs/content/docs/guides/next/frameworks/astro.mdx @@ -1,14 +1,14 @@ --- title: Astro -description: Set up Prisma Next in a Astro app with create-prisma, from scaffold to rendered data. +description: Set up Prisma Next in an Astro app with create-prisma, from scaffold to rendered data, and deploy it to Prisma Compute. url: /guides/next/frameworks/astro metaTitle: How to use Prisma Next with Astro -metaDescription: Scaffold a Astro project with Prisma Next and Prisma Postgres, initialize the database, seed it, and see your data, with tested commands. +metaDescription: Scaffold an Astro site with Prisma Next and Prisma Postgres, seed the database, render your data, and deploy to Prisma Compute, with tested commands. --- ## Introduction -This guide shows you how to use Prisma Next in an Astro site. You scaffold a project that queries users during server rendering and exposes a JSON API route, initialize the schema, and see your data render. +This guide shows you how to use Prisma Next in an Astro site. You scaffold a project that queries users during server rendering and exposes a JSON API route, initialize the schema, see your data render, and deploy the site to [Prisma Compute](/compute). Every command below was run end to end against a live [Prisma Postgres](/postgres) database. @@ -17,21 +17,41 @@ Every command below was run end to end against a live [Prisma Postgres](/postgre One command scaffolds the project with Prisma Next wired in: ```npm -npx create-prisma@next --template astro --provider postgres +npx create-prisma@next create my-astro-app --template astro --provider postgres ``` Pick Prisma Postgres at the database prompt to have a database created for you, or paste your own `DATABASE_URL`. ## Prerequisites -- [Node.js](https://nodejs.org) v20.19 or later +- [Node.js](https://nodejs.org) 24 or later - A PostgreSQL connection string, or nothing at all: the scaffold can create the database for you +## Use with your agent + +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: + + + +```text +Create a new Astro app with Prisma Next, seed it, and deploy it to Prisma Compute. + +1. Scaffold: `npx create-prisma@next create my-astro-app --template astro --provider postgres --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-astro-app`, run `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun. +3. Start `npm run dev` in the background, wait until it reports ready, verify http://localhost:4321 lists the seeded users and `curl http://localhost:4321/api/users` returns them as JSON, then stop the dev server. +4. Prepare the deploy build: run `npm install @astrojs/node@^10`, then set `output: "server"` and `adapter: node({ mode: "standalone" })` in `astro.config.mjs`, following https://www.prisma.io/docs/guides/next/frameworks/astro.md. +5. Deploy: check `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`. Then run `npx @prisma/cli@latest app deploy --create-project my-astro-app --env .env --env HOST=0.0.0.0` (without HOST the live URL answers `Service not found`) and verify the live URL's /api/users endpoint with curl. + +Use the installed Prisma Next skills. +``` + + + ## 1. Scaffold and enter the project ```npm -npx create-prisma@next --template astro --provider postgres -cd my-app +npx create-prisma@next create my-astro-app --template astro --provider postgres +cd my-astro-app ``` The scaffold writes your connection string to `.env`, generates the Astro app with Prisma Next wired in, installs dependencies, and emits the contract your queries are type-checked against. @@ -48,6 +68,12 @@ npm run db:seed Seeded 3 users. ``` +:::note + +Seeing `Cannot read properties of undefined (reading 'where')`? The current `astro` template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun `db:seed`. + +::: + `db:init` applies your schema (`src/prisma/contract.prisma`) to the database and signs it; the seed gives the first page something to show. ## 3. Run and verify @@ -66,6 +92,67 @@ Open [http://localhost:4321](http://localhost:4321). The page lists the seeded u Model access is namespace-qualified on PostgreSQL: `db.orm.public.User`. The [Prisma Next overview](/orm/next) covers the contract-first model behind it. +## 4. Deploy to Prisma Compute + +Astro is supported on [Prisma Compute](/compute), which runs the site as a Node server. That needs the Node adapter in standalone mode; without it the deploy fails at build time with `Astro build did not produce a standalone server entrypoint`. The template currently pins Astro 6, so install the matching adapter major: + +```npm +npm install @astrojs/node@^10 +``` + +Then configure the adapter in `astro.config.mjs`. Setting `output: "server"` renders the page and the API route per request, so the live site reads current data instead of freezing the build-time snapshot into static files: + +```js title="astro.config.mjs" +// @ts-check +import node from "@astrojs/node"; +import { prismaVitePlugin } from "@prisma-next/vite-plugin-contract-emit"; +import { defineConfig } from "astro/config"; + +// https://astro.build/config +export default defineConfig({ + output: "server", + adapter: node({ mode: "standalone" }), + vite: { + plugins: [prismaVitePlugin()], + }, +}); +``` + +Sign in once (it opens a browser): + +```npm +npx @prisma/cli@latest auth login +``` + +Then deploy from the project directory. The `--env .env` flag passes your `DATABASE_URL` to the deployment, so the live site talks to the same database. The `HOST=0.0.0.0` variable is required: the standalone server binds `localhost` by default, which Compute's router cannot reach, and the live URL answers `Service not found` without it: + +```npm +npx @prisma/cli@latest app deploy --env .env --env HOST=0.0.0.0 +``` + +```text no-copy +First deploy of "my-astro-app" -- promoting to production. + +Build settings + Build Command astro build · Astro default + Output Directory dist · Astro output + +Building locally... + Built 8.3 MB +Uploading... +Deploying... +Live in 10.6s +https://.ewr.prisma.build +``` + +Verify the live API route returns the seeded users: + +```bash +curl https://.ewr.prisma.build/api/users +``` + +The live URL's root page renders the same users server-side. The first deploy asks you to pick or create a project (pass `--create-project my-astro-app` to skip the prompt), pins the directory to it in a gitignored `.prisma/local.json`, and promotes to production. For previews per Git branch and deploy-on-push, see [Deploy your first app](/prisma-compute/deploy). + ## Next steps - Change the schema in `src/prisma/contract.prisma`, then run `npm run contract:emit` and `npm run db:update`. diff --git a/apps/docs/content/docs/guides/next/frameworks/elysia.mdx b/apps/docs/content/docs/guides/next/frameworks/elysia.mdx index 80575bbc36..45aa72dec4 100644 --- a/apps/docs/content/docs/guides/next/frameworks/elysia.mdx +++ b/apps/docs/content/docs/guides/next/frameworks/elysia.mdx @@ -1,14 +1,14 @@ --- title: Elysia -description: Build an Elysia API on Prisma Next with the elysia template. +description: Build an Elysia API on Prisma Next with the elysia template and deploy it to Prisma Compute. url: /guides/next/frameworks/elysia metaTitle: How to use Prisma Next with Elysia -metaDescription: Scaffold an Elysia API backed by Prisma Next and Prisma Postgres, seed it, and serve users over HTTP, with tested commands and output. +metaDescription: Scaffold an Elysia API backed by Prisma Next and Prisma Postgres, seed it, serve users over HTTP, and deploy it to Prisma Compute as a Bun app. --- ## Introduction -In this guide, you scaffold an Elysia API backed by Prisma Next, initialize and seed a PostgreSQL database, and serve data over HTTP. The `elysia` template generates the server, so most of the work is understanding the pieces. +In this guide, you scaffold an Elysia API backed by Prisma Next, initialize and seed a PostgreSQL database, serve data over HTTP, and deploy the API to [Prisma Compute](/compute) as a Bun app. The `elysia` template generates the server, so most of the work is understanding the pieces. Every command and response below was run end to end against a live Prisma Postgres database. @@ -17,10 +17,29 @@ Every command and response below was run end to end against a live Prisma Postgr - [Bun](https://bun.sh/) 1.1 or later (Elysia is Bun-first) - A PostgreSQL connection string, or nothing at all: the scaffold can create a [Prisma Postgres](/postgres) database for you +## Use with your agent + +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: + + + +```text +Verify `bun --version` first; if Bun is missing, stop and ask. Create a new Elysia API with Prisma Next, seed it, and deploy it to Prisma Compute. + +1. Scaffold: `bunx create-prisma@next create my-elysia-api --template elysia --provider postgres --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-elysia-api`, run `bun run db:init`, then `bun run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun. +3. Start `bun run dev` in the background, wait until it reports ready, verify `curl http://localhost:3000/users` returns the seeded users, then stop the dev server. +4. Deploy: check `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`. Then run `npx @prisma/cli@latest app deploy --create-project my-elysia-api --env .env --framework bun --entry src/index.ts` and verify the live URL's /users endpoint. + +Use the installed Prisma Next skills. +``` + + + ## 1. Scaffold the project ```bash -bunx create-prisma@next create my-elysia-api --provider postgres --template elysia +bunx create-prisma@next create my-elysia-api --template elysia --provider postgres ``` Pick your database at the prompt. The template generates an Elysia server in `src/index.ts` with `GET /` and `GET /users` routes, the Prisma Next setup in `src/prisma/`, and package scripts for the database steps. @@ -43,7 +62,7 @@ Seeded 3 users. :::note -Scaffolded with an older `create-prisma` and seeing `Cannot read properties of undefined (reading 'where')`? Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`. Current templates generate the qualified form. +Seeing `Cannot read properties of undefined (reading 'where')`? The current `elysia` template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun `db:seed`. ::: @@ -61,19 +80,51 @@ curl http://localhost:3000/users ```json no-copy [ - { "id": "1", "email": "alice@prisma.io", "username": "alice", "name": "Alice", "createdAt": "2026-07-07T08:51:14.054Z" }, - { "id": "2", "email": "bob@prisma.io", "username": "bob", "name": "Bob", "createdAt": "2026-07-07T08:51:14.089Z" }, - { "id": "3", "email": "carol@prisma.io", "username": "carol", "name": "Carol", "createdAt": "2026-07-07T08:51:14.122Z" } + { "id": "1", "email": "alice@prisma.io", "username": "alice", "name": "Alice", "createdAt": "2026-07-24T11:43:41.450Z" }, + { "id": "2", "email": "bob@prisma.io", "username": "bob", "name": "Bob", "createdAt": "2026-07-24T11:43:41.490Z" }, + { "id": "3", "email": "carol@prisma.io", "username": "carol", "name": "Carol", "createdAt": "2026-07-24T11:43:41.533Z" } ] ``` The route handler is ordinary Elysia code calling an ordinary Prisma Next query; there is no framework adapter in between. To add write routes, follow the same pattern as the [Hono guide's POST route](/guides/next/frameworks/hono#4-add-a-post-route); the query code is identical. +## 4. Deploy to Prisma Compute + +Elysia apps run on [Prisma Compute](/compute) as Bun apps, so the API can go from your terminal to a live URL in one command. Sign in once (it opens a browser): + +```npm +npx @prisma/cli@latest auth login +``` + +Then deploy from the project directory. Compute does not auto-detect Elysia yet, so pass `--framework bun` with the server entry file. The `--env .env` flag passes your `DATABASE_URL` to the deployment, so the live API talks to the same database: + +```npm +npx @prisma/cli@latest app deploy --env .env --framework bun --entry src/index.ts +``` + +```text no-copy +First deploy of "my-elysia-api" -- promoting to production. +Building locally... + Built 1.2 MB +Uploading... +Deploying... +Live in 8.8s +https://.ewr.prisma.build +``` + +Verify the live endpoint returns the seeded users: + +```bash +curl https://.ewr.prisma.build/users +``` + +The first deploy asks you to pick or create a project (pass `--create-project my-elysia-api` to skip the prompt), pins the directory to it in a gitignored `.prisma/local.json`, and promotes to production. For previews per Git branch and deploy-on-push, see [Deploy your first app](/prisma-compute/deploy). + ## Common gotchas :::warning -In a long-running server, don't call `db.close()` in route handlers; the client's connection pool is shared across requests. Close it only on process shutdown. +In a long-running server, don't call `db.runtime().close()` in route handlers; the client's connection pool is shared across requests. Close it only on process shutdown. ::: diff --git a/apps/docs/content/docs/guides/next/frameworks/hono.mdx b/apps/docs/content/docs/guides/next/frameworks/hono.mdx index b0bd21d446..fc33ae49a0 100644 --- a/apps/docs/content/docs/guides/next/frameworks/hono.mdx +++ b/apps/docs/content/docs/guides/next/frameworks/hono.mdx @@ -1,26 +1,46 @@ --- title: Hono -description: Build a Hono API on Prisma Next with the hono template, then add your own routes. +description: Build a Hono API on Prisma Next with the hono template, add your own routes, and deploy it to Prisma Compute. url: /guides/next/frameworks/hono metaTitle: How to use Prisma Next with Hono -metaDescription: Scaffold a Hono API backed by Prisma Next and Prisma Postgres, seed it, serve users over HTTP, and add a POST route, with tested commands and output. +metaDescription: Scaffold a Hono API backed by Prisma Next and Prisma Postgres, seed it, serve users over HTTP, add a POST route, and deploy to Prisma Compute. --- ## Introduction -In this guide, you scaffold a Hono API backed by Prisma Next, initialize and seed a PostgreSQL database, serve data over HTTP, and add your own POST route. The `hono` template generates the server for you, so most of the work is understanding the pieces and extending them. +In this guide, you scaffold a Hono API backed by Prisma Next, initialize and seed a PostgreSQL database, serve data over HTTP, add your own POST route, and deploy the API to [Prisma Compute](/compute). The `hono` template generates the server for you, so most of the work is understanding the pieces and extending them. Every command, route, and response below was run end to end against a live Prisma Postgres database. ## Prerequisites -- Node.js 24 or later, or [Bun](https://bun.sh/) (this guide uses Bun for speed; npm works the same) +- [Node.js](https://nodejs.org) 24 or later, or [Bun](https://bun.sh/) (this guide uses Bun for speed; npm works the same) - A PostgreSQL connection string, or nothing at all: the scaffold can create a [Prisma Postgres](/postgres) database for you +## Use with your agent + +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: + + + +```text +Create a new Hono API with Prisma Next, seed it, and deploy it to Prisma Compute. + +1. Scaffold: `npx create-prisma@next create my-hono-api --template hono --provider postgres --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-hono-api`, run `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun. +3. Start `npm run dev` in the background, wait until it reports ready, verify `curl http://localhost:3000/users` returns the seeded users, then stop the dev server. +4. Add a POST /users route that creates a user from the request body, following https://www.prisma.io/docs/guides/next/frameworks/hono.md, restart the dev server, and verify it with curl. +5. Deploy: check `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`. Then run `npx @prisma/cli@latest app deploy --create-project my-hono-api --env .env` and verify the live URL's /users endpoint. + +Use the installed Prisma Next skills. +``` + + + ## 1. Scaffold the project ```bash -bunx create-prisma@next create my-hono-api --provider postgres --template hono +bunx create-prisma@next create my-hono-api --template hono --provider postgres ``` Pick your package manager and database at the prompts. The template generates a Hono server in `src/index.ts` with two routes (`GET /` and `GET /users`), the Prisma Next setup in `src/prisma/`, and package scripts for the database steps. @@ -43,7 +63,7 @@ Seeded 3 users. :::note -Scaffolded with an older `create-prisma` and seeing `Cannot read properties of undefined (reading 'where')`? Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`. Current templates generate the qualified form. +Seeing `Cannot read properties of undefined (reading 'where')`? The current `hono` template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun `db:seed`. ::: @@ -99,11 +119,43 @@ curl -X POST http://localhost:3000/users \ `.create(...)` returns the full inserted record, database defaults included, so the response needs no second query. +## 5. Deploy to Prisma Compute + +Hono is supported on [Prisma Compute](/compute), so the API can go from your terminal to a live URL in one command. Sign in once (it opens a browser): + +```npm +npx @prisma/cli@latest auth login +``` + +Then deploy from the project directory. The `--env .env` flag passes your `DATABASE_URL` to the deployment, so the live API talks to the same database: + +```npm +npx @prisma/cli@latest app deploy --env .env +``` + +```text no-copy +First deploy of "my-hono-api" -- promoting to production. +Building locally... + Built 0.9 MB +Uploading... +Deploying... +Live in 7.5s +https://.ewr.prisma.build +``` + +Verify the live endpoint returns the seeded users: + +```bash +curl https://.ewr.prisma.build/users +``` + +The first deploy asks you to pick or create a project (pass `--create-project my-hono-api` to skip the prompt), pins the directory to it in a gitignored `.prisma/local.json`, and promotes to production. For previews per Git branch and deploy-on-push, see [Deploy your first app](/prisma-compute/deploy). + ## Common gotchas :::warning -In a long-running server, don't call `db.close()` in route handlers; the client's connection pool is shared across requests. Close it only on process shutdown. +In a long-running server, don't call `db.runtime().close()` in route handlers; the client's connection pool is shared across requests. Close it only on process shutdown. ::: @@ -112,7 +164,7 @@ In a long-running server, don't call `db.close()` in route handlers; the client' The scaffold installs [Prisma Next skills](/ai/tools/skills#available-skills-for-prisma-next) for your coding agent. Prompts that map to this guide: - "Using the prisma-next-queries skill, add GET /users/:id that returns one user or a 404." -- "Add a Post model related to User, update the database, and expose GET /users/:id/posts." +- "Expose GET /users/:id/posts using the Post model that ships with the starter contract." - "Wrap the signup route's writes in a [transaction](/orm/next/fundamentals/transactions)." ## Next steps diff --git a/apps/docs/content/docs/guides/next/frameworks/nestjs.mdx b/apps/docs/content/docs/guides/next/frameworks/nestjs.mdx index bae676e1d6..23bebef64b 100644 --- a/apps/docs/content/docs/guides/next/frameworks/nestjs.mdx +++ b/apps/docs/content/docs/guides/next/frameworks/nestjs.mdx @@ -1,40 +1,49 @@ --- title: NestJS -description: Set up Prisma Next in a NestJS app with create-prisma, from scaffold to rendered data. +description: Set up Prisma Next in a NestJS app with create-prisma, from scaffold to seeded API to a live deploy on Prisma Compute. url: /guides/next/frameworks/nestjs metaTitle: How to use Prisma Next with NestJS -metaDescription: Scaffold a NestJS project with Prisma Next and Prisma Postgres, initialize the database, seed it, and see your data, with tested commands. +metaDescription: Scaffold a NestJS API with Prisma Next and Prisma Postgres, initialize and seed the database, query it over HTTP, and deploy to Prisma Compute. --- ## Introduction -This guide shows you how to use Prisma Next in a NestJS API. You scaffold a project with a users controller backed by Prisma Next, initialize the schema, and query it over HTTP. +This guide shows you how to use Prisma Next in a NestJS API. You scaffold a project with a users controller backed by Prisma Next, initialize the schema, query it over HTTP, and deploy the API to [Prisma Compute](/compute). Every command below was run end to end against a live [Prisma Postgres](/postgres) database. -## Quick start +## Prerequisites -One command scaffolds the project with Prisma Next wired in: +- [Node.js](https://nodejs.org) 24 or later +- A PostgreSQL connection string, or nothing at all: the scaffold can create the database for you -```npm -npx create-prisma@next --template nest --provider postgres -``` +## Use with your agent -Pick Prisma Postgres at the database prompt to have a database created for you, or paste your own `DATABASE_URL`. +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: -## Prerequisites + -- [Node.js](https://nodejs.org) v20.19 or later -- A PostgreSQL connection string, or nothing at all: the scaffold can create the database for you +```text +Create a new NestJS API with Prisma Next, seed it, and deploy it to Prisma Compute. + +1. Scaffold: `npx create-prisma@next create my-nest-api --template nest --provider postgres --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-nest-api`, run `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun. +3. Start `npm run dev` in the background, wait until it reports ready, and verify `curl http://localhost:3000/users` returns the seeded users; stop the dev server once verified. If it returns a 500 and the server logs `Cannot read properties of undefined (reading 'findAll')`, add explicit injection tokens: `@Inject(UsersService)` on the constructor parameter in `src/users.controller.ts` and `@Inject(PrismaService)` in `src/users.service.ts` (import `Inject` from `@nestjs/common`), then retry. +4. Deploy: check `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`. Then run `npx @prisma/cli@latest app deploy --create-project my-nest-api --env .env` and verify the live URL's /users endpoint. + +Use the installed Prisma Next skills. +``` + + ## 1. Scaffold and enter the project ```npm -npx create-prisma@next --template nest --provider postgres -cd my-app +npx create-prisma@next create my-nest-api --template nest --provider postgres +cd my-nest-api ``` -The scaffold writes your connection string to `.env`, generates the NestJS app with Prisma Next wired in, installs dependencies, and emits the contract your queries are type-checked against. +Pick Prisma Postgres at the database prompt to have a database created for you, or paste your own `DATABASE_URL`. The scaffold writes your connection string to `.env`, generates the NestJS app with Prisma Next wired in, installs dependencies, and emits the contract your queries are type-checked against. ## 2. Initialize and seed the database @@ -48,7 +57,13 @@ npm run db:seed Seeded 3 users. ``` -`db:init` applies your schema (`src/prisma/contract.prisma`) to the database and signs it; the seed gives the first page something to show. +`db:init` applies your schema (`src/prisma/contract.prisma`) to the database and signs it; the seed gives the first request something to return. + +:::note + +Seeing `Cannot read properties of undefined (reading 'where')`? The current `nest` template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun `db:seed`. + +::: ## 3. Run and verify @@ -56,7 +71,7 @@ Seeded 3 users. npm run dev ``` -Query the API: +The server starts on port 3000 (set `PORT` to change it). Query the API: ```bash curl http://localhost:3000/users @@ -64,18 +79,81 @@ curl http://localhost:3000/users ```json no-copy [ - { "id": "1", "email": "alice@prisma.io", "username": "alice", "name": "Alice", "createdAt": "2026-07-07T09:44:19.201Z" } + { "id": "1", "email": "alice@prisma.io", "username": "alice", "name": "Alice", "createdAt": "2026-07-24T10:55:54.156Z" }, + { "id": "2", "email": "bob@prisma.io", "username": "bob", "name": "Bob", "createdAt": "2026-07-24T10:55:54.192Z" }, + { "id": "3", "email": "carol@prisma.io", "username": "carol", "name": "Carol", "createdAt": "2026-07-24T10:55:54.228Z" } ] ``` +:::note + +Getting a 500 with `Cannot read properties of undefined (reading 'findAll')` in the server logs? The `dev` script runs through `tsx`, which does not emit the decorator metadata NestJS constructor injection relies on, so the controller receives no service instance. Add explicit injection tokens: in `src/users.controller.ts`, change the constructor parameter to `@Inject(UsersService) private readonly usersService: UsersService`, and in `src/users.service.ts` to `@Inject(PrismaService) private readonly prisma: PrismaService` (import `Inject` from `@nestjs/common` in both files). The watcher reloads and the route works. + +::: + ## Where things live - `src/users.controller.ts`: the `GET /users` route -- `src/users.service.ts`: the service that runs the Prisma Next query -- `src/prisma/db.ts`: the Prisma Next client the service imports +- `src/users.service.ts`: the service the controller calls +- `src/prisma.service.ts`: the injectable that exposes the Prisma Next client and query helpers +- `src/prisma/users.ts`: the `listUsers` query the service runs +- `src/prisma/db.ts`: the Prisma Next client itself Model access is namespace-qualified on PostgreSQL: `db.orm.public.User`. The [Prisma Next overview](/orm/next) covers the contract-first model behind it. +## 4. Deploy to Prisma Compute + +NestJS is supported on [Prisma Compute](/compute), so the API can go from your terminal to a live URL in one command. Sign in once (it opens a browser): + +```npm +npx @prisma/cli@latest auth login +``` + +Then deploy from the project directory. The `--env .env` flag passes your `DATABASE_URL` to the deployment, so the live API talks to the same database: + +```npm +npx @prisma/cli@latest app deploy --env .env +``` + +```text no-copy +First deploy of "my-nest-api" -- promoting to production. + +Build settings + Build Command npm run build · package.json scripts.build + Output Directory dist · NestJS output + +Building locally... + Built 1.1 MB +Uploading... +Deploying... +Live in 9.6s +https://.ewr.prisma.build +``` + +Verify the live endpoint returns the seeded users: + +```bash +curl https://.ewr.prisma.build/users +``` + +The first deploy asks you to pick or create a project (pass `--create-project my-nest-api` to skip the prompt), pins the directory to it in a gitignored `.prisma/local.json`, and promotes to production. For previews per Git branch and deploy-on-push, see [Deploy your first app](/prisma-compute/deploy). + +## Common gotchas + +:::warning + +In a long-running server, don't call `db.runtime().close()` in request handlers; the client's connection pool is shared across requests. Close it only on process shutdown. + +::: + +## Prompt your coding agent + +The scaffold installs [Prisma Next skills](/ai/tools/skills#available-skills-for-prisma-next) for your coding agent. Prompts that map to this guide: + +- "Using the prisma-next-queries skill, add GET /users/:id to the users controller that returns one user or a 404." +- "Expose GET /users/:id/posts using the Post model that ships with the starter contract." +- "Add a POST /users route that creates a user from the request body and returns it with a 201." + ## Next steps - Change the schema in `src/prisma/contract.prisma`, then run `npm run contract:emit` and `npm run db:update`. diff --git a/apps/docs/content/docs/guides/next/frameworks/nextjs.mdx b/apps/docs/content/docs/guides/next/frameworks/nextjs.mdx index d51a7a7b26..4f6f97e6a1 100644 --- a/apps/docs/content/docs/guides/next/frameworks/nextjs.mdx +++ b/apps/docs/content/docs/guides/next/frameworks/nextjs.mdx @@ -1,40 +1,50 @@ --- title: Next.js -description: Set up Prisma Next in a Next.js app with create-prisma, from scaffold to rendered data. +description: Set up Prisma Next in a Next.js app with create-prisma, from scaffold to rendered data, and deploy it to Prisma Compute. url: /guides/next/frameworks/nextjs metaTitle: How to use Prisma Next with Next.js -metaDescription: Scaffold a Next.js project with Prisma Next and Prisma Postgres, initialize the database, seed it, and see your data, with tested commands. +metaDescription: Scaffold a Next.js app with Prisma Next and Prisma Postgres, initialize and seed the database, render your data, and deploy to Prisma Compute. --- ## Introduction -This guide shows you how to use Prisma Next in a Next.js app. You scaffold a project where a server component queries your database, initialize the schema, and see your data render. +This guide shows you how to use Prisma Next in a Next.js app. You scaffold a project where a server component queries your database, initialize the schema, see your data render, and deploy the app to [Prisma Compute](/compute). Every command below was run end to end against a live [Prisma Postgres](/postgres) database. -## Quick start +## Prerequisites -One command scaffolds the project with Prisma Next wired in: +- [Node.js](https://nodejs.org) 24 or later +- A PostgreSQL connection string, or nothing at all: the scaffold can create the database for you -```npm -npx create-prisma@next --template next --provider postgres -``` +## Use with your agent -Pick Prisma Postgres at the database prompt to have a database created for you, or paste your own `DATABASE_URL`. +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: -## Prerequisites + -- [Node.js](https://nodejs.org) v20.19 or later -- A PostgreSQL connection string, or nothing at all: the scaffold can create the database for you +```text +Create a new Next.js app with Prisma Next, seed it, and deploy it to Prisma Compute. + +1. Scaffold: `npx create-prisma@next create my-app --template next --provider postgres --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-app`, run `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun. +3. Start `npm run dev` in the background, wait until it reports ready, verify http://localhost:3000 renders the seeded users, then stop the dev server. +4. Set `output: "standalone"` in `next.config.ts`; Prisma Compute deploys the standalone server that `next build` emits. +5. Deploy: check `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`. Then run `npx @prisma/cli@latest app deploy --create-project my-app --env .env` and verify the live URL renders the seeded users. + +Use the installed Prisma Next skills. +``` + + ## 1. Scaffold and enter the project ```npm -npx create-prisma@next --template next --provider postgres +npx create-prisma@next create my-app --template next --provider postgres cd my-app ``` -The scaffold writes your connection string to `.env`, generates the Next.js app with Prisma Next wired in, installs dependencies, and emits the contract your queries are type-checked against. +Pick Prisma Postgres at the database prompt to have a database created for you, or paste your own `DATABASE_URL`. The scaffold writes your connection string to `.env`, generates the Next.js app with Prisma Next wired in, installs dependencies, and emits the contract your queries are type-checked against. ## 2. Initialize and seed the database @@ -50,13 +60,63 @@ Seeded 3 users. `db:init` applies your schema (`src/prisma/contract.prisma`) to the database and signs it; the seed gives the first page something to show. +:::note + +Seeing `Cannot read properties of undefined (reading 'where')`? The current `next` template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun `db:seed`. + +::: + ## 3. Run and verify ```npm npm run dev ``` -Open [http://localhost:3000](http://localhost:3000). The page lists the seeded users, rendered by a server component that calls Prisma Next directly. +Open [http://localhost:3000](http://localhost:3000) (set `PORT` to change it). The page lists the seeded users, rendered by a server component that calls Prisma Next directly. + +## 4. Deploy to Prisma Compute + +Next.js is supported on [Prisma Compute](/compute). Compute runs the standalone server that `next build` emits, and the template does not enable that output mode yet, so set it in `next.config.ts` first: + +```ts title="next.config.ts" +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + output: "standalone", +}; + +export default nextConfig; +``` + +:::warning + +Without `output: "standalone"` the deploy command still completes, but the uploaded build contains no server to start and the live URL returns a 504. With it, the build drops from roughly 170 MB to 14 MB and boots normally. + +::: + +Sign in once (it opens a browser): + +```npm +npx @prisma/cli@latest auth login +``` + +Then deploy from the project directory. The `--env .env` flag passes your `DATABASE_URL` to the deployment, so the live app talks to the same database: + +```npm +npx @prisma/cli@latest app deploy --env .env +``` + +```text no-copy +First deploy of "my-app" -- promoting to production. +Building locally... + Built 14.4 MB +Uploading... +Deploying... +Live in 15.5s +https://.ewr.prisma.build +``` + +Open the live URL: the page renders the same seeded users as your local dev server. The first deploy asks you to pick or create a project (pass `--create-project my-app` to skip the prompt), pins the directory to it in a gitignored `.prisma/local.json`, and promotes to production. Later production deploys from the same directory need `--prod`; for previews per Git branch and deploy-on-push, see [Deploy your first app](/prisma-compute/deploy). ## Where things live diff --git a/apps/docs/content/docs/guides/next/frameworks/nuxt.mdx b/apps/docs/content/docs/guides/next/frameworks/nuxt.mdx index 8b1fd1815b..32d3992d16 100644 --- a/apps/docs/content/docs/guides/next/frameworks/nuxt.mdx +++ b/apps/docs/content/docs/guides/next/frameworks/nuxt.mdx @@ -1,14 +1,14 @@ --- title: Nuxt -description: Set up Prisma Next in a Nuxt app with create-prisma, from scaffold to rendered data. +description: Set up Prisma Next in a Nuxt app with create-prisma, from scaffold to rendered data, and deploy it to Prisma Compute. url: /guides/next/frameworks/nuxt metaTitle: How to use Prisma Next with Nuxt -metaDescription: Scaffold a Nuxt project with Prisma Next and Prisma Postgres, initialize the database, seed it, and see your data, with tested commands. +metaDescription: Scaffold a Nuxt app with Prisma Next and Prisma Postgres, initialize and seed the database, render your data, and deploy to Prisma Compute. --- ## Introduction -This guide shows you how to use Prisma Next in a Nuxt app. You scaffold a project where a server API route queries your database and the page renders it, initialize the schema, and see your data. +This guide shows you how to use Prisma Next in a Nuxt app. You scaffold a project where a server API route queries your database and the page renders it, initialize the schema, see your data, and deploy the app to [Prisma Compute](/compute). Every command below was run end to end against a live [Prisma Postgres](/postgres) database. @@ -17,20 +17,39 @@ Every command below was run end to end against a live [Prisma Postgres](/postgre One command scaffolds the project with Prisma Next wired in: ```npm -npx create-prisma@next --template nuxt --provider postgres +npx create-prisma@next create my-app --template nuxt --provider postgres ``` Pick Prisma Postgres at the database prompt to have a database created for you, or paste your own `DATABASE_URL`. ## Prerequisites -- [Node.js](https://nodejs.org) v20.19 or later +- [Node.js](https://nodejs.org) 24 or later - A PostgreSQL connection string, or nothing at all: the scaffold can create the database for you +## Use with your agent + +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: + + + +```text +Create a new Nuxt app with Prisma Next, seed it, and deploy it to Prisma Compute. + +1. Scaffold: `npx create-prisma@next create my-app --template nuxt --provider postgres --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-app`, run `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun. +3. Start `npm run dev` in the background, wait until it reports ready, verify that http://localhost:3000 lists the seeded users and `curl http://localhost:3000/api/users` returns them, then stop the dev server. +4. Deploy: check `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`. Then run `npx @prisma/cli@latest app deploy --create-project my-app --env .env` and verify the live URL's /api/users endpoint. + +Use the installed Prisma Next skills. +``` + + + ## 1. Scaffold and enter the project ```npm -npx create-prisma@next --template nuxt --provider postgres +npx create-prisma@next create my-app --template nuxt --provider postgres cd my-app ``` @@ -50,13 +69,33 @@ Seeded 3 users. `db:init` applies your schema (`src/prisma/contract.prisma`) to the database and signs it; the seed gives the first page something to show. +:::note + +Seeing `Cannot read properties of undefined (reading 'where')`? The current `nuxt` template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun `db:seed`. + +::: + ## 3. Run and verify ```npm npm run dev ``` -Open [http://localhost:3000](http://localhost:3000). The page lists the seeded users, fetched from the `/api/users` server route. +Open [http://localhost:3000](http://localhost:3000). The page lists the seeded users, fetched from the `/api/users` server route. You can hit that route directly: + +```bash +curl http://localhost:3000/api/users +``` + +```json no-copy +{ + "users": [ + { "id": "1", "email": "alice@prisma.io", "username": "alice", "name": "Alice", "createdAt": "2026-07-24T11:43:58.001Z" }, + { "id": "2", "email": "bob@prisma.io", "username": "bob", "name": "Bob", "createdAt": "2026-07-24T11:43:58.035Z" }, + { "id": "3", "email": "carol@prisma.io", "username": "carol", "name": "Carol", "createdAt": "2026-07-24T11:43:58.068Z" } + ] +} +``` ## Where things live @@ -66,6 +105,45 @@ Open [http://localhost:3000](http://localhost:3000). The page lists the seeded u Model access is namespace-qualified on PostgreSQL: `db.orm.public.User`. The [Prisma Next overview](/orm/next) covers the contract-first model behind it. +## 4. Deploy to Prisma Compute + +Nuxt is supported on [Prisma Compute](/compute), so the app can go from your terminal to a live URL in one command. Sign in once (it opens a browser): + +```npm +npx @prisma/cli@latest auth login +``` + +Then deploy from the project directory. The `--env .env` flag passes your `DATABASE_URL` to the deployment, so the live app talks to the same database: + +```npm +npx @prisma/cli@latest app deploy --env .env +``` + +Compute detects the Nuxt defaults (`nuxt build`, output in `.output`) without any configuration: + +```text no-copy +First deploy of "my-app" -- promoting to production. + +Build settings + Build Command nuxt build · Nuxt default + Output Directory .output · Nuxt output + +Building locally... + Built 1.0 MB +Uploading... +Deploying... +Live in 12.3s +https://.ewr.prisma.build +``` + +Verify the live app: open the URL to see the rendered user list, or hit the API route: + +```bash +curl https://.ewr.prisma.build/api/users +``` + +The first deploy asks you to pick or create a project (pass `--create-project my-app` to skip the prompt), pins the directory to it in a gitignored `.prisma/local.json`, and promotes to production. For previews per Git branch and deploy-on-push, see [Deploy your first app](/prisma-compute/deploy). + ## Next steps - Change the schema in `src/prisma/contract.prisma`, then run `npm run contract:emit` and `npm run db:update`. diff --git a/apps/docs/content/docs/guides/next/frameworks/sveltekit.mdx b/apps/docs/content/docs/guides/next/frameworks/sveltekit.mdx index e28ca489cc..4b19722f66 100644 --- a/apps/docs/content/docs/guides/next/frameworks/sveltekit.mdx +++ b/apps/docs/content/docs/guides/next/frameworks/sveltekit.mdx @@ -17,20 +17,38 @@ Every command below was run end to end against a live [Prisma Postgres](/postgre One command scaffolds the project with Prisma Next wired in: ```npm -npx create-prisma@next --template svelte --provider postgres +npx create-prisma@next create my-app --template svelte --provider postgres ``` Pick Prisma Postgres at the database prompt to have a database created for you, or paste your own `DATABASE_URL`. ## Prerequisites -- [Node.js](https://nodejs.org) v20.19 or later +- [Node.js](https://nodejs.org) 24 or later - A PostgreSQL connection string, or nothing at all: the scaffold can create the database for you +## Use with your agent + +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: + + + +```text +Create a new SvelteKit app with Prisma Next, seed it, and verify the page renders. + +1. Scaffold: `npx create-prisma@next create my-app --template svelte --provider postgres --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-app`, run `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun. +3. Do not deploy to Prisma Compute; it does not support SvelteKit yet. Start `npm run dev` in the background, wait until it reports ready, verify http://localhost:5173 lists the three seeded users, then stop the dev server, following https://www.prisma.io/docs/guides/next/frameworks/sveltekit.md. + +Use the installed Prisma Next skills. +``` + + + ## 1. Scaffold and enter the project ```npm -npx create-prisma@next --template svelte --provider postgres +npx create-prisma@next create my-app --template svelte --provider postgres cd my-app ``` @@ -48,6 +66,12 @@ npm run db:seed Seeded 3 users. ``` +:::note + +Seeing `Cannot read properties of undefined (reading 'where')`? The current `svelte` template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun `db:seed`. + +::: + `db:init` applies your schema (`src/prisma/contract.prisma`) to the database and signs it; the seed gives the first page something to show. ## 3. Run and verify @@ -60,12 +84,15 @@ Open [http://localhost:5173](http://localhost:5173). The page lists the seeded u ## Where things live -- `src/routes/+page.server.ts`: the server `load` function that queries users +- `src/routes/+page.server.ts`: the server `load` function that fetches users - `src/routes/+page.svelte`: the page that renders them -- `src/prisma/db.ts`: the Prisma Next client the load function imports +- `src/prisma/users.ts`: the `listUsers` query helper the load function imports +- `src/prisma/db.ts`: the Prisma Next client behind that helper Model access is namespace-qualified on PostgreSQL: `db.orm.public.User`. The [Prisma Next overview](/orm/next) covers the contract-first model behind it. +[Prisma Compute](/compute) does not support SvelteKit deployments yet; see [Deploy your first app](/prisma-compute/deploy) for what is currently supported. In the meantime, the app deploys to SvelteKit's usual hosts through its standard adapters. + ## Next steps - Change the schema in `src/prisma/contract.prisma`, then run `npm run contract:emit` and `npm run db:update`. diff --git a/apps/docs/content/docs/guides/next/frameworks/tanstack-start.mdx b/apps/docs/content/docs/guides/next/frameworks/tanstack-start.mdx index 8be51d4a64..26a936a342 100644 --- a/apps/docs/content/docs/guides/next/frameworks/tanstack-start.mdx +++ b/apps/docs/content/docs/guides/next/frameworks/tanstack-start.mdx @@ -1,14 +1,14 @@ --- title: TanStack Start -description: Set up Prisma Next in a TanStack Start app with create-prisma, from scaffold to rendered data. +description: Set up Prisma Next in a TanStack Start app with create-prisma, from scaffold to rendered data, and deploy it to Prisma Compute. url: /guides/next/frameworks/tanstack-start metaTitle: How to use Prisma Next with TanStack Start -metaDescription: Scaffold a TanStack Start project with Prisma Next and Prisma Postgres, initialize the database, seed it, and see your data, with tested commands. +metaDescription: Scaffold a TanStack Start project with Prisma Next and Prisma Postgres, seed it, render your data, and deploy to Prisma Compute, with tested commands. --- ## Introduction -This guide shows you how to use Prisma Next in a TanStack Start app. You scaffold a project where a server function queries your database and a route loader feeds it to the page, initialize the schema, and see your data. +This guide shows you how to use Prisma Next in a TanStack Start app. You scaffold a project where a server function queries your database and a route loader feeds it to the page, initialize the schema, see your data, and deploy the app to [Prisma Compute](/compute). Every command below was run end to end against a live [Prisma Postgres](/postgres) database. @@ -17,20 +17,40 @@ Every command below was run end to end against a live [Prisma Postgres](/postgre One command scaffolds the project with Prisma Next wired in: ```npm -npx create-prisma@next --template tanstack-start --provider postgres +npx create-prisma@next create my-app --template tanstack-start --provider postgres ``` Pick Prisma Postgres at the database prompt to have a database created for you, or paste your own `DATABASE_URL`. ## Prerequisites -- [Node.js](https://nodejs.org) v20.19 or later +- [Node.js](https://nodejs.org) 24 or later - A PostgreSQL connection string, or nothing at all: the scaffold can create the database for you +## Use with your agent + +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: + + + +```text +Create a new TanStack Start app with Prisma Next, seed it, and deploy it to Prisma Compute. + +1. Scaffold: `npx create-prisma@next create my-app --template tanstack-start --provider postgres --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-app`, run `npm run db:init`, then `npm run db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun. +3. Start `npm run dev` in the background, wait until it reports ready, verify http://localhost:3000 renders the three seeded users, then stop the dev server. +4. Prepare the deploy build: install `nitro` and enable the `nitro()` Vite plugin for builds only, following https://www.prisma.io/docs/guides/next/frameworks/tanstack-start.md. +5. Deploy: check `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`. Then run `npx @prisma/cli@latest app deploy --create-project my-app --env .env` and verify the live URL renders the seeded users. + +Use the installed Prisma Next skills. +``` + + + ## 1. Scaffold and enter the project ```npm -npx create-prisma@next --template tanstack-start --provider postgres +npx create-prisma@next create my-app --template tanstack-start --provider postgres cd my-app ``` @@ -50,6 +70,12 @@ Seeded 3 users. `db:init` applies your schema (`src/prisma/contract.prisma`) to the database and signs it; the seed gives the first page something to show. +:::note + +Seeing `Cannot read properties of undefined (reading 'where')`? The current `tanstack-start` template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts` and `src/prisma/users.ts`, then rerun `db:seed`. The home page reads through `src/prisma/users.ts`, so until both files are updated it shows "Could not query users yet" instead of the user list. + +::: + ## 3. Run and verify ```npm @@ -58,6 +84,66 @@ npm run dev Open [http://localhost:3000](http://localhost:3000). The page lists the seeded users, provided by the route loader's server function. +## 4. Deploy to Prisma Compute + +TanStack Start is supported on [Prisma Compute](/compute), so the app can go from your terminal to a live URL. The Compute build expects Nitro's `.output` directory, and the template builds with plain Vite, so first install the `nitro` package (not `nitropack`): + +```npm +npm install nitro +``` + +Then enable `nitro()` from `nitro/vite` for builds only: + +```ts title="vite.config.ts" +import { prismaVitePlugin } from "@prisma-next/vite-plugin-contract-emit"; +import { defineConfig } from "vite"; +import viteReact from "@vitejs/plugin-react"; +import { tanstackStart } from "@tanstack/react-start/plugin/vite"; +import { nitro } from "nitro/vite"; +import tsconfigPaths from "vite-tsconfig-paths"; + +export default defineConfig(({ command }) => ({ + plugins: [ + prismaVitePlugin(), + tsconfigPaths({ projects: ["./tsconfig.json"] }), + tanstackStart(), + ...(command === "build" ? [nitro()] : []), + viteReact(), + ], +})); +``` + +The Nitro plugin is enabled for builds only because it conflicts with the contract watcher in the dev server; `npm run dev` keeps working unchanged. + +Sign in once (it opens a browser): + +```npm +npx @prisma/cli@latest auth login +``` + +Then deploy from the project directory. The `--env .env` flag passes your `DATABASE_URL` to the deployment, so the live app reads the same database: + +```npm +npx @prisma/cli@latest app deploy --env .env +``` + +```text no-copy +First deploy of "my-app" -- promoting to production. + +Build settings + Build Command npm run build · package.json scripts.build + Output Directory .output · TanStack Start output + +Building locally... + Built 0.5 MB +Uploading... +Deploying... +Live in 9.4s +https://.ewr.prisma.build +``` + +Open the live URL: the page renders the same seeded users, served from your Prisma Postgres database. The first deploy asks you to pick or create a project (pass `--create-project my-app` to skip the prompt), pins the directory to it in a gitignored `.prisma/local.json`, and promotes to production. For previews per Git branch and deploy-on-push, see [Deploy your first app](/prisma-compute/deploy). + ## Where things live - `src/routes/index.tsx`: the route: a `createServerFn` queries users, the loader passes them to the page diff --git a/apps/docs/content/docs/guides/next/runtimes/bun.mdx b/apps/docs/content/docs/guides/next/runtimes/bun.mdx index 630ead7a80..328d5daac6 100644 --- a/apps/docs/content/docs/guides/next/runtimes/bun.mdx +++ b/apps/docs/content/docs/guides/next/runtimes/bun.mdx @@ -1,14 +1,14 @@ --- title: Bun -description: Scaffold a Prisma Next app with Bun, initialize your database, and run your first typed query. +description: Scaffold a Prisma Next app with Bun, run your first typed query, serve users over HTTP, and deploy to Prisma Compute. url: /guides/next/runtimes/bun metaTitle: How to use Prisma Next with Bun -metaDescription: Set up a Prisma Next project with Bun and Prisma Postgres, from scaffold to first query, with tested commands and real output. +metaDescription: Set up a Prisma Next project with Bun and Prisma Postgres, from scaffold to first typed query, then serve users over HTTP and deploy to Prisma Compute. --- ## Introduction -In this guide, you scaffold a Prisma Next project with Bun, initialize a PostgreSQL database from your schema, and run your first typed query. Bun runs TypeScript directly, so there is no build step anywhere in the flow. +In this guide, you scaffold a Prisma Next project with Bun, initialize a PostgreSQL database from your schema, run your first typed query, serve query results over HTTP with `Bun.serve`, and deploy the server to [Prisma Compute](/compute). Bun runs TypeScript directly, so there is no build step anywhere in the flow. Every command and code sample below was run end to end against a live Prisma Postgres database. @@ -17,12 +17,32 @@ Every command and code sample below was run end to end against a live Prisma Pos - [Bun](https://bun.sh/) 1.1 or later (`bun --version`) - A PostgreSQL connection string, or nothing at all: the scaffold can create a [Prisma Postgres](/postgres) database for you +## Use with your agent + +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: + + + +```text +Create a new Bun app with Prisma Next, run a first typed query, and deploy it to Prisma Compute. + +1. Scaffold: `bunx create-prisma@next create my-bun-app --template minimal --provider postgres --package-manager bun --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-bun-app`, run `bun run contract:emit`, then `bun run db:init`. If any script fails with `undefined is not an object (evaluating 'db.orm.User.where')`, change `db.orm.User` to `db.orm.public.User` in `src/index.ts`, `src/prisma/seed.ts`, and `src/prisma/users.ts`, then rerun. +3. Replace `src/index.ts` with a script that creates a user and reads all users back via `db.orm.public.User`, following https://www.prisma.io/docs/guides/next/runtimes/bun.md, and verify `bun run dev` prints the created user. +4. Add `src/server.ts` with a `Bun.serve` server exposing GET /users, and verify `curl http://localhost:3000/users` returns the users. +5. Deploy: check `npx @prisma/cli@latest auth whoami`; if I am not signed in, stop and ask me to run `npx @prisma/cli@latest auth login`. Then run `npx @prisma/cli@latest app deploy --create-project my-bun-app --env .env --framework bun --entry src/server.ts` and verify the live URL's /users endpoint. + +Use the installed Prisma Next skills. +``` + + + ## 1. Scaffold the project Create the project with `create-prisma`. Pick Bun as the package manager when prompted, or pass everything up front: ```bash -bunx create-prisma@next create my-bun-app --provider postgres --package-manager bun +bunx create-prisma@next create my-bun-app --template minimal --provider postgres --package-manager bun ``` When the prompt asks about the database, pick Prisma Postgres to have one created for you, or paste your own `DATABASE_URL`. The scaffold writes the connection string to `.env`, sets up `src/prisma/` with a starter schema, and installs dependencies with Bun. @@ -52,6 +72,12 @@ If `db:init` reports that the contract file is missing, run `bun run contract:em Replace `src/index.ts` with a script that creates a user and reads every user back. Model access is namespace-qualified on PostgreSQL: `db.orm.public.User`, where `public` is the default schema. +:::note + +The scaffolded `src/index.ts`, `src/prisma/seed.ts`, and `src/prisma/users.ts` still use the older unqualified form `db.orm.User`, which fails under Bun with `TypeError: undefined is not an object (evaluating 'db.orm.User.where')`. Replacing `src/index.ts` below fixes the script you run here; if you also want `bun run db:seed`, update `db.orm.User` to `db.orm.public.User` in the other two files first. + +::: + ```ts title="src/index.ts" import { db } from "./prisma/db"; @@ -65,10 +91,10 @@ console.log(`created user ${user.email}`); const users = await db.orm.public.User.select("id", "email", "name").all(); console.log(`there are now ${users.length} users`); -await db.close(); +await db.runtime().close(); ``` -`await db.close()` at the end lets the script exit cleanly; without it, the connection pool keeps the process alive. +`await db.runtime().close()` at the end lets the script exit cleanly; without it, the connection pool keeps the process alive. ## 4. Run it @@ -77,18 +103,90 @@ bun run dev ``` ```text no-copy -created user ada+1783380852695@prisma.io -there are now 2 users +created user ada+1784893846026@prisma.io +there are now 1 users ``` +The `pg` driver may print an SSL mode deprecation warning above the output; it comes from the `sslmode=require` setting in the generated connection string and does not affect the query. + That is the whole loop: schema to contract, contract to database, typed queries against both. +## 5. Serve it over HTTP + +The script pattern works for one-off jobs. To keep the app running and serve query results, add a small HTTP server with `Bun.serve`. Create `src/server.ts`: + +```ts title="src/server.ts" +import { db } from "./prisma/db"; + +const server = Bun.serve({ + port: Number(process.env.PORT ?? 3000), + async fetch(req) { + const { pathname } = new URL(req.url); + if (pathname === "/users") { + const users = await db.orm.public.User.select("id", "email", "name").all(); + return Response.json(users); + } + return new Response("Not found", { status: 404 }); + }, +}); + +console.log(`Listening on http://localhost:${server.port}`); +``` + +Start it and check the endpoint: + +```bash +bun src/server.ts +``` + +```bash +curl http://localhost:3000/users +``` + +```json no-copy +[{ "id": 1, "email": "ada+1784893846026@prisma.io", "name": "Ada Lovelace" }] +``` + +The server listens on port 3000; set `PORT` to change it. Unlike the script, the server never calls `db.runtime().close()`: the connection pool is shared across requests and closes when the process exits. + +## 6. Deploy to Prisma Compute + +Plain Bun servers are supported on [Prisma Compute](/compute), so the server can go from your terminal to a live URL in one command. Sign in once (it opens a browser): + +```npm +npx @prisma/cli@latest auth login +``` + +Then deploy from the project directory. A plain Bun app has no framework for the CLI to detect, so pass the entrypoint explicitly. The `--env .env` flag passes your `DATABASE_URL` to the deployment, so the live server talks to the same database: + +```npm +npx @prisma/cli@latest app deploy --env .env --framework bun --entry src/server.ts +``` + +```text no-copy +First deploy of "my-bun-app" -- promoting to production. +Building locally... + Built 0.8 MB +Uploading... +Deploying... +Live in 6.1s +https://.ewr.prisma.build +``` + +Verify the live endpoint returns your users: + +```bash +curl https://.ewr.prisma.build/users +``` + +The first deploy asks you to pick or create a project (pass `--create-project my-bun-app` to skip the prompt), pins the directory to it in a gitignored `.prisma/local.json`, and promotes to production. For previews per Git branch and deploy-on-push, see [Deploy your first app](/prisma-compute/deploy). + ## Prompt your coding agent The scaffold installs [Prisma Next skills](/ai/tools/skills#available-skills-for-prisma-next) for your coding agent. Prompts that map to this guide: - "Using the prisma-next-queries skill, add a script that lists the 10 newest users." -- "Add a Post model related to User, emit the contract, and update the database." +- "Add a published flag to the Post model in the starter contract, emit the contract, and update the database." ## Next steps diff --git a/apps/docs/content/docs/guides/next/runtimes/deno.mdx b/apps/docs/content/docs/guides/next/runtimes/deno.mdx index 5d9f8287fe..9ab00f6c7e 100644 --- a/apps/docs/content/docs/guides/next/runtimes/deno.mdx +++ b/apps/docs/content/docs/guides/next/runtimes/deno.mdx @@ -8,7 +8,7 @@ metaDescription: Set up a Prisma Next project on Deno with Prisma Postgres, from ## Introduction -In this guide, you scaffold a Prisma Next project for Deno, initialize a PostgreSQL database, and run your first typed query. Deno runs TypeScript natively and installs npm packages on demand, so the flow is close to the [Bun guide](/guides/next/runtimes/bun) with two Deno-specific differences this guide calls out: explicit import extensions and permission flags. +In this guide, you scaffold a Prisma Next project for Deno, initialize and seed a PostgreSQL database, and run your first typed query. Deno runs TypeScript natively and installs npm packages on demand, so the flow is close to the [Bun guide](/guides/next/runtimes/bun) with two Deno-specific differences this guide calls out: explicit import extensions and permission flags. Every command and code sample below was run end to end against a live Prisma Postgres database. @@ -17,12 +17,32 @@ Every command and code sample below was run end to end against a live Prisma Pos - [Deno](https://deno.com/) 2.0 or later (`deno --version`) - A PostgreSQL connection string, or nothing at all: the scaffold can create a [Prisma Postgres](/postgres) database for you +## Use with your agent + +Prefer to delegate this guide? Copy the prompt and hand it to your coding agent: + + + +```text +Create a new Prisma Next project on Deno, seed it, and run a first typed query. + +1. Scaffold: `deno run -A npm:create-prisma@next create my-deno-app --template minimal --provider postgres --package-manager deno --prisma-postgres --yes` (or pass `--database-url ""` instead of `--prisma-postgres` if I give you a connection string). +2. In `my-deno-app`, run `deno install`, then `deno run -A --env-file=.env npm:prisma-next contract emit` and `deno run -A --env-file=.env npm:prisma-next db init`. +3. Run `deno task db:seed`. If seeding fails with `Cannot read properties of undefined (reading 'where')`, change `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts`, `src/prisma/users.ts`, and `src/index.ts`, then rerun. +4. Replace `src/index.ts` with a script that creates a user and reads all users back, following https://www.prisma.io/docs/guides/next/runtimes/deno.md. Keep the `.ts` extension on relative imports. Verify `deno task dev` prints the created user and the user count. +5. Do not deploy to Prisma Compute; it does not support Deno yet. + +Use the installed Prisma Next skills. +``` + + + ## 1. Scaffold the project `create-prisma` supports Deno as a package manager choice: ```bash -deno run -A npm:create-prisma@next create my-deno-app --provider postgres --package-manager deno +deno run -A npm:create-prisma@next create my-deno-app --template minimal --provider postgres --package-manager deno ``` Pick Prisma Postgres at the database prompt to have a database created for you, or paste your own `DATABASE_URL`. The generated `package.json` scripts wrap every command in `deno run -A --env-file=.env`, so environment variables load without a dotenv import. @@ -39,11 +59,29 @@ deno run -A --env-file=.env npm:prisma-next contract emit deno run -A --env-file=.env npm:prisma-next db init ``` -The first command compiles `src/prisma/contract.prisma` into the contract your queries are type-checked against. The second creates the tables and signs the database. +The first command compiles `src/prisma/contract.prisma` into the contract your queries are type-checked against and prints a JSON summary with `"ok": true` and the emitted file paths. The second creates the tables and signs the database; it exits quietly on success. The `-A` flag grants the permissions the CLI needs (network for the database, filesystem for the generated files). To scope permissions tighter, start from `--allow-net --allow-read --allow-write --allow-env` and adjust to your setup. -## 3. Write your first query +## 3. Seed the database + +The scaffold wires a seed script to a Deno task: + +```bash +deno task db:seed +``` + +```text no-copy +Seeded 3 users. +``` + +:::note + +Seeing `Cannot read properties of undefined (reading 'where')`? The current template still generates the older unqualified query form. Update `db.orm.User` to `db.orm.public.User` in `src/prisma/seed.ts`, `src/prisma/users.ts`, and `src/index.ts`, then rerun `deno task db:seed`. + +::: + +## 4. Write your first query Replace `src/index.ts`. Two things to notice: Deno requires the `.ts` extension on relative imports, and model access is namespace-qualified on PostgreSQL (`db.orm.public.User`): @@ -60,22 +98,26 @@ console.log(`created user ${user.email}`); const users = await db.orm.public.User.select("id", "email", "name").all(); console.log(`there are now ${users.length} users`); -await db.close(); +await db.runtime().close(); ``` If you see `Module not found "file:///…/src/prisma/db"`, the import is missing its `.ts` extension. Deno does not resolve relative imports without an extension. -## 4. Run it +## 5. Run it ```bash deno task dev ``` ```text no-copy -created user grace+1783380988819@prisma.io -there are now 3 users +created user grace+1784893859312@prisma.io +there are now 4 users ``` +The count is the three seeded users plus the one this script created. + +[Prisma Compute](/compute) does not support Deno deployments yet; see [Deploy your first app](/prisma-compute/deploy) for what is currently supported. In the meantime, the app deploys to Deno's usual hosts, such as Deno Deploy or any server that runs the Deno CLI. + ## Common gotchas :::warning diff --git a/apps/docs/content/docs/orm/index.mdx b/apps/docs/content/docs/orm/index.mdx index b0920d3aec..8bb4b7bd52 100644 --- a/apps/docs/content/docs/orm/index.mdx +++ b/apps/docs/content/docs/orm/index.mdx @@ -3,7 +3,7 @@ title: Prisma ORM description: 'Prisma ORM is a next-generation Node.js and TypeScript ORM that provides type-safe database access, migrations, and a visual data editor.' url: /orm metaTitle: What is Prisma ORM? (Overview) -metaDescription: This page gives a high-level overview of what Prisma ORM is and how it works. It's a great starting point for Prisma newcomers +metaDescription: Prisma ORM is a next-generation Node.js and TypeScript ORM that provides type-safe database access, migrations, and a visual data editor. --- Prisma ORM is [open-source](https://github.com/prisma/prisma) and consists of: @@ -16,10 +16,42 @@ Prisma Client works with any Node.js or TypeScript backend, whether you're deplo :::tip[Try Prisma Next] -Prisma Next is the next major version of Prisma ORM, available now in Early Access. Start with the [Prisma Next getting started guide](/next) and share feedback in [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text). +Prisma Next is the next major version of Prisma ORM, available now in Early Access. Start with the [Prisma Next getting started guide](/next) and share feedback in [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text). This section documents Prisma 7, the current generally available release. ::: +## Get started + + + }> + Prisma ORM 7 with Prisma Postgres in about 5 minutes. + + }> + Introspect your database and start querying with Prisma ORM 7. + + }> + The Early Access docs for the next major version. + + + +Working with a coding agent? Copy the prompt below, or start from the [getting started page](/) for the full stack. + + + +```text +Add Prisma ORM 7 to this project with my existing database. + +If I have not given you a database connection string and none exists in the project, stop and ask. + +1. Run `npx prisma@latest init` (Prisma 7). For an existing database, set DATABASE_URL in `.env` and introspect it with `npx prisma db pull`; for a new schema, define models in `prisma/schema.prisma` and run `npx prisma migrate dev --name init`. If migrate dev asks to reset the database, stop and ask me first. +2. Install the driver adapter for the database (Prisma 7 requires one), e.g. `npm install @prisma/adapter-pg` for PostgreSQL, and pass it to `new PrismaClient({ adapter })`. Generate the client with `npx prisma generate` and write one query in an existing code path. +3. Run the query (e.g. with `npx tsx`) and show me the output, the schema, and the query you added. + +Current docs: https://www.prisma.io/docs/orm.md and https://www.prisma.io/docs/llms.txt. +``` + + + ## Why Prisma ORM Traditional database tools force a tradeoff between **productivity** and **control**. Raw SQL gives full control but is error-prone and lacks type safety. Traditional ORMs improve productivity but abstract too much, leading to the [object-relational impedance mismatch](https://en.wikipedia.org/wiki/Object-relational_impedance_mismatch) and performance pitfalls like the n+1 problem. @@ -145,9 +177,8 @@ const user = await prisma.user.create({ }, }); ``` -:::note +:::note[Prisma 7 Connection Requirements] -### Prisma 7 Connection Requirements Starting with **Prisma 7**, providing a [driver adapter](/orm/core-concepts/supported-databases/database-drivers) is mandatory for direct database connections. This change standardizes database connectivity across Node.js, Serverless, and Edge environments. If you use Prisma Accelerate, instantiate Prisma Client with `accelerateUrl` and the Accelerate extension instead of a driver adapter. diff --git a/apps/docs/content/docs/orm/next/index.mdx b/apps/docs/content/docs/orm/next/index.mdx index cde3e17e4b..f4b2e3729c 100644 --- a/apps/docs/content/docs/orm/next/index.mdx +++ b/apps/docs/content/docs/orm/next/index.mdx @@ -3,7 +3,7 @@ title: Prisma Next description: A look at Prisma Next, a ground-up rethink of Prisma that improves queries, extensibility, migrations, and AI-friendly workflows while keeping Prisma’s schema-first approach. url: /orm/next metaTitle: What is Prisma Next? -metaDescription: A look at Prisma Next, a ground-up rethink of Prisma that improves queries, extensibility, migrations, and AI-friendly workflows while keeping Prisma’s schema-first approach. +metaDescription: Prisma Next is a ground-up rethink of Prisma ORM with better queries, extensibility, migrations, and AI-friendly workflows, keeping the schema-first approach. badge: early-access --- @@ -42,6 +42,20 @@ Scaffold a new project in one command: npx create-prisma@next ``` +## Get started + + + }> + Scaffold a Prisma Next app with PostgreSQL, seed it, and run your first query. + + }> + Add Prisma Next to an existing app with `prisma-next init`. + + }> + Prisma Next with Prisma Postgres and a Prisma Compute deploy, with guide and agent options. + + + ### Supported databases Prisma Next ships first-class support for **PostgreSQL** (the primary target, on track for general availability) and **MongoDB**. **SQLite** is the next SQL target on deck, with **MySQL** to follow. diff --git a/apps/docs/content/docs/orm/v6/overview/introduction/what-is-prisma.mdx b/apps/docs/content/docs/orm/v6/overview/introduction/what-is-prisma.mdx index 5c48886eed..11334cc17f 100644 --- a/apps/docs/content/docs/orm/v6/overview/introduction/what-is-prisma.mdx +++ b/apps/docs/content/docs/orm/v6/overview/introduction/what-is-prisma.mdx @@ -2,7 +2,7 @@ title: What is Prisma ORM? description: This page gives a high-level overview of what Prisma ORM is and how it works. It's a great starting point for Prisma newcomers! url: /orm/v6/overview/introduction/what-is-prisma -metaTitle: What is Prisma ORM? (Overview) +metaTitle: What is Prisma ORM? (Prisma 6 overview) metaDescription: This page gives a high-level overview of what Prisma ORM is and how it works. It's a great starting point for Prisma newcomers! --- diff --git a/apps/docs/content/docs/postgres/index.mdx b/apps/docs/content/docs/postgres/index.mdx index 49bd09ec32..916b0de037 100644 --- a/apps/docs/content/docs/postgres/index.mdx +++ b/apps/docs/content/docs/postgres/index.mdx @@ -22,17 +22,36 @@ Everything below is included with every Prisma Postgres database. No extra servi ### Create a database -New to Prisma Postgres? Start here. +New to Prisma Postgres? Start here. In the [recommended stack](/), Prisma Postgres is the database behind a [Prisma Next](/next) app, and [Prisma Compute](/compute) later runs that app next to it. - - Create a temporary Prisma Postgres database in one command. + }> + Scaffold a Prisma Next app and let setup provision Prisma Postgres. - - Set up Prisma ORM and connect it to Prisma Postgres. + }> + Create a temporary Prisma Postgres database in one command, no account needed. + + }> + Set up Prisma ORM 7, the current GA release, and connect it to Prisma Postgres. +Working with a coding agent? Copy this prompt: + + + +```text +Create a Prisma Postgres database for this project. + +1. Run `npx create-db@latest`. It creates a temporary Prisma Postgres database without an account and prints a connection string plus a claim URL. +2. Put the connection string in `.env` as DATABASE_URL and wire it into whichever of Prisma ORM, Kysely, Drizzle, TypeORM, or node-postgres the project already uses (detect it from package.json; if none, ask me). Verify the connection with one trivial query such as `select 1`. +3. Remind me to open the claim URL to keep the database in my Prisma workspace. + +Current docs: https://www.prisma.io/docs/postgres.md. +``` + + + ### Get your connection string In [Prisma Console](https://console.prisma.io), open your database and click **Connect to your database** to copy connection URLs. diff --git a/apps/docs/cspell.json b/apps/docs/cspell.json index 95c02a558a..7a0c5afc51 100644 --- a/apps/docs/cspell.json +++ b/apps/docs/cspell.json @@ -425,7 +425,12 @@ "Yewande", "yourapp", "yourdb", - "Zenstack" + "Zenstack", + "astrodark", + "nuxtjs", + "quickstarts", + "Quickstarts", + "nitropack" ], "patterns": [ { diff --git a/apps/docs/public/img/technologies/bun.svg b/apps/docs/public/img/technologies/bun.svg new file mode 100644 index 0000000000..e3557d78c1 --- /dev/null +++ b/apps/docs/public/img/technologies/bun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/docs/public/img/technologies/deno.svg b/apps/docs/public/img/technologies/deno.svg new file mode 100644 index 0000000000..5d107cff2e --- /dev/null +++ b/apps/docs/public/img/technologies/deno.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/docs/public/img/technologies/hono.svg b/apps/docs/public/img/technologies/hono.svg new file mode 100644 index 0000000000..a22b917912 --- /dev/null +++ b/apps/docs/public/img/technologies/hono.svg @@ -0,0 +1 @@ +Hono Streamline Icon: https://streamlinehq.com \ No newline at end of file diff --git a/apps/docs/public/img/technologies/nestjs.svg b/apps/docs/public/img/technologies/nestjs.svg new file mode 100644 index 0000000000..ea7a6a73fa --- /dev/null +++ b/apps/docs/public/img/technologies/nestjs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/docs/public/img/technologies/prisma-postgres.svg b/apps/docs/public/img/technologies/prisma-postgres.svg new file mode 100644 index 0000000000..a82e9ee86a --- /dev/null +++ b/apps/docs/public/img/technologies/prisma-postgres.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/docs/public/img/technologies/tanstack.svg b/apps/docs/public/img/technologies/tanstack.svg new file mode 100644 index 0000000000..d320e4b938 --- /dev/null +++ b/apps/docs/public/img/technologies/tanstack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/docs/source.config.ts b/apps/docs/source.config.ts index d006716576..cc83c6ba40 100644 --- a/apps/docs/source.config.ts +++ b/apps/docs/source.config.ts @@ -55,6 +55,9 @@ export const docs = defineDocs({ metaDescription: z.string(), aiPrompt: z.string().optional(), noindex: z.boolean().optional(), + // Visually hides the docs sidebar on landing pages; the pages stay in + // navigation, search, sitemap, and llms.txt. + hideSidebar: z.boolean().optional(), }), postprocess: { includeProcessedMarkdown: true, diff --git a/apps/docs/src/app/(docs)/(default)/[[...slug]]/page.tsx b/apps/docs/src/app/(docs)/(default)/[[...slug]]/page.tsx index 7322fcb113..2ab5bc065a 100644 --- a/apps/docs/src/app/(docs)/(default)/[[...slug]]/page.tsx +++ b/apps/docs/src/app/(docs)/(default)/[[...slug]]/page.tsx @@ -30,9 +30,19 @@ export default async function Page({ params }: { params: Promise }) const aiPromptSlug = (page.data as { aiPrompt?: string }).aiPrompt; const promptContent = aiPromptSlug ? await getPromptContent(aiPromptSlug) : null; + const hideSidebar = (page.data as { hideSidebar?: boolean }).hideSidebar; return ( <> + {hideSidebar && ( + // Server-rendered so the sidebar never flashes in. Desktop-only: the + // mobile drawer stays available behind the hamburger. Pages remain in + // nav, search, sitemap, and llms.txt. + + )} {/* The hidden llms.txt directive for AI agents lives in the root layout (src/app/layout.tsx) as the first child of — agent-readiness audits require it near the top of the HTML, before the sidebar. */} diff --git a/apps/docs/src/components/getting-started.tsx b/apps/docs/src/components/getting-started.tsx new file mode 100644 index 0000000000..5a730a7ed1 --- /dev/null +++ b/apps/docs/src/components/getting-started.tsx @@ -0,0 +1,686 @@ +"use client"; +import { type MouseEventHandler, type ReactNode, useEffect, useRef, useState } from "react"; +import { + ArrowRight, + ArrowUpDown, + Check, + ChevronDown, + Copy, + Sparkles, + Terminal, + X, +} from "lucide-react"; +import posthog from "posthog-js"; +import { useCopyButton } from "fumadocs-ui/utils/use-copy-button"; +import { buttonVariants } from "@prisma-docs/ui/components/button"; +import { cn } from "@prisma-docs/ui/lib/cn"; +import { withDocsBasePath } from "@/lib/urls"; + +function copyText(container: HTMLElement | null): string { + const pre = container?.querySelector("pre"); + return (pre?.textContent ?? container?.textContent ?? "").trim(); +} + +/** Renders `backtick` spans in a plain-string prop as styled inline code. */ +function InlineCode({ text }: { text: string }) { + const parts = text.split(/`([^`]+)`/g); + return ( + <> + {parts.map((part, i) => + i % 2 === 1 ? ( + + {part} + + ) : ( + part + ), + )} + + ); +} + +/** + * Native-dialog modal for reading a full prompt. Overlays the page, so + * opening it never shifts the layout. Content stays mounted (display: none + * while closed), so prompts remain in the served HTML for crawlers/agents. + */ +function PromptModal({ + open, + onClose, + title, + checked, + onCopy, + children, +}: { + open: boolean; + onClose: () => void; + title: string; + checked: boolean; + onCopy: MouseEventHandler; + children: ReactNode; +}) { + const ref = useRef(null); + useEffect(() => { + const dialog = ref.current; + if (!dialog) return; + if (open && !dialog.open) dialog.showModal(); + if (!open && dialog.open) dialog.close(); + }, [open]); + return ( + { + if (e.target === ref.current) onClose(); + }} + className="m-auto w-[min(48rem,calc(100vw-2rem))] rounded-xl border bg-fd-card p-0 text-fd-foreground shadow-xl backdrop:bg-black/50" + > +
+ {title} + + +
+
+ {children} +
+
+ ); +} + +/** + * A collapsed, copyable agent prompt. The prompt itself is authored as a + * regular fenced code block child, so it stays in the DOM for crawlers and in + * the generated .md / llms output for agents; visually it collapses into a + * single row with copy and view actions. Viewing opens a modal, so the row + * never pushes the content below it around. + */ +export function AgentPrompt({ + title = "Use with your agent", + guideHref, + guideTitle = "Guide", + icon, + children, +}: { + title?: string; + guideHref?: string; + guideTitle?: string; + icon?: ReactNode; + children: ReactNode; +}) { + const bodyRef = useRef(null); + const [open, setOpen] = useState(false); + const [checked, onCopy] = useCopyButton(async () => { + await navigator.clipboard.writeText(copyText(bodyRef.current)); + posthog.capture("docs:copy_prompt", { page_path: window.location.pathname }); + }); + + return ( +
+
+ + {title} + {guideHref && ( + + {guideTitle} + + )} + + +
+ setOpen(false)} + title={title} + checked={checked} + onCopy={onCopy} + > +
{children}
+
+
+ ); +} + +/** + * A row that opens arbitrary content in a modal instead of expanding inline, + * so revealing it never shifts the layout below. The content stays mounted + * inside the (closed) dialog, so it remains in the served HTML for crawlers + * and in the generated .md / llms output. + */ +export function ModalRow({ + title, + description, + modalTitle, + icon, + children, +}: { + title: string; + description?: string; + modalTitle?: string; + icon?: ReactNode; + children: ReactNode; +}) { + const [open, setOpen] = useState(false); + const dialogRef = useRef(null); + useEffect(() => { + const dialog = dialogRef.current; + if (!dialog) return; + if (open && !dialog.open) dialog.showModal(); + if (!open && dialog.open) dialog.close(); + }, [open]); + + return ( +
+
+ + + {title} + {description && ( + {description} + )} + + +
+ setOpen(false)} + onClick={(e) => { + if (e.target === dialogRef.current) setOpen(false); + }} + className="m-auto w-[min(48rem,calc(100vw-2rem))] rounded-xl border bg-fd-card p-0 text-fd-foreground shadow-xl backdrop:bg-black/50" + > +
+ {modalTitle ?? title} + +
+
+ {children} +
+
+
+ ); +} + +/** + * Compact launcher row for the condensed journey: a button opens a modal with + * AI Prompt and CLI tabs, and a copy action grabs the prompt without opening + * anything. The prompt is a fenced code block child that stays mounted inside + * the (closed) dialog, so it remains in the served HTML for crawlers and in + * the generated .md / llms output; the CLI commands are passed as a + * newline-separated string and mirrored into .md by the markdown pipeline. + */ +export function GetStartedTabs({ cli, children }: { cli: string; children: ReactNode }) { + const [tab, setTab] = useState<"prompt" | "cli">("prompt"); + const [open, setOpen] = useState(false); + const promptRef = useRef(null); + const dialogRef = useRef(null); + useEffect(() => { + const dialog = dialogRef.current; + if (!dialog) return; + if (open && !dialog.open) dialog.showModal(); + if (!open && dialog.open) dialog.close(); + }, [open]); + + const [rowChecked, onRowCopy] = useCopyButton(async () => { + await navigator.clipboard.writeText(copyText(promptRef.current)); + posthog.capture("docs:copy_prompt", { page_path: window.location.pathname, tab: "prompt" }); + }); + const [modalChecked, onModalCopy] = useCopyButton(async () => { + const text = tab === "cli" ? cli : copyText(promptRef.current); + await navigator.clipboard.writeText(text); + posthog.capture("docs:copy_prompt", { page_path: window.location.pathname, tab }); + }); + + const tabButton = (value: "prompt" | "cli", icon: ReactNode, label: string) => ( + + ); + + return ( +
+
+ + + AI prompt and CLI steps + + One journey scaffolds, seeds, migrates, and deploys the whole stack. + + + + +
+ setOpen(false)} + onClick={(e) => { + if (e.target === dialogRef.current) setOpen(false); + }} + className="m-auto w-[min(48rem,calc(100vw-2rem))] rounded-xl border bg-fd-card p-0 text-fd-foreground shadow-xl backdrop:bg-black/50" + > +
+ {tabButton("prompt",
+
+
+ {cli.split("\n").map((line, i) => + line.startsWith("#") ? ( + + {line.replace(/^#\s*/, "")} + + ) : ( + + $ + {line} + + ), + )} +
+
+
+ {children} +
+
+
+ ); +} + +/** + * Two-column section: heading and blurb on the left, content on the right. + * Stacks on small screens. + */ +export function SectionRow({ + title, + description, + children, +}: { + title: string; + description?: string; + children: ReactNode; +}) { + const id = title + .toLowerCase() + .replace(/[^a-z0-9\s-]/g, "") + .trim() + .replace(/\s+/g, "-"); + return ( +
+
+

+ + {title} + +

+ {description && ( +

+ +

+ )} +
+
+ {children} +
+
+ ); +} + +/** Grid wrapper for IconLink items. */ +export function IconGrid({ columns = 2, children }: { columns?: 2 | 3; children: ReactNode }) { + return ( +
+ {children} +
+ ); +} + +function IconTile({ + src, + darkSrc, + invertDark, + mono, + icon, + className, +}: { + src?: string; + darkSrc?: string; + invertDark?: boolean; + mono?: string; + icon?: ReactNode; + className?: string; +}) { + return ( + + ); +} + +/** + * Compact horizontal link: a small icon tile plus a label, in the style of + * framework pickers. Icon can be an image (src), a mono letter fallback, or a + * passed element (e.g. a lucide icon). + */ +export function IconLink({ + href, + title, + src, + darkSrc, + invertDark, + mono, + icon, + description, + badge, +}: { + href: string; + title: string; + src?: string; + darkSrc?: string; + invertDark?: boolean; + mono?: string; + icon?: ReactNode; + description?: string; + badge?: string; +}) { + return ( + + + + + {title} + {badge && ( + + {badge} + + )} + + {description && ( + {description} + )} + + + ); +} + +/** Hero layout: pitch and actions on the left, the stack diagram on the right. */ +export function HeroGrid({ children }: { children: ReactNode }) { + return ( +
+ {children} +
+ ); +} + +/** Left side of the hero: badge, pitch, and CTA buttons. */ +export function HeroPitch({ + badge, + children, + primaryHref, + primaryLabel, + secondaryHref, + secondaryLabel, +}: { + badge?: string; + children: ReactNode; + primaryHref: string; + primaryLabel: string; + secondaryHref?: string; + secondaryLabel?: string; +}) { + return ( +
+ {badge && ( + + + )} +
+ {children} +
+
+ + {primaryLabel} + + {secondaryHref && secondaryLabel && ( + + {secondaryLabel} + + )} +
+
+ ); +} + +/** + * One product layer inside the StackDiagram. Purely illustrative — the hero + * copy carries the links — so it renders as a static tile with no click or + * hover affordance. The description is the element's children so it survives + * into the .md / llms output. + */ +export function StackLayer({ + title, + src, + invertDark, + icon, + children, +}: { + title: string; + src?: string; + invertDark?: boolean; + icon?: ReactNode; + children?: ReactNode; +}) { + return ( +
+ + + {title} + {children} + +
+ ); +} + +/** + * Visual of the Prisma stack: linked product layers joined by connectors. + * Children are StackLayer elements. + */ +export function StackDiagram({ caption, children }: { caption?: string; children: ReactNode }) { + const layers = Array.isArray(children) ? children : [children]; + return ( +
+
+ {layers + .filter((child) => child != null && child !== "\n") + .map((child, i) => ( +
+ {i > 0 && ( + + )} + {child} +
+ ))} +
+ {caption && ( +
{caption}
+ )} +
+ ); +} diff --git a/apps/docs/src/components/page-actions.tsx b/apps/docs/src/components/page-actions.tsx index fdded71bde..ff4c99da0d 100644 --- a/apps/docs/src/components/page-actions.tsx +++ b/apps/docs/src/components/page-actions.tsx @@ -10,39 +10,12 @@ import { cva } from "class-variance-authority"; const cache = new Map(); function toIndexMarkdownUrl(markdownUrl: string): string | null { - console.log(markdownUrl); - - // if (!markdownUrl.endsWith('.mdx')) return `${markdownUrl.replace(/\/$/, '')}/index.mdx`; - const withoutExtension = markdownUrl.slice(0, -".mdx".length); if (withoutExtension.endsWith("/index")) return null; return `${withoutExtension}/index.mdx`; } -async function fetchMarkdownWithFallback( - markdownUrl: string, -): Promise<{ content: string; resolvedUrl: string }> { - const res = await fetch(markdownUrl); - if (res.ok) { - return { content: await res.text(), resolvedUrl: markdownUrl }; - } - - const fallbackUrl = toIndexMarkdownUrl(markdownUrl); - if (!fallbackUrl) { - throw new Error(`Failed to fetch markdown from ${markdownUrl} (${res.status})`); - } - - const fallbackRes = await fetch(fallbackUrl); - if (fallbackRes.ok) { - return { content: await fallbackRes.text(), resolvedUrl: fallbackUrl }; - } - - throw new Error( - `Failed to fetch markdown from ${markdownUrl} (${res.status}) and ${fallbackUrl} (${fallbackRes.status})`, - ); -} - export function CopyPromptButton({ fullPrompt }: { fullPrompt: string }) { const [checked, onClick] = useCopyButton(async () => { await navigator.clipboard.writeText(fullPrompt); @@ -177,6 +150,9 @@ export function ViewOptions({ { title: "Open in Claude", tool: "claude", + // claude.ai shows a caution banner on any link-prefilled prompt and + // waits for the user to confirm; the description sets that expectation. + description: "Claude previews the prompt and asks you to confirm", href: `https://claude.ai/new?${new URLSearchParams({ q, })}`, @@ -195,8 +171,11 @@ export function ViewOptions({ { title: "Open in T3 Chat", tool: "t3_chat", + // T3 Chat's default model can't fetch URLs on its own; search=true + // turns on web search so the "Read " prompt actually works. href: `https://t3.chat/new?${new URLSearchParams({ q, + search: "true", })}`, icon: , }, @@ -233,7 +212,14 @@ export function ViewOptions({ } > {item.icon} - {item.title} + + {item.title} + {"description" in item && item.description && ( + + {item.description} + + )} + ))} diff --git a/apps/docs/src/lib/llm-markdown.ts b/apps/docs/src/lib/llm-markdown.ts index f5f1f6ff59..a2653ec2ae 100644 --- a/apps/docs/src/lib/llm-markdown.ts +++ b/apps/docs/src/lib/llm-markdown.ts @@ -255,8 +255,9 @@ function formatYoutube(attrs: string) { * code fences inside `
` into indented fences that markdown consumers * (and the afdocs parity checker) no longer treat as code blocks. Dedenting the * body back to column 0 and collapsing the summary to a single bold line keeps - * the content faithful to the rendered page. Must run BEFORE fenced code blocks - * are protected, so the dedent applies to the fences themselves. + * the content faithful to the rendered page. Fences are already protected as + * indented placeholder tokens here; the prefix-aware restore in + * `protectFencedCodeBlocks` replays this dedent on the fence lines. */ function formatDetails(content: string) { const summaryMatch = content.match(/]*>([\s\S]*?)<\/summary>/); @@ -326,6 +327,44 @@ function formatButton(_attrs: string, content: string) { return stripJsxTags(trimComponentContent(content)); } +function formatStackLayer(attrs: string, content: string) { + const title = getAttribute(attrs, "title") ?? "Step"; + const href = getAttribute(attrs, "href"); + const text = stripJsxTags(trimComponentContent(content)).replace(/\n+/g, " "); + const label = href ? `[${title}](${href})` : title; + return `- **${label}**${text ? `: ${text}` : ""}`; +} + +function formatHeroPitch(attrs: string, content: string) { + const text = stripJsxTags(trimComponentContent(content)); + const links: string[] = []; + const primaryHref = getAttribute(attrs, "primaryHref"); + const primaryLabel = getAttribute(attrs, "primaryLabel"); + if (primaryHref && primaryLabel) links.push(`- [${primaryLabel}](${primaryHref})`); + const secondaryHref = getAttribute(attrs, "secondaryHref"); + const secondaryLabel = getAttribute(attrs, "secondaryLabel"); + if (secondaryHref && secondaryLabel) links.push(`- [${secondaryLabel}](${secondaryHref})`); + return [text, links.join("\n")].filter(Boolean).join("\n\n"); +} + +function formatGetStartedTabs(attrs: string, content: string) { + // cli may be a quoted string or a multiline template literal. + const cli = getAttribute(attrs, "cli") ?? attrs.match(/cli=\{\s*`([\s\S]*?)`\s*\}/)?.[1]; + const text = trimComponentContent(content); + const cliBlock = cli ? `\`\`\`bash\n${cli}\n\`\`\`` : ""; + return [cliBlock, text].filter(Boolean).join("\n\n"); +} + +function formatIconLink(attrs: string, _content: string) { + const title = getAttribute(attrs, "title") ?? "Link"; + const href = getAttribute(attrs, "href"); + const description = getAttribute(attrs, "description"); + const badge = getAttribute(attrs, "badge"); + const label = href ? `[${title}](${href})` : title; + const suffix = [description, badge].filter(Boolean).join(", "); + return `- ${label}${suffix ? `: ${suffix}` : ""}`; +} + function findOpeningTagEnd(value: string, startIndex: number) { let quote: string | undefined; let braceDepth = 0; @@ -456,25 +495,68 @@ function createProtector(input: string, label: string) { restore(value: string, blocks: readonly string[]) { return value.replace(pattern, (match, index: string) => blocks[Number(index)] ?? match); }, + restoreLines(value: string, replace: (index: number, linePrefix: string) => string) { + const linePattern = new RegExp(`^(.*?)${boundary}${label}_(\\d+)${boundary}`, "gm"); + return value.replace(linePattern, (_match, prefix: string, index: string) => + replace(Number(index), prefix), + ); + }, }; } +/** + * Replaces every fenced code block with a single-line placeholder token so the + * component pipeline can never rewrite code samples (e.g. a fenced example that + * mentions `` or ``). The token keeps the fence's leading + * indentation, so line-level transforms — the dedent in `trimComponentContent`, + * the `> ` prefix in `formatCallout` — act on the token line like on any other + * line. `restore` reads what happened to the token line's prefix and applies + * the same shift to every line of the fence, which preserves the dedent and + * blockquote behavior the pipeline previously applied to raw fences. + */ export function protectFencedCodeBlocks(markdown: string) { - const blocks: string[] = []; + const blocks: { text: string; indent: string }[] = []; const protector = createProtector(markdown, "LLM_FENCED_CODE_BLOCK"); const protectedMarkdown = markdown.replace( /^([ \t]*)([`~]{3,})[^\n]*\n[\s\S]*?^\1\2\s*$/gm, - (match) => { + (match, indent: string) => { const token = protector.token(blocks.length); - blocks.push(match); - return token; + blocks.push({ text: match, indent }); + return indent + token; }, ); return { markdown: protectedMarkdown, restore(value: string) { - return protector.restore(value, blocks); + const restored = protector.restoreLines(value, (index, linePrefix) => { + const block = blocks[index]; + if (!block) return linePrefix; + // Only whitespace shifts and blockquote markers are line transforms we + // can mirror; any other prefix (a fence collapsed into prose) is left + // in place with the block substituted verbatim. + if (!/^[>\s]*$/.test(linePrefix)) return linePrefix + block.text.slice(block.indent.length); + const removable = Math.min( + linePrefix.match(/[ \t]*$/)?.[0].length ?? 0, + block.indent.length, + ); + const removed = block.indent.length - removable; + const prefix = linePrefix.slice(0, linePrefix.length - removable); + return block.text + .split("\n") + .map((line) => { + const leading = line.match(/^[ \t]*/)?.[0].length ?? 0; + return prefix + line.slice(Math.min(removed, leading)); + }) + .join("\n"); + }); + // A token that ended up mid-line (its line start consumed by an earlier + // token on the same line) misses the line-anchored pass; substitute it + // verbatim so no placeholder ever leaks into the output. + return protector.restore( + restored, + blocks.map((block) => block.text), + ); }, }; } @@ -507,7 +589,12 @@ export function normalizeProcessedMarkdown( markdown: string, options?: { headingDepths?: ReadonlyMap }, ) { - const componentMarkdown = markdown + // Protect fenced code before any component transform so code samples that + // mention component tags (or MDX comments) are never rewritten as live + // content. The prefix-aware restore keeps the dedent/blockquote behavior for + // fences nested inside
, callouts, tabs, and steps. + const protectedCode = protectFencedCodeBlocks(markdown); + const componentMarkdown = protectedCode.markdown .replace(/\{\/\*[\s\S]*?\*\/\}/g, "") .replace( /]*>([\s\S]*?)<\/CalloutContainer>/g, @@ -539,16 +626,75 @@ export function normalizeProcessedMarkdown( trimComponentContent(content), ) .replace(/]*\/>/g, "") + .replace( + // Attrs matcher tolerates JSX-element props like icon={}, + // whose ">" would end a naive [^>]* match early. + /"'{]|"[^"]*"|'[^']*'|\{[^{}]*\})*)>([\s\S]*?)<\/AgentPrompt>/g, + (_match, attrs: string, content: string) => { + const title = getAttribute(attrs, "title"); + const guideHref = getAttribute(attrs, "guideHref"); + // Untitled prompts sit under an existing "Use with your agent" + // heading in the page, so emit only the content. + if (!title && !guideHref) return trimComponentContent(content); + const base = formatSectionComponent(attrs, content, "Use with your agent"); + if (!guideHref) return base; + const guideTitle = getAttribute(attrs, "guideTitle") ?? "Follow the guide"; + const [heading, ...rest] = base.split("\n\n"); + return [heading, `Follow the guide: [${guideTitle}](${guideHref})`, ...rest].join("\n\n"); + }, + ) + .replace( + /]*)>([\s\S]*?)<\/SectionRow>/g, + (_match, attrs: string, content: string) => { + const title = getAttribute(attrs, "title") ?? "Section"; + const description = getAttribute(attrs, "description"); + const text = trimComponentContent(content); + return ["## " + title, description, text].filter(Boolean).join("\n\n"); + }, + ) + .replace(/<\/?IconGrid[^>]*>/g, "") + .replace(/<\/?StackDiagram[^>]*>/g, "") + .replace( + /]*)>([\s\S]*?)<\/HeroPitch>/g, + (_match, attrs: string, content: string) => formatHeroPitch(attrs, content), + ) + .replace(/<\/?HeroGrid[^>]*>/g, "") + .replace( + // Same brace-tolerant attrs matcher as AgentPrompt: ModalRow takes + // JSX-element props like icon={}. The row's modal content + // collapses to a bold title line plus the body, like
does. + /"'{]|"[^"]*"|'[^']*'|\{[^{}]*\})*)>([\s\S]*?)<\/ModalRow>/g, + (_match, attrs: string, content: string) => { + const title = getAttribute(attrs, "title"); + const body = trimComponentContent(content); + if (!body) return title ? `**${title}**` : ""; + return title ? `**${title}**\n\n${body}` : body; + }, + ) .replace(/]*>([\s\S]*?)<\/details>/g, (_match, content: string) => formatDetails(content), ); - const protectedCode = protectFencedCodeBlocks(componentMarkdown); const withoutJsxComponents = replaceComponentBlocks( - replaceComponentBlocks(protectedCode.markdown, "Card", formatCard) - .replace(/<\/?Cards[^>]*>/g, "") - .replace(//g, (match: string) => formatApiPage(match)) - .replace(//g, (_match, attrs: string) => formatYoutube(attrs)), + replaceComponentBlocks( + replaceComponentBlocks( + replaceComponentBlocks( + // GetStartedTabs goes through the brace-aware parser because its + // `cli` prop is a template literal that can contain ">" (e.g. shell + // redirections), which would end a naive [^>]* attrs match early. + replaceComponentBlocks(componentMarkdown, "GetStartedTabs", formatGetStartedTabs), + "Card", + formatCard, + ) + .replace(/<\/?Cards[^>]*>/g, "") + .replace(//g, (match: string) => formatApiPage(match)) + .replace(//g, (_match, attrs: string) => formatYoutube(attrs)), + "StackLayer", + formatStackLayer, + ), + "IconLink", + formatIconLink, + ), "Button", formatButton, ); @@ -562,14 +708,14 @@ export function normalizeProcessedMarkdown( // placeholders at this point. const withHeadings = restoreHeadingMarkers(withoutJsxComponents, options?.headingDepths); const protectedInline = protectInlineCode(withHeadings); - const unescaped = protectedInline.restore( - protectedInline.markdown.replace(/\\([_{}])/g, "$1"), - ); + const unescaped = protectedInline.restore(protectedInline.markdown.replace(/\\([_{}])/g, "$1")); return protectedCode .restore(unescaped) .replace(/^[ \t]+(#{3,4} )/gm, "$1") .replace(/^[ \t]+(- \[)/gm, "$1") + .replace(/^[ \t]+(- \*\*\[)/gm, "$1") + .replace(/^[ \t]+(\d+\. \*\*\[)/gm, "$1") .replace(/\n{3,}/g, "\n\n") .trim(); } diff --git a/apps/docs/src/mdx-components.tsx b/apps/docs/src/mdx-components.tsx index aa45be6dd3..5bc64070fd 100644 --- a/apps/docs/src/mdx-components.tsx +++ b/apps/docs/src/mdx-components.tsx @@ -2,7 +2,20 @@ import defaultMdxComponents from "fumadocs-ui/mdx"; import { Youtube } from "@prisma-docs/ui/components/youtube"; import { APIPage } from "@/components/api-page"; import { ConceptAnimation } from "@/components/concept-animation"; +import { + AgentPrompt, + GetStartedTabs, + HeroGrid, + HeroPitch, + IconGrid, + IconLink, + ModalRow, + SectionRow, + StackDiagram, + StackLayer, +} from "@/components/getting-started"; import { withDocsBasePath } from "@/lib/urls"; +import { cn } from "@prisma-docs/ui/lib/cn"; import type { MDXComponents } from "mdx/types"; import { ImageZoom } from "fumadocs-ui/components/image-zoom"; @@ -41,6 +54,49 @@ function withDocsBasePathForImageSrc(src: unknown): unknown { return withDocsBasePath(src); } +/** + * Small technology logo for use inside Card icons and link grids. + * Renders a plain img (no zoom) at a consistent size. Pass `darkSrc` for a + * dedicated dark-mode asset, or `invertDark` for monochrome logos that only + * need inverting. + */ +function TechIcon({ + src, + alt, + darkSrc, + invertDark, +}: { + src: string; + alt: string; + darkSrc?: string; + invertDark?: boolean; +}) { + const base = "size-6 max-w-6 object-contain"; + if (darkSrc) { + return ( + <> + {/* eslint-disable-next-line @next/next/no-img-element */} + {alt} + {/* eslint-disable-next-line @next/next/no-img-element */} + + + ); + } + return ( + // eslint-disable-next-line @next/next/no-img-element + {alt} + ); +} + export function getMDXComponents(components?: MDXComponents): MDXComponents { const pageContext = (components as any)?._pageContext; @@ -63,7 +119,18 @@ export function getMDXComponents(components?: MDXComponents): MDXComponents { Accordion, Accordions, APIPage, + AgentPrompt, ConceptAnimation, + GetStartedTabs, + HeroGrid, + HeroPitch, + IconGrid, + IconLink, + ModalRow, + SectionRow, + StackDiagram, + StackLayer, + TechIcon, Youtube, img: (props: any) => ( @@ -83,9 +150,9 @@ export function getMDXComponents(components?: MDXComponents): MDXComponents { td: ({ ref: _ref, ...props }) => , caption: ({ ref: _ref, ...props }) => , // Override Fumadocs Callout components with Eclipse Alert for alerts (:::ppg, :::error, :::success, :::warning) - CalloutTitle: ({ children }: any) =>
{children}
, + CalloutTitle: ({ children }: any) =>
{children}
, CalloutDescription: ({ children }: any) => <>{children}, - CalloutContainer: ({ type, children, icon, ...props }: any) => { + CalloutContainer: ({ type, children, icon, className, ...props }: any) => { const variantMap: Record = { ppg: "ppg", error: "error", @@ -98,7 +165,17 @@ export function getMDXComponents(components?: MDXComponents): MDXComponents { }; return ( - + {children} );