# Remix 3 (/docs/guides/frameworks/remix) > For the complete Prisma documentation index, see [llms.txt](https://www.prisma.io/docs/llms.txt). A markdown version of any docs page is available by appending `.md` to its URL. Add Prisma ORM to a Remix 3 app, seed a PostgreSQL database, render users from a controller, and deploy to Prisma Compute. Location: Guides > Frameworks > Remix 3 ## Introduction [#introduction] This guide shows you how to use Prisma ORM in a [Remix 3](https://remix.run/) app. You create a project, seed a PostgreSQL database, render users on the home page, and deploy the app to [Prisma Compute](https://www.prisma.io/docs/compute), Prisma's app hosting service. In Remix 3, a controller handles requests and passes database results to a component that renders the page. See the [Remix 3 release candidate announcement](https://remix.run/blog/remix-3-release-candidate) for an overview of the new framework. For apps built with Remix 2, see the [React Router guide](https://www.prisma.io/docs/guides/frameworks/react-router-7). ## Prerequisites [#prerequisites] * [Node.js](https://nodejs.org) 24.11 or newer * A PostgreSQL connection string. Use your own database, or run `npx create-db@latest` to create a [Prisma Postgres](https://www.prisma.io/docs/postgres) database. * A [Prisma account](https://console.prisma.io/?utm_source=docs\&utm_medium=content\&utm_content=guides) to deploy to Compute. ## 1. Create a Remix app [#1-create-a-remix-app] Create a project with the [Remix CLI](https://guides.remix.run/start-here/) and install its dependencies: #### bun ```bash bunx remix@latest new my-app cd my-app bun install ``` #### pnpm ```bash pnpm dlx remix@latest new my-app cd my-app pnpm install ``` #### yarn ```bash yarn dlx remix@latest new my-app cd my-app yarn install ``` #### npm ```bash npx remix@latest new my-app cd my-app npm install ``` The starter defines routes in `app/routes.ts` and handles the home page in `app/actions/controller.tsx`. Its `app/router.ts` exports the router used by the server. ## 2. Add Prisma ORM [#2-add-prisma-orm] Add Prisma ORM to the existing project with [`orm init`](https://www.prisma.io/docs/cli/orm-init), using `--yes` to accept the default prompts: #### bun ```bash bunx prisma@latest orm init --yes --target postgres --authoring psl ``` #### pnpm ```bash pnpm dlx prisma@latest orm init --yes --target postgres --authoring psl ``` #### yarn ```bash yarn dlx prisma@latest orm init --yes --target postgres --authoring psl ``` #### npm ```bash npx prisma@latest orm init --yes --target postgres --authoring psl ``` The command selects PostgreSQL and writes your schema in Prisma Schema Language (`psl`). It installs Prisma ORM and creates `src/prisma/contract.prisma` for your schema, `src/prisma/db.ts` for the database client, and `prisma.config.ts` for the CLI. Create a `.env` file at the project root with your PostgreSQL connection string. If you used `create-db`, copy the connection string it prints, and open its separate claim URL in your browser to save the database in your Prisma account before it expires after 24 hours: ```bash title=".env" DATABASE_URL="postgres://user:password@localhost:5432/mydb" ``` Both the CLI and the database client load this file automatically. ## 3. Define and initialize the database [#3-define-and-initialize-the-database] Prisma ORM calls your schema a contract. Replace the starter schema with a user model, keeping `// use prisma-8` so the CLI uses the schema format for Prisma ORM 8: ```prisma title="src/prisma/contract.prisma" // use prisma-8 model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` Generate the TypeScript definitions for checking your queries and a JSON file containing your Prisma model. Then create the database table: #### bun ```bash bunx prisma contract emit bunx prisma db init ``` #### pnpm ```bash pnpm prisma contract emit pnpm prisma db init ``` #### yarn ```bash yarn prisma contract emit yarn prisma db init ``` #### npm ```bash npx prisma contract emit npx prisma db init ``` `prisma contract emit` generates these files for your queries and deployment: * `src/prisma/contract.d.ts` exports `Contract`, a TypeScript type describing your tables and columns for checking queries. * `src/prisma/contract.json` stores the same model in Prisma's JSON format for the client and deployment tools to read. Include both files when you commit your project to Git; the starter's `.gitignore` excludes neither file. Leave `src/prisma/db.ts` as generated: it uses `Contract` to check your queries and reads `contract.json` at runtime. `prisma db init` creates the `User` table with unique emails and saves a description of that schema in your project's `migrations` directory. ## 4. Seed users [#4-seed-users] Create a script that adds sample users and skips existing emails when you run it again. `db.orm` is the client's query API, and `db.orm.public.User` queries the `User` table. PostgreSQL groups tables into schemas; this guide uses its default schema, `public`: ```ts title="src/prisma/seed.ts" import { db } from "./db.ts"; try { for (const user of [ { email: "alice@prisma.io", name: "Alice" }, { email: "bob@prisma.io", name: "Bob" }, ]) { const existing = await db.orm.public.User.where({ email: user.email }).first(); if (!existing) await db.orm.public.User.create(user); } console.log("Seeded Alice and Bob"); } finally { await db.close(); } ``` Run it from the project root: ```bash node src/prisma/seed.ts ``` ```text no-copy Seeded Alice and Bob ``` ## 5. Render users on the home page [#5-render-users-on-the-home-page] Replace `app/actions/home-page.tsx` with a [Remix component](https://guides.remix.run/rendering-ui/) that displays the queried users. Remix passes each component a `Handle`, an object containing its props. Read the users passed by the controller from `handle.props.users`, and return a function containing the JSX as shown below. The starter's `Document` component supplies the page's HTML document: ```tsx title="app/actions/home-page.tsx" import type { Handle } from "remix/component"; import { Document } from "./document.tsx"; type User = { email: string; name: string | null }; export function HomePage(handle: Handle<{ users: User[] }>) { return () => (

Users

); } ``` Replace the home page controller so it reads users with Prisma ORM and passes them to the component. Keep the `assets` import from `../assets.ts` and the `async assets(context)` handler shown below; they serve the JavaScript files the browser needs. Use `context.render(...)` in the controller's request handler to return the component as an HTML response: ```tsx title="app/actions/controller.tsx" import { createController } from "remix/router"; import { db } from "../../src/prisma/db.ts"; import { assets } from "../assets.ts"; import { routes } from "../routes.ts"; import { HomePage } from "./home-page.tsx"; export default createController(routes, { actions: { async assets(context) { return (await assets.fetch(context.request)) ?? new Response("Not Found", { status: 404 }); }, async home(context) { const users = await db.orm.public.User.orderBy((user) => user.id.asc()).all(); return context.render(); }, }, }); ``` Import `db` in `controller.tsx`; don't import it in `home-page.tsx` or files served to the browser. Don't call `db.close()` in a controller; the connection pool is shared across requests. ## 6. Run and verify [#6-run-and-verify] Check the types, then start the development server: #### bun ```bash bun run typecheck bun run dev ``` #### pnpm ```bash pnpm run typecheck pnpm run dev ``` #### yarn ```bash yarn typecheck yarn dev ``` #### npm ```bash npm run typecheck npm run dev ``` Open [http://localhost:44100](http://localhost:44100) to see the seeded users: ```text no-copy Users Alice (alice@prisma.io) Bob (bob@prisma.io) ``` You can also check the rendered HTML with `curl http://localhost:44100`. If the port is already in use, run `PORT=44101 npm run dev` and open [http://localhost:44101](http://localhost:44101). Press **Ctrl+C** to stop the development server before continuing. ## 7. Deploy to Prisma Compute [#7-deploy-to-prisma-compute] Your first deployment creates a Prisma project containing this app's server and a new Prisma Postgres database, separate from your local database. [Prisma Composer](https://www.prisma.io/docs/composer) is the TypeScript configuration library you use to describe this deployment. ### 7.1. Declare the app [#71-declare-the-app] Run the following commands and create all deployment files in the project root. Install the deployment packages and build tool: #### bun ```bash bun add @prisma/composer @prisma/composer-prisma-cloud bun add --dev esbuild ``` #### pnpm ```bash pnpm add @prisma/composer @prisma/composer-prisma-cloud pnpm add -D esbuild ``` #### yarn ```bash yarn add @prisma/composer @prisma/composer-prisma-cloud yarn add --dev esbuild ``` #### npm ```bash npm install @prisma/composer @prisma/composer-prisma-cloud npm install -D esbuild ``` Create `data-contract.ts` so your deployment configuration can use the schema you generated. `dataContract()` returns an object describing your PostgreSQL schema for Composer; export it as `userData` so the server and database configuration use the same schema: ```ts title="data-contract.ts" import { dataContract } from "@prisma/composer-prisma-cloud/orm"; import type { Contract } from "./src/prisma/contract.d.ts"; import contractJson from "./src/prisma/contract.json" with { type: "json" }; export const userData = dataContract(contractJson); ``` Create `service.ts` to describe the server's startup file, `dist/server.mjs`. Add `database: postgres(userData)` to `deps` so deployment knows which database schema the server needs. These files describe deployment work; `prisma deploy` creates the hosted database and server, then supplies the database connection: ```ts title="service.ts" import node from "@prisma/composer/node"; import { compute } from "@prisma/composer-prisma-cloud"; import { postgres } from "@prisma/composer-prisma-cloud/orm"; import { userData } from "./data-contract.ts"; export default compute({ name: "web", deps: { database: postgres(userData) }, // Package an existing build; run npm run build before deploying. build: node({ module: import.meta.url, // The source file's URL makes dir relative to service.ts. dir: "./dist", entry: "server.mjs", }), }); ``` A Composer module groups the server and database into one app. Create `module.ts` to define the app named `my-remix-app`. Use `provision()` to declare the resources the CLI creates or updates when you run `prisma deploy`, and pass the created database to the server through `deps`: ```ts title="module.ts" import { module } from "@prisma/composer"; import { postgres } from "@prisma/composer-prisma-cloud/orm"; import { userData } from "./data-contract.ts"; import web from "./service.ts"; export default module("my-remix-app", ({ provision }) => { const database = provision(postgres({ name: "database", contract: userData, config: "./prisma.config.ts" })); provision(web, { deps: { database } }); }); ``` Replace `prisma.config.ts` with the configuration below to deploy to Compute in `us-east-1`. The `extensions` array lists the deployment tools: `prismaCloud()` creates the hosted resources, and `nodeBuild()` packages your existing `dist` directory. The `config: "./prisma.config.ts"` setting in `module.ts` tells Composer to read this file for the hosted database's migrations. Set `orm.migrations.dir` to the project-root `migrations` directory; step 7.3 generates the files there. Deployment applies them to the new hosted database, while local commands use the connection from your `.env`. Keep `state: prismaState()` so Composer saves the server and database IDs in the hosted project and updates those resources on future deploys: ```ts title="prisma.config.ts" import 'dotenv/config'; import { defineConfig as composer } from '@prisma/composer/config'; import { nodeBuild } from '@prisma/composer/node/control'; import { prismaCloud, prismaState } from '@prisma/composer-prisma-cloud/control'; import { definePrismaConfig } from '@prisma/cli-engine'; import { defineConfig as ormConfig } from '@prisma/orm-postgres/config'; export default definePrismaConfig({ composer: composer({ extensions: [prismaCloud({ region: 'us-east-1' }), nodeBuild()], state: prismaState(), }), orm: ormConfig({ contract: "./src/prisma/contract.prisma", migrations: { dir: "./migrations" }, db: { connection: process.env['DATABASE_URL']!, }, }), }); ``` ### 7.2. Package the server and assets [#72-package-the-server-and-assets] Create a separate server startup file for Compute. `service.load()` reads the values supplied by deployment when the server starts, including the database connection string. `service.port()` provides the port assigned by Compute. Set the database URL before loading Prisma, and seed users before accepting requests: ```ts title="compute-server.ts" import * as http from "node:http"; import { dirname } from "node:path"; import { fileURLToPath } from "node:url"; import { createRequestListener } from "remix/node-fetch-server"; import service from "./service.ts"; process.chdir(dirname(fileURLToPath(import.meta.url))); process.env.NODE_ENV = "production"; process.env.DATABASE_URL = service.load().database.url; const { db } = await import("./src/prisma/db.ts"); for (const user of [ { email: "alice@prisma.io", name: "Alice" }, { email: "bob@prisma.io", name: "Bob" }, ]) { if (!(await db.orm.public.User.where({ email: user.email }).first())) { await db.orm.public.User.create(user); } } const { router } = await import("./app/router.ts"); http.createServer(createRequestListener(router.fetch)).listen(service.port(), "0.0.0.0"); ``` The deployed Remix server needs the app's source files to generate browser JavaScript and CSS. Create `build.mjs` to copy `app`, `public`, and `tsconfig.json` into `dist`, bundle the server startup file, and write the package list for the deployed server: ```js title="build.mjs" import { cp, mkdir, rm, readFile, writeFile } from "node:fs/promises"; import { build } from "esbuild"; await rm("dist", { recursive: true, force: true }); await mkdir("dist", { recursive: true }); await build({ entryPoints: ["compute-server.ts"], outfile: "dist/server.mjs", bundle: true, // Leave these out of the bundle; package.json's build command installs them in dist/node_modules. external: ["remix/*", "@prisma/orm-postgres/*", "dotenv/config"], platform: "node", format: "esm", }); for (const path of ["app", "public", "tsconfig.json"]) { await cp(path, `dist/${path}`, { recursive: true }); } const { dependencies: installed } = JSON.parse(await readFile("package.json", "utf8")); const dependencies = Object.fromEntries(["remix", "@prisma/orm-postgres", "dotenv"].map((name) => [name, installed[name]])); await writeFile("dist/package.json", JSON.stringify({ type: "module", dependencies })); ``` Add a `build` script to the existing scripts in `package.json`. Compute runs on Linux x64, so use the flags below to install Linux binaries for Remix's JavaScript and CSS compilers. `--libc=glibc` selects binaries for glibc (the GNU C Library), which Compute uses: ```json title="package.json" { "scripts": { "build": "node build.mjs && npm install --prefix dist --omit=dev --ignore-scripts --os=linux --cpu=x64 --libc=glibc" } } ``` The starter's `.gitignore` excludes `.env`, and the build script does not copy it into `dist`. ### 7.3. Build and deploy [#73-build-and-deploy] The earlier `db init` also saved a description of the schema it created locally in your project's `migrations` directory. `migration plan` uses that description to write a migration that creates the same `User` table in a fresh hosted database. Generate the migration files, then sign in through the browser. Check which workspace will contain your app; a workspace groups Prisma projects under your account: #### bun ```bash bunx prisma migration plan --name init bunx prisma auth login bunx prisma auth whoami ``` #### pnpm ```bash pnpm prisma migration plan --name init pnpm prisma auth login pnpm prisma auth whoami ``` #### yarn ```bash yarn prisma migration plan --name init yarn prisma auth login yarn prisma auth whoami ``` #### npm ```bash npx prisma migration plan --name init npx prisma auth login npx prisma auth whoami ``` To switch between workspaces you've signed into on this computer, run `npx prisma auth workspace list`, then `npx prisma auth workspace use "Your workspace name"` with the name shown in the list. If your workspace is absent, run `npx prisma auth login` again and choose it during browser sign-in. Check existing project names before deploying: #### bun ```bash bunx prisma project list ``` #### pnpm ```bash pnpm prisma project list ``` #### yarn ```bash yarn prisma project list ``` #### npm ```bash npx prisma project list ``` For your first deployment, choose an unused project name. If `my-remix-app` is listed, replace `"my-remix-app"` in `module.ts` with an unused name such as `"my-remix-app-2"`. Keep that name for later deploys. Build and deploy: #### bun ```bash bun run build bunx prisma deploy module.ts ``` #### pnpm ```bash pnpm run build pnpm prisma deploy module.ts ``` #### yarn ```bash yarn build yarn prisma deploy module.ts ``` #### npm ```bash npm run build npx prisma deploy module.ts ``` Keep the generated `migrations` directory with your project. Deployment applies these migrations before starting the server. ```text no-copy my-remix-app ├─ database postgres-database db_abc123 └─ web compute-service cps_abc123 https://xyz.ewr.prisma.build ``` The app name in `module.ts` selects the project in your current workspace. The first deploy creates that project; later deploys update its server and database using the IDs saved by `prismaState()`. Open the printed URL: the page shows Alice and Bob from the deployed database. In your browser's developer tools, open **Network** and reload the page; requests under `/assets/` should return `200`. For automatic deployments and previews per Git branch, see [Deploy on push](https://www.prisma.io/docs/compute/deploy-on-push). ## Use with your agent [#use-with-your-agent] ```text Create a Remix 3 app with Prisma ORM, render database users, and deploy to Prisma Compute, following https://www.prisma.io/docs/guides/frameworks/remix.md. 1. Run `npx remix@latest new my-app`, enter the project, and run `npm install`. Add Prisma ORM with `npx prisma@latest orm init --yes --target postgres --authoring psl`. 2. Use the PostgreSQL connection string I provide, or create a Prisma Postgres database with `npx create-db@latest` and show me its claim URL to open in a browser before the database expires after 24 hours. Set DATABASE_URL in .env to the separate PostgreSQL connection string it prints. 3. Define the User model and run `npx prisma contract emit`, `npx prisma db init`, and the seed script from the guide. 4. Update the home page component and controller from the guide. Run `npm run typecheck`, start `npm run dev`, and verify http://localhost:44100 renders Alice and Bob. Stop the server after verification. 5. Follow the deployment section to add the Composer configuration, Compute server startup file, and build script. Plan the initial migration with `npx prisma migration plan --name init`, then run `npm run typecheck`. Check `npx prisma auth whoami`; if I am not signed in, ask me to run `npx prisma auth login`. Run `npm run build` and `npx prisma deploy module.ts`, then verify the live page and that its /assets/ requests return 200. In the deployed server, set DATABASE_URL to the connection supplied by service.load().database.url. Keep the local connection string for local commands. ``` ## Next steps [#next-steps] * [Query your data](https://www.prisma.io/docs/orm/fundamentals/reading-data): filtering, sorting, and pagination. * [Update your schema](https://www.prisma.io/docs/guides/database/schema-changes) as your app grows. * [Remix routing and controllers](https://guides.remix.run/routing-and-controllers/) for more pages and actions. ## Related pages - [`Astro`](https://www.prisma.io/docs/guides/frameworks/astro): Set up Prisma ORM in an Astro app with create-prisma, from scaffold to rendered data, and deploy it to Prisma Compute. - [`Elysia`](https://www.prisma.io/docs/guides/frameworks/elysia): Build an Elysia API on Prisma ORM with the elysia template and deploy it to Prisma Compute. - [`Hono`](https://www.prisma.io/docs/guides/frameworks/hono): Build a Hono API on Prisma ORM with the hono template, add your own routes, and deploy it to Prisma Compute. - [`NestJS`](https://www.prisma.io/docs/guides/frameworks/nestjs): Set up Prisma ORM in a NestJS app with create-prisma, from scaffold to seeded API to a live deploy on Prisma Compute. - [`Next.js`](https://www.prisma.io/docs/guides/frameworks/nextjs): Set up Prisma ORM in a Next.js app with create-prisma, from scaffold to rendered data, and deploy it to Prisma Compute.