Skip to main content
Every app gets an isolated database managed through Prisma. The framework wraps the Prisma client with RLS context so that all queries are automatically scoped to the authenticated user’s permissions.

Defining models

The task tracker needs a Task model. Define it in prisma/schema.prisma:
model Task {
  id        String   @id @default(cuid())
  title     String
  status    String   @default("active")
  priority  Int      @default(3)
  userId    String
  user      User     @relation(fields: [userId], references: [id])
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@index([userId])
  @@index([status])
}
After modifying the schema, apply changes and generate types:
pnpm install --silent && pnpm run db:push && pnpm run db:generate
Type information flows automatically from the Prisma schema through tRPC to the frontend — no manual type definitions needed.

Database access

All database access in procedure handlers goes through ctx.db:
getMyTasks: scopedProcedure([])
  .meta({ description: "Get current user's tasks" })
  .query(async ({ ctx }) => {
    return ctx.db.task.findMany({
      where: { userId: ctx.userId },
      orderBy: { createdAt: 'desc' },
    });
  }),
ctx.db is a Prisma client with the authenticated user’s RLS context (user ID, role, scopes, org IDs) injected automatically.

Built-in tables

The scaffolded app includes tables provided by the framework, including common ones like User — so you don’t need to define them yourself. You can add relations to built-in tables from your own models, as the Task model does above with User. For the full list of built-in tables, multi-database support, indexing, transactions, and identity patterns, see the Database reference.