- Initialize Git repository with main branch - Create comprehensive .gitignore for Node.js, React, and environment files - Set up directory structure (frontend/, backend/, docs/) - Create detailed README.md with project overview and setup instructions - Add .env.example with all required environment variables - Configure Prettier for consistent code formatting All acceptance criteria met: ✅ Git repository initialized with appropriate .gitignore ✅ Directory structure matches Technical Assumptions ✅ README.md created with project overview and setup docs ✅ .env.example file with all required environment variables ✅ Prettier config files added for code formatting consistency 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2.7 KiB
2.7 KiB
Database Schema
Prisma Schema Definition
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Book {
id Int @id @default(autoincrement())
title String @db.VarChar(500)
author String? @db.VarChar(500)
totalPages Int
coverUrl String? @db.VarChar(1000)
deadlineDate DateTime @db.Date
isPrimary Boolean @default(false)
status String @default("reading") @db.VarChar(50)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
readingLogs ReadingLog[]
@@index([deadlineDate])
@@index([status])
}
model ReadingLog {
id Int @id @default(autoincrement())
bookId Int
logDate DateTime @db.Date
currentPage Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
book Book @relation(fields: [bookId], references: [id], onDelete: Cascade)
@@unique([bookId, logDate])
@@index([bookId])
@@index([logDate])
}
SQL Schema (Generated)
-- Books table
CREATE TABLE "Book" (
"id" SERIAL PRIMARY KEY,
"title" VARCHAR(500) NOT NULL,
"author" VARCHAR(500),
"totalPages" INTEGER NOT NULL,
"coverUrl" VARCHAR(1000),
"deadlineDate" DATE NOT NULL,
"isPrimary" BOOLEAN NOT NULL DEFAULT false,
"status" VARCHAR(50) NOT NULL DEFAULT 'reading',
"createdAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP NOT NULL
);
-- Indexes for Books
CREATE INDEX "Book_deadlineDate_idx" ON "Book"("deadlineDate");
CREATE INDEX "Book_status_idx" ON "Book"("status");
-- Reading Logs table
CREATE TABLE "ReadingLog" (
"id" SERIAL PRIMARY KEY,
"bookId" INTEGER NOT NULL,
"logDate" DATE NOT NULL,
"currentPage" INTEGER NOT NULL,
"createdAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP NOT NULL,
CONSTRAINT "ReadingLog_book_fkey" FOREIGN KEY ("bookId") REFERENCES "Book"("id") ON DELETE CASCADE
);
-- Unique constraint: one log per book per day
CREATE UNIQUE INDEX "ReadingLog_bookId_logDate_key" ON "ReadingLog"("bookId", "logDate");
-- Indexes for ReadingLog
CREATE INDEX "ReadingLog_bookId_idx" ON "ReadingLog"("bookId");
CREATE INDEX "ReadingLog_logDate_idx" ON "ReadingLog"("logDate");
Performance Considerations:
- Indexes on
deadlineDateandstatusfor filtering active books - Composite unique index on
(bookId, logDate)prevents duplicate logs and optimizes queries - Index on
logDatefor date range queries (7-day rolling average) - Cascade delete ensures orphaned logs don't persist when book is deleted