We'll use Prisma, a type-safe ORM, to turn our schema into typed code. The Prisma schema is a single readable file that maps to database tables.
1generator client {
2 provider = "prisma-client-js"
3}
4
5datasource db {
6 provider = "postgresql"
7 url = env("DATABASE_URL")
8}
9
10model User {
11 id String @id @default(uuid())
12 email String @unique
13 name String
14 tasks Task[]
15 createdAt DateTime @default(now())
16}
17
18model Task {
19 id String @id @default(uuid())
20 title String
21 description String?
22 status TaskStatus @default(TODO)
23 dueDate DateTime?
24 owner User @relation(fields: [ownerId], references: [id])
25 ownerId String
26 tags Tag[]
27 createdAt DateTime @default(now())
28 updatedAt DateTime @updatedAt
29}
30
31model Tag {
32 id String @id @default(uuid())
33 name String @unique
34 tasks Task[]
35}
36
37enum TaskStatus {
38 TODO
39 IN_PROGRESS
40 DONE
41}? marks a field optional (nullable) — description String?.@id is the primary key; @default(uuid()) auto-generates it.@unique enforces no duplicates.@updatedAt auto-stamps the row on every write.Task[] on User and User on Task together model the one-to-many relation.Tag[] on both sides models many-to-many; Prisma manages the join table for you.1npx prisma migrate dev --name init
2npx prisma generatemigrate dev creates the SQL migration and applies it. generate produces a fully typed client. From here, prisma.task.create(...) is autocompleted and type-checked — the foundation for every CRUD operation in the rest of the course.