CodingNic

Build the Data Layer

Model Annotations and Preferences

Build the Data Layer 20 min read

Model Annotations and Preferences

Model Annotations and Preferences

Finish the data model for the features that make Readly a personal reading space.

Task

Add bookmarks, highlights, notes, and reader preferences.

Use these models:

text
model Bookmark {
  id        String   @id @default(cuid())
  userId    String
  bookId    String
  cfi       String
  label     String?
  createdAt DateTime @default(now())

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

  @@index([userId, bookId])
}

model Highlight {
  id        String   @id @default(cuid())
  userId    String
  bookId    String
  cfi       String
  text      String
  color     String   @default("yellow")
  favorite  Boolean  @default(false)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

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

  @@index([userId, bookId])
}

model Note {
  id          String   @id @default(cuid())
  userId      String
  bookId      String
  highlightId String?
  content     String
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

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

  @@index([userId, bookId])
  @@index([highlightId])
}

model ReaderPreference {
  id           String   @id @default(cuid())
  userId       String   @unique
  theme        String   @default("paper")
  fontFamily   String   @default("serif")
  fontSize     Int      @default(105)
  lineHeight   Float    @default(1.7)
  contentWidth String   @default("comfortable")
  updatedAt    DateTime @updatedAt

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

Update the User Relations

User should expose the collections used by these models:

text
bookmarks         Bookmark[]
highlights        Highlight[]
notes             Note[]
readerPreferences ReaderPreference?

Update the Book Relations

Book should expose:

text
bookmarks  Bookmark[]
highlights  Highlight[]
notes      Note[]

Check the Relationship Design

Highlights can have notes, while notes can also belong directly to a book. This gives the annotations UI enough information to support passage notes and book-level notes without coupling the reader to the database implementation.

Test

Run:

bash
npx prisma format
npx prisma validate

Checkpoint

The Prisma schema now represents the complete persistence model required by the remaining Readly course modules.