TanStack Start
Learn how to use Prisma ORM in a TanStack Start app
Introduction
Prisma ORM simplifies database interactions, and TanStack Start offers a robust framework for building modern React applications. Together with Prisma Postgres, they provide a seamless full-stack development experience with type-safe queries and efficient data management.
This guide will walk you through integrating Prisma ORM with a Prisma Postgres database in a TanStack Start project from scratch.
Prerequisites
1. Set up your project
To begin, create a new TanStack Start project.
npm create @tanstack/start@latest- 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 create a new Prisma Postgres
Database for you. The final database connection string will be printed out.
● Database Connection
│
│ Connection String:
│
│ postgresql://b4889.....
│Copy this connection string and set the DATABASE_URL variable in .env.local:
# Database URL for PostgreSQL
DATABASE_URL="postgresql://b4889....."2. Configure Prisma
2.1. Define your Prisma Schema
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. Configure the Prisma Client generator
Now, run the following command to create the database tables:
npm run db:seed -- --name init2.3. Seed the database
Generate the Prisma Client needed for the project;
npm run db:generateThen seed the project with the seed.ts file in the prisma/ directory:
npm run db:seedAnd open Prisma Studio to inspect your data:
npm run db:studio3. Integrate Prisma into TanStack Start
3.1 The Prisma Client
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
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;
}3.2 Fetch data on load
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>
);
}3.3 Display the todos
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.
Next steps
You've successfully integrated Prisma ORM with TanStack Start, creating a seamless full-stack application. Here are a few suggestions for what you can do next:
- Expand your Prisma models to handle more complex data relationships.
- Implement additional CRUD operations to enhance your application's functionality.
- Explore more features of Prisma and TanStack Start to deepen your understanding.
- Check out Prisma Postgres to see how you can scale your application.