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:
bunx create-prisma@stable --template tanstack-startpnpm create prisma@stable --template tanstack-startyarn create prisma@stable --template tanstack-startnpm create prisma@stable -- --template tanstack-startOr follow the steps below to set it up manually.
To begin, create a new TanStack Start project.
bun create @tanstack/start@latestpnpm create @tanstack/start@latestyarn create @tanstack/start@latestnpm 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:
cd tanstack-start-prismaThen, add the connection string you copied to your .env file:
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-prismaThen, add the connection string you copied to your .env file:
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:
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
2.2. Run migrations and generate Prisma Client
Section titled “2.2. Run migrations and generate Prisma Client”Now, run the following command to create the database tables:
bun run db:migrate --name initpnpm run db:migrate --name inityarn db:migrate --name initnpm run db:migrate -- --name initGenerate the Prisma Client needed for the project:
bun run db:generatepnpm run db:generateyarn db:generatenpm run db:generateThen seed the project with the seed.ts file in the prisma/ directory:
bun run db:seedpnpm run db:seedyarn db:seednpm run db:seedAnd open Prisma Studio to inspect your data:
bun run db:studiopnpm run db:studioyarn db:studionpm run db:studioInstead 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
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
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:
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():
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:
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.