CodingNic

Build the Data Layer

Model Books and Reading Data

Build the Data Layer 18 min read

Model Books and Reading Data

Model Books and Reading Data

A Readly user needs a private collection of books and a persistent reading position for each book.

Task

Add Book and ReadingProgress to the Prisma schema.

Use this model shape:

text
model Book {
  id          String   @id @default(cuid())
  userId      String
  title       String
  author      String?
  description String?
  coverUrl    String?
  fileKey     String
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  user            User             @relation(fields: [userId], references: [id], onDelete: Cascade)
  readingProgress ReadingProgress?
  bookmarks      Bookmark[]
  highlights     Highlight[]
  notes          Note[]

  @@index([userId])
  @@index([userId, createdAt])
}

model ReadingProgress {
  id         String   @id @default(cuid())
  userId     String
  bookId     String   @unique
  cfi        String?
  percentage Float    @default(0)
  completed  Boolean  @default(false)
  updatedAt  DateTime @updatedAt

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  book Book @relation(fields: [bookId], references: [id], onDelete: Cascade)

  @@index([userId])
}

Make sure User also exposes the progress relation:

text
readingProgress ReadingProgress[]

Ownership Matters

userId is intentionally present on both Book and ReadingProgress. Later API handlers can verify that a resource belongs to the signed-in user before reading or changing it.

bookId is unique on ReadingProgress because each user should have one progress record for a book. The application will still verify user ownership when accessing the record.

Test

Run:

bash
npx prisma format
npx prisma validate

Checkpoint

The schema now represents a user’s private books and persistent reading state.