Skip to main content
Prisma Documentation Docs

Search documentation

Type to search this documentation.

On this pageOverview

TanStack Start

TanStack Start runs server functions alongside your React routes, which is where you call Prisma ORM to read from a Prisma Postgres database.

This guide shows you how to integrate Prisma ORM with a Prisma Postgres database in a TanStack Start project from scratch.

Run one command to scaffold a TanStack Start project with Prisma ORM and Prisma Postgres ready to go:

title="bun"
bunx create-prisma@stable --template tanstack-start
pnpm
pnpm create prisma@stable --template tanstack-start
yarn
yarn create prisma@stable --template tanstack-start
npm
npm create prisma@stable -- --template tanstack-start

Or follow the steps below to set it up manually.

To begin, create a new TanStack Start project.

bun create @tanstack/start@latest
Bash
pnpm create @tanstack/start@latest
Bash
yarn create @tanstack/start@latest
Bash
npm create @tanstack/start@latest

[!NOTE]

  • What would you like to name your project? tanstack-start-prisma
  • Would you like to use Tailwind CSS? No
  • Select Toolchain None
  • Select deployment adapter Nitro
  • What add-ons would you like for your project? Prisma
  • Would you like any examples? No
  • Prisma: Database Provider Prisma PostgresSQL

This will create a new folder called tanstack-start-prisma and provision a new Prisma Postgres database. At the end of the setup, the CLI will display the database connection string:

●  Database Connection
│
│    Connection String:
│
│    postgresql://username:password@db.prisma.io:5432/postgres
●

[!WARNING] The database is temporary and will be deleted after 24 hours. To keep it permanently, follow the claim link shown in the CLI output.

Navigate to your project directory:

Bash
cd tanstack-start-prisma

Then, add the connection string you copied to your .env file:

.env
DATABASE_URL="postgresql://username:password@db.prisma.io:5432/postgres"

This will create a new folder called tanstack-start-prisma and provision a new Prisma Postgres database. At the end of the setup, the CLI will display the database connection string:

●  Database Connection

│

│    Connection String:

│

│    postgresql://username:password@db.prisma.io:5432/postgres

●

Navigate to your project directory:

cd tanstack-start-prisma

Then, add the connection string you copied to your .env file:

title=".env"
DATABASE_URL="postgresql://username:password@db.prisma.io:5432/postgres"

In schema.prisma, the model for our todos is defined below the generator and datasource blocks:

title="prisma/schema.prisma"
generator client {

  provider = "prisma-client"

  output   = "../app/generated/prisma"

}

datasource db {

  provider = "postgresql"

}

model Todo {

  id        Int      @id @default(autoincrement())

  title     String

  createdAt DateTime @default(now())

}

This creates a Todo model that will be pushed to the database

Now, run the following command to create the database tables:

title="bun"
bun run db:migrate --name init
pnpm
pnpm run db:migrate --name init
yarn
yarn db:migrate --name init
npm
npm run db:migrate -- --name init

Generate the Prisma Client needed for the project:

title="bun"
bun run db:generate
pnpm
pnpm run db:generate
yarn
yarn db:generate
npm
npm run db:generate

Then seed the project with the seed.ts file in the prisma/ directory:

title="bun"
bun run db:seed
pnpm
pnpm run db:seed
yarn
yarn db:seed
npm
npm run db:seed

And open Prisma Studio to inspect your data:

title="bun"
bun run db:studio
pnpm
pnpm run db:studio
yarn
yarn db:studio
npm
npm run db:studio

Instead of creating a new Prisma Client instance in each file, TanStack Start has a db.ts that creates a single instance that can be shared globally

title="src/db.ts"
import { PrismaClient } from "./generated/prisma/client.js";

import { PrismaPg } from "@prisma/adapter-pg";

const adapter = new PrismaPg({

  connectionString: process.env.DATABASE_URL!,

});

declare global {

  var __prisma: PrismaClient | undefined;

}

export const prisma = globalThis.__prisma || new PrismaClient({ adapter });

if (process.env.NODE_ENV !== "production") {

  globalThis.__prisma = prisma;

}

First, import the necessary modules. Then, create a server function using the createServerFn function. This function will fetch the data from the database using the .findMany() method

title="src/routes/index.tsx"
import { createFileRoute } from "@tanstack/react-router";

import { createServerFn } from "@tanstack/react-start"; 

import { prisma } from '../db'; 

export const Route = createFileRoute("/")({

  component: Home,

});

const getTodos = createServerFn({ method: "GET" }).handler(async () => { 

  return prisma.todo.findMany(); 

}); 

function Home() {

  return (

    <div>

    </div>

  );

}

TanStack Start allows functions to run on load with loader functions in the createFileRoute function. Fetch the users and their posts on load with this code:

title="app/routes/index.tsx"
import { createFileRoute } from '@tanstack/react-router';

import { createServerFn } from '@tanstack/react-start';

import { prisma } from '../db';

export const Route = createFileRoute("/")({

  component: Home,

  loader: () => { 

    return getTodos(); 

  }, 

});

const getTodos = createServerFn({ method: "GET" }).handler(async () => {

  return prisma.todo.findMany();

});

function Home() {

  return (

    <div>

      <h1>Todos</h1>

    </div>

  );

}

Store the response from the loader in the main component using Route.useLoaderData():

title="app/routes/index.tsx"
import { createServerFn } from "@tanstack/react-start";

import { createFileRoute } from "@tanstack/react-router";

import { prisma } from '../db';

export const Route = createFileRoute("/")({

  component: Home,

  loader: () => {

    return getTodos();

  },

});

const getTodos = createServerFn({ method: "GET" }).handler(async () => {

  return prisma.todo.findMany();

});

function Home() {

  const todos = Route.useLoaderData(); 

  return (

    <div>

      <h1>Todos</h1>

    </div>

  );

}

Next, you'll update the home page to display the data retrieved from your database.

Map over the todos and display them in a list:

title="app/routes/index.tsx"
import { createFileRoute } from '@tanstack/react-router';

import { createServerFn } from '@tanstack/react-start';

import { prisma } from '../db';

export const Route = createFileRoute('/')({

  component: App,

  loader: () => getTodos(),

});

const getTodos = createServerFn({ method: 'GET' }).handler(async () => {

  return prisma.todo.findMany();

});

function App() {

  const todos = Route.useLoaderData();

  return (

    <div>

      <ul>

        {todos.map(todo => (

          <li key={todo.id}>{todo.title}</li>

        ))}

      </ul>

    </div>

  );

}

This setup will display the todos on your page, fetched directly from your database.

Your TanStack Start app now loads todos from a Prisma Postgres database through a server function. A few suggestions for what to do next:

  • Expand your Prisma models to handle more complex data relationships.
  • Implement additional CRUD operations.
  • Check out Prisma Postgres to see how you can scale your application.
Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu