- 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>
52 KiB
Book Reading Tracker - Product Requirements Document (PRD)
Project: Book Reading Tracker Author: John (Product Manager) 📋 Created: 2025-12-01 Status: Draft v1.0 Related Documents:
- Project Brief:
docs/brief.md - Brainstorming Session:
docs/brainstorming-session-results.md
Goals and Background Context
Goals
- Enable book club members to track daily reading progress and meet deadlines consistently
- Provide actionable pace calculations that tell users exactly how many pages to read per day
- Create a frictionless mobile-first experience with <10 second logging workflow
- Deliver MVP within 4-6 weeks with zero ongoing operational costs
- Validate concept for single-user deployment before considering multi-user expansion
- Maintain simplicity and focus - solve the deadline problem without feature bloat
Background Context
Book club participants face a recurring challenge: finishing assigned books by discussion deadlines. Missing these deadlines results in spoiler exposure and diminished participation quality. Existing solutions (Goodreads, habit trackers, spreadsheets) don't provide deadline-focused pace calculation or frictionless mobile logging.
This PWA addresses the gap by combining Open Library book metadata, simple daily logging, dynamic pace calculation, and visual status indicators. Built for self-hosting on Coolify infrastructure to ensure zero ongoing costs, full privacy, and complete control. The MVP focuses ruthlessly on the core problem: helping users meet book club deadlines through clear, actionable feedback on reading pace.
Change Log
| Date | Version | Description | Author |
|---|---|---|---|
| 2025-12-01 | 1.0 | Initial PRD created from Project Brief | John (PM) |
Requirements
Functional
FR1: System shall integrate with Open Library API to search books by title, author, or ISBN
FR2: System shall display book search results with cover images, title, author, and page count
FR3: System shall allow user to select a book from search results and add it to their reading list
FR4: System shall require user to set a deadline date when adding a book to the reading list
FR5: System shall display active books in a list view on the main screen
FR6: System shall allow user to log current page number for any active book via a quick-tap workflow (tap book → enter page → save)
FR7: System shall calculate required pages per day as: (Total Pages - Current Page) ÷ (Days Until Deadline)
FR8: System shall calculate actual reading pace as a rolling 7-day average of pages read per day
FR9: System shall display both required pace and actual pace with clear labeling
FR10: System shall show pages remaining and days remaining for each active book
FR11: System shall provide color-coded status indicator:
- Green: Actual pace ≥ Required pace (on track)
- Yellow: Actual pace within 10% of required pace (slightly behind)
- Red: Actual pace >10% below required pace (falling behind)
FR12: System shall display a calendar view showing dates when user logged progress
FR13: System shall highlight current date and deadline dates on the calendar
FR14: System shall persist all book data and reading logs in PostgreSQL database
FR15: System shall function as a Progressive Web App (PWA) installable via "Add to Home Screen"
FR16: System shall work offline for viewing existing data and logging entries (sync when online)
FR17: System shall validate page number inputs (must be numeric, >0, ≤ total pages)
FR18: System shall prevent logging page numbers that are less than previously logged page for the same book (can only move forward)
FR19: System shall recalculate required pace automatically each day as deadline approaches
FR20: System shall cache book metadata from Open Library to reduce API calls and improve performance
Non Functional
NFR1: Page load time shall be <2 seconds on 3G mobile connection
NFR2: Log entry save operation shall complete in <1 second
NFR3: Application shall be mobile-responsive and fully functional on screen sizes from 320px to 1920px width
NFR4: Application shall support last 2 versions of Chrome, Safari, Firefox, and Edge browsers
NFR5: Application shall use HTTPS for all communications (enforced by Coolify/PWA requirements)
NFR6: Application shall sanitize all user inputs to prevent XSS attacks
NFR7: Application shall use parameterized queries or ORM to prevent SQL injection
NFR8: Application shall deploy as Docker containers to Coolify infrastructure
NFR9: Database shall have automated backup mechanism via Coolify PostgreSQL management
NFR10: Application shall respect Open Library API rate limits and implement appropriate caching/retry logic
NFR11: Frontend bundle size shall be optimized for mobile (<500KB initial load)
NFR12: Application shall handle Open Library API failures gracefully with user-friendly error messages
NFR13: PWA service worker shall cache static assets and implement cache-first strategy for offline support
NFR14: Application shall be accessible and usable with keyboard navigation for basic workflows
NFR15: All REST API endpoints shall validate inputs and return appropriate HTTP status codes and error messages
User Interface Design Goals
Overall UX Vision
The Book Reading Tracker emphasizes simplicity, speed, and clarity above all else. The interface is designed for daily micro-interactions (<10 seconds) on mobile devices. Visual design is minimal and text-focused, prioritizing information density and fast comprehension over decorative elements.
Key principles:
- Mobile-first: Every interaction optimized for thumb-friendly tapping
- Information hierarchy: Most critical data (required pace, status) immediately visible
- Minimal chrome: No unnecessary navigation, buttons, or decorative elements
- Fast feedback: Immediate visual confirmation of actions (page logged, status updated)
Key Interaction Paradigms
3-Tap Logging Workflow: The core interaction is logging progress in 3 taps:
- Tap book card from list
- Tap/enter page number in modal
- Tap save button
Pull-to-Refresh: Standard mobile pattern for refreshing book list and recalculating paces
Color-Coded Status: No need to read text - green/yellow/red instantly communicates on-track status
Calendar as Read-Only Reference: Calendar is informational (show logged days, deadlines), not primary logging interface in MVP
Core Screens and Views
1. Book List Screen (Home/Main)
- Primary screen showing all active books
- Each book card displays: cover thumbnail, title, author, required pace, actual pace, status indicator
- "Add Book" button prominently placed
- Bottom navigation (if needed): Home, Calendar
2. Add Book Screen
- Search input field
- Search results list with cover images
- Book detail preview with deadline date picker
- "Add to Reading List" button
3. Log Progress Modal
- Triggered by tapping book card
- Shows book title/cover for context
- Number input for current page
- "Save" and "Cancel" buttons
- Displays last logged page and date
4. Book Detail Screen
- Full book information (cover, title, author, total pages)
- Detailed progress metrics (pages read, days elapsed, pace trend)
- Calendar view for this specific book
- "Log Progress" button
- Edit deadline option
- Remove book option
5. Calendar View Screen
- Month view with dots/indicators on logged days
- Deadline dates marked distinctly
- Current date highlighted
- Tap date to see details (read-only in MVP)
6. Settings Screen (Minimal)
- App version
- Data export (future)
- Link to documentation/help
Accessibility
WCAG AA Compliance (Target):
- Minimum color contrast ratios (4.5:1 for normal text)
- Color-coded status also includes text labels (not relying on color alone)
- Keyboard navigable (tab order, enter to submit)
- Semantic HTML for screen readers
- Touch targets minimum 44x44px
Branding
Minimal, Functional Aesthetic:
- No specific brand identity required for MVP
- Clean, modern design with focus on readability
- Neutral color palette (grays, blues) with accent colors for status (green/yellow/red)
- System fonts or simple web-safe font stack
- Book cover images provide visual variety
Visual Style:
- Text-heavy, data-forward design
- Generous white space for mobile clarity
- Card-based layout for book list
- Subtle shadows/borders for depth
Target Device and Platforms
Web Responsive (Mobile-First):
- Primary: Mobile browsers (iOS Safari, Android Chrome)
- Secondary: Desktop browsers for occasional access
- PWA Installation: Supported on both mobile and desktop
Supported Platforms:
- iOS (last 2 versions of Safari)
- Android (last 2 versions of Chrome)
- Desktop (Chrome, Firefox, Safari, Edge - last 2 versions)
Technical Assumptions
Repository Structure
Monorepo:
The project will use a single Git repository containing both frontend and backend code, organized as follows:
books/
├── frontend/ # React + Vite PWA
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── pages/ # Page components
│ │ ├── hooks/ # Custom React hooks
│ │ ├── services/ # API client, utilities
│ │ ├── assets/ # Images, icons
│ │ └── App.jsx # Root component
│ ├── public/ # Static assets, PWA manifest
│ ├── index.html
│ ├── vite.config.js
│ ├── package.json
│ └── Dockerfile
├── backend/ # Node.js + Express API
│ ├── src/
│ │ ├── routes/ # API route handlers
│ │ ├── controllers/ # Business logic
│ │ ├── services/ # External integrations (Open Library)
│ │ ├── middleware/ # Auth, validation, error handling
│ │ └── server.js # Express app entry
│ ├── prisma/ # Prisma schema and migrations
│ │ └── schema.prisma
│ ├── package.json
│ └── Dockerfile
├── docker-compose.yml # Local development orchestration
├── .env.example # Environment variable template
├── docs/ # Project documentation
└── README.md
Rationale:
- Monorepo simplifies coordination between frontend and backend changes
- Shared tooling and dependencies easier to manage
- Single repository for deployment to Coolify
- Aligns with AI-assisted development workflow (Claude Code can see full context)
Service Architecture
Monolithic Architecture with Separate Frontend/Backend Containers:
- Frontend Container: React PWA served by Vite production build (static files)
- Backend Container: Node.js + Express REST API
- Database: PostgreSQL container (managed by Coolify)
Communication Flow:
User (Browser)
↓ HTTPS
Frontend (PWA)
↓ REST API calls
Backend (Express)
↓ Prisma ORM
PostgreSQL Database
External: Open Library API (book search)
Rationale:
- Simple, proven architecture for MVP scope
- Easy to deploy and debug with only 3 containers
- No need for microservices complexity at this scale
- Aligns with "simplest thing that works" principle
- Frontend and backend can be developed and deployed independently
Deployment:
- Both containers deployed to single Coolify instance
- Reverse proxy (Caddy/Nginx) handles routing and SSL
- Environment-based configuration (dev, production)
Testing Requirements
Unit + Integration Testing:
Frontend:
- Unit Tests: Component testing with Vitest and React Testing Library
- Coverage Target: >70% for critical business logic (pace calculation, validation)
- Tests Required For:
- Pace calculation logic
- Form validation
- Date manipulation utilities
- API service layer
Backend:
- Unit Tests: Route handlers and business logic with Jest
- Integration Tests: API endpoints with test database
- Coverage Target: >80% for API routes and core logic
- Tests Required For:
- All REST API endpoints (CRUD operations)
- Pace calculation algorithms
- Open Library API integration (mocked)
- Database operations (via Prisma)
Manual Testing:
- Mobile device testing (iOS Safari, Android Chrome)
- PWA installation and offline functionality
- Cross-browser compatibility
- Responsive design validation
No E2E Testing in MVP:
- Manual user acceptance testing sufficient for single-user MVP
- E2E framework (Playwright/Cypress) can be added post-MVP if needed
Rationale:
- Balances test coverage with development velocity
- Focuses testing on business-critical logic (pace calculation)
- Manual testing acceptable for UI/UX validation in MVP
- Automated tests provide regression safety for future development
Additional Technical Assumptions and Requests
Frontend Technology Stack:
- React 18+ with functional components and hooks
- Vite for build tooling and dev server
- Tailwind CSS for styling (utility-first, mobile-friendly)
- React Context API for state management (no Redux/Zustand needed)
- Axios or Fetch API for HTTP requests
- vite-plugin-pwa for PWA functionality and service worker
- date-fns for date manipulation (lightweight alternative to Moment.js)
Backend Technology Stack:
- Node.js 20+ LTS
- Express 4.x for REST API
- Prisma as ORM for PostgreSQL
- dotenv for environment configuration
- cors middleware for cross-origin requests
- helmet for security headers
- express-validator for input validation
Database:
- PostgreSQL 15+
- Prisma migrations for schema management
- Connection pooling configured in Prisma
Development Tools:
- Git for version control
- ESLint for code linting
- Prettier for code formatting
- Docker and Docker Compose for local development
- Postman/Insomnia for API testing during development
Environment Variables:
DATABASE_URL- PostgreSQL connection stringAPI_PORT- Backend API port (default: 3000)FRONTEND_URL- Frontend URL for CORS configurationNODE_ENV- Environment (development, production)OPEN_LIBRARY_API_URL- Open Library API base URL
Error Handling and Logging:
- Backend: Centralized error handling middleware
- Frontend: Error boundary components for React error handling
- Logging: Console logging in development, structured logging in production (Winston or Pino)
API Design Conventions:
- RESTful endpoints following standard conventions
- JSON request/response bodies
- HTTP status codes: 200 (success), 201 (created), 400 (bad request), 404 (not found), 500 (server error)
- Consistent error response format:
{ error: "message", details: {} }
Code Quality:
- Use ESLint + Prettier with shared configuration
- Consistent naming conventions (camelCase for JS, kebab-case for files)
- Component naming: PascalCase for React components
- Meaningful variable and function names
- Comments for complex business logic
Performance Optimization:
- Lazy loading for non-critical components
- Image optimization for book covers (cached from Open Library)
- API response caching where appropriate
- Database query optimization (indexes on frequently queried fields)
Epic List
Epic 1: Foundation & Core Infrastructure
Goal: Establish project structure, development environment, database schema, and basic API/frontend scaffolding with a simple health check endpoint to validate deployment pipeline.
Epic 2: Book Search & Management
Goal: Enable users to search for books via Open Library API and add them to their reading list with deadline dates, creating the foundation for all tracking features.
Epic 3: Progress Logging & Pace Calculation
Goal: Implement the core value proposition - allow users to log daily page numbers and display calculated required pace vs. actual pace with color-coded status indicators.
Epic 4: Calendar View & Data Visualization
Goal: Provide users with a calendar view showing logged reading activity and deadline markers, completing the basic MVP feature set.
Epic 5: PWA Features & Production Readiness
Goal: Add Progressive Web App capabilities (offline support, installability), finalize mobile responsiveness, and prepare application for production deployment to Coolify.
Epic 1: Foundation & Core Infrastructure
Epic Goal: Set up the complete development environment and project infrastructure including Git repository, frontend/backend scaffolding, database schema, Docker configuration, and a health check endpoint to validate the entire stack works end-to-end before building features.
Story 1.1: Project Initialization & Repository Setup
As a developer, I want a properly structured monorepo with frontend and backend directories, so that I have a clean foundation for building the application with all necessary tooling configured.
Acceptance Criteria:
- Git repository initialized with appropriate
.gitignorefor Node.js, React, and environment files - Directory structure matches Technical Assumptions section (frontend/, backend/, docs/)
- README.md created with project overview, setup instructions, and tech stack documentation
.env.examplefile created listing all required environment variables- Root-level
package.jsoncreated (if using monorepo workspace tools) or separate package.json files in frontend/ and backend/ - EditorConfig or Prettier config files added for consistent code formatting
Story 1.2: Frontend Scaffolding with Vite + React
As a developer, I want a Vite + React application scaffold with Tailwind CSS configured, so that I can start building UI components with the chosen tech stack.
Acceptance Criteria:
- Vite project created in
frontend/directory usingnpm create vite@latest - React 18+ configured as the framework
- Tailwind CSS installed and configured (
tailwind.config.js,postcss.config.js) - Base styles imported in main CSS file (
@tailwind base; @tailwind components; @tailwind utilities;) - Sample component renders successfully showing Tailwind styles work
- ESLint and Prettier configured for React/JavaScript
- Development server runs successfully on
http://localhost:5173(or configured port) package.jsonscripts include:dev,build,preview,lint
Story 1.3: Backend Scaffolding with Node.js + Express
As a developer, I want a Node.js Express API scaffold with basic middleware configured, so that I can start building REST API endpoints.
Acceptance Criteria:
- Express application created in
backend/src/server.js - Required dependencies installed:
express,cors,helmet,dotenv,express-validator - Middleware configured: CORS (allowing frontend origin), Helmet (security headers), JSON body parser
- Environment configuration loaded via
dotenvat startup - Server listens on port from environment variable (default: 3000)
- Basic error handling middleware implemented (catches errors, returns JSON response)
- Health check endpoint created:
GET /api/healthreturns{ status: "ok", timestamp: "..." } package.jsonscripts include:dev(nodemon for auto-reload),start(production)- ESLint configured for Node.js/Express patterns
Story 1.4: Database Schema Definition with Prisma
As a developer, I want a Prisma schema defining Books and ReadingLogs tables, so that I have a clear data model ready for implementation.
Acceptance Criteria:
- Prisma installed in
backend/directory (npm install prisma @prisma/client) - Prisma initialized with PostgreSQL provider (
npx prisma init) prisma/schema.prismafile defines the following models:
Books Model:
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])
}
ReadingLogs Model:
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])
}
- Schema includes appropriate indexes for performance (bookId, logDate, deadlineDate)
- Relationship defined: Book has many ReadingLogs (one-to-many)
- Unique constraint on ReadingLog ensures one entry per book per day
Story 1.5: Database Setup & Initial Migration
As a developer, I want the database schema migrated to a PostgreSQL database, so that the application can persist data.
Acceptance Criteria:
DATABASE_URLenvironment variable configured in.envfile- Prisma migration created:
npx prisma migrate dev --name init - Migration successfully creates
BookandReadingLogtables in PostgreSQL - Prisma Client generated and can be imported in backend code
- Database connection verified (Prisma Client can connect successfully)
- Migration files committed to Git (
prisma/migrations/) - Instructions in README.md for running migrations in new environments
Story 1.6: Docker Configuration for Local Development
As a developer, I want Docker Compose configuration for running the full stack locally, so that I can develop and test the application in a containerized environment matching production.
Acceptance Criteria:
-
Dockerfilecreated infrontend/directory:- Multi-stage build (build stage + nginx/serve stage for production)
- Development stage uses Vite dev server
- Production stage serves static build files
-
Dockerfilecreated inbackend/directory:- Node.js base image (node:20-alpine or similar)
- Installs dependencies and runs Prisma generate
- Exposes API port
- Runs
npm startcommand
-
docker-compose.ymlcreated in project root defining services:- postgres: PostgreSQL 15+ with volume for data persistence
- backend: Builds from backend/Dockerfile, depends on postgres, exposes API port
- frontend: Builds from frontend/Dockerfile, exposes dev server port, depends on backend
- Environment variables configured via
.envfile
-
docker-compose upsuccessfully starts all three containers -
Frontend accessible at
http://localhost:5173(or configured port) -
Backend API accessible at
http://localhost:3000/api/health -
Database accessible on PostgreSQL port with credentials from .env
-
Hot reload works for both frontend and backend in development mode
-
README.md updated with Docker setup and usage instructions
Story 1.7: CI/CD Deployment Configuration for Coolify
As a developer, I want deployment configuration ready for Coolify, so that I can deploy the application to production infrastructure.
Acceptance Criteria:
- Production
docker-compose.ymlor Coolify configuration file created - Environment variable template documented for Coolify deployment
- Build and deployment process documented in
docs/deployment.md:- How to configure Coolify project
- Required environment variables
- Database connection setup
- SSL/HTTPS configuration (handled by Coolify)
- Health check endpoints for monitoring
- Production Dockerfiles optimized (multi-stage builds, minimal image size)
- Database migration strategy documented (how to run migrations on deployment)
- Backup and restore procedures documented for PostgreSQL
Epic 2: Book Search & Management
Epic Goal: Enable users to search for books using the Open Library API and add selected books to their reading list with deadline dates, providing the foundation for all progress tracking features.
Story 2.1: Open Library API Integration Service
As a developer, I want a backend service that queries the Open Library API, so that users can search for books by title, author, or ISBN.
Acceptance Criteria:
- Service module created in
backend/src/services/openLibraryService.js - Function
searchBooks(query)implemented:- Makes HTTP request to
https://openlibrary.org/search.json?q={query} - Parses response and extracts relevant fields: title, author, first_publish_year, cover_i, number_of_pages, isbn
- Returns array of book objects with normalized structure
- Handles API errors gracefully (returns empty array or error object)
- Makes HTTP request to
- Function limits results to top 20 books for performance
- Book cover URLs constructed using cover_i:
https://covers.openlibrary.org/b/id/{cover_i}-M.jpg - Service includes error handling for network failures and invalid responses
- Service respects rate limits (implements basic request throttling if needed)
- Unit tests written for service (mocked HTTP responses)
Story 2.2: Book Search API Endpoint
As a user, I want an API endpoint to search for books, so that the frontend can retrieve book search results.
Acceptance Criteria:
- API endpoint created:
GET /api/books/search?q={query} - Endpoint validates query parameter (required, non-empty, max length 200 characters)
- Endpoint calls
openLibraryService.searchBooks(query) - Returns JSON response with book results:
{ "results": [ { "olid": "OL12345W", "title": "The Name of the Wind", "author": "Patrick Rothfuss", "publishYear": 2007, "coverUrl": "https://covers.openlibrary.org/b/id/123456-M.jpg", "totalPages": 662 } ] } - Returns 400 error if query parameter is missing or invalid
- Returns 500 error if Open Library API fails, with user-friendly error message
- Endpoint returns 200 with empty results array if no books found
- Caches search results for 1 hour (in-memory cache acceptable for MVP)
- Integration test written for endpoint (mocked Open Library service)
Story 2.3: Add Book API Endpoint
As a user, I want an API endpoint to add a book to my reading list, so that I can start tracking progress for that book.
Acceptance Criteria:
- API endpoint created:
POST /api/books - Endpoint accepts JSON request body:
{ "title": "The Name of the Wind", "author": "Patrick Rothfuss", "totalPages": 662, "coverUrl": "https://covers.openlibrary.org/b/id/123456-M.jpg", "deadlineDate": "2025-03-15" } - Endpoint validates all required fields: title, totalPages (>0), deadlineDate (valid date, not in past)
- Author and coverUrl are optional
- Endpoint creates new Book record in database via Prisma
- Sets
statusto "reading" by default - Returns 201 status with created book object including generated ID
- Returns 400 error if validation fails with specific error messages
- Returns 500 error if database operation fails
- Unit and integration tests written covering success and error cases
Story 2.4: List Active Books API Endpoint
As a user, I want an API endpoint to retrieve my active books, so that the frontend can display my current reading list.
Acceptance Criteria:
- API endpoint created:
GET /api/books - Endpoint queries database for all books with
status = "reading" - Returns JSON array of book objects:
{ "books": [ { "id": 1, "title": "The Name of the Wind", "author": "Patrick Rothfuss", "totalPages": 662, "coverUrl": "https://covers.openlibrary.org/b/id/123456-M.jpg", "deadlineDate": "2025-03-15", "isPrimary": false, "status": "reading", "createdAt": "2025-12-01T10:00:00Z" } ] } - Books ordered by deadline date (soonest first)
- Returns 200 status with empty array if no active books
- Returns 500 error if database query fails
- Integration test written
Story 2.5: Book Search UI Component
As a user, I want a search interface to find and select books, so that I can add them to my reading list.
Acceptance Criteria:
- "Add Book" screen/modal component created in
frontend/src/pages/AddBook.jsx - Search input field with placeholder "Search by title, author, or ISBN"
- Search triggers API call to
/api/books/search?q={query}on form submit or button click - Loading indicator displayed while search is in progress
- Search results displayed as a list/grid with:
- Book cover thumbnail (or placeholder if no cover)
- Title (bold)
- Author
- Total pages
- "Select" button
- Clicking "Select" button navigates to book detail view with pre-filled data
- Empty state message shown if no results found
- Error message shown if API call fails
- Search input debounced (300ms delay) if implementing search-as-you-type
- Component is mobile-responsive (card layout stacks vertically on small screens)
Story 2.6: Add Book Form UI
As a user, I want a form to confirm book details and set a deadline, so that I can add the book to my reading list with a finish date.
Acceptance Criteria:
- Add book form component created (can be part of AddBook screen or separate)
- Form displays selected book information (cover, title, author, total pages) as read-only
- Form includes:
- Deadline date picker (required)
- "Add to Reading List" button
- "Cancel" or "Back" button
- Deadline date picker validates:
- Date must be in the future
- User-friendly date selection interface (mobile-optimized)
- Clicking "Add to Reading List" calls
POST /api/bookswith form data - Loading state shown while API call is in progress
- Success: User redirected to home screen (book list) with success message
- Error: Error message displayed below form, user can retry
- Form validation prevents submission if deadline is invalid
- Form is mobile-responsive and thumb-friendly
Story 2.7: Book List Display UI
As a user, I want to see all my active books on the home screen, so that I can quickly view my reading list and select a book to log progress.
Acceptance Criteria:
- Home screen component created in
frontend/src/pages/Home.jsx - Component fetches active books from
GET /api/bookson mount - Books displayed as cards/list items showing:
- Cover thumbnail (left side)
- Title and author (prominent)
- Total pages and deadline date
- Placeholder text for pace calculation (to be implemented in Epic 3)
- "Add Book" button prominently displayed (e.g., floating action button or top-right)
- Empty state shown if no books (with "Add your first book" message and CTA)
- Loading state shown while fetching books
- Error state shown if API call fails (with retry button)
- Tapping a book card navigates to book detail screen (or triggers log progress modal - Epic 3)
- List ordered by deadline date (soonest first)
- Component is mobile-responsive with smooth scrolling
Epic 3: Progress Logging & Pace Calculation
Epic Goal: Implement the core value proposition by allowing users to log their current page number daily, calculating required pace vs. actual pace, and displaying clear status indicators, enabling users to track if they're on track to meet deadlines.
Story 3.1: Log Progress API Endpoint
As a user, I want an API endpoint to log my current page for a book, so that my reading progress is tracked in the system.
Acceptance Criteria:
- API endpoint created:
POST /api/books/:bookId/logs - Endpoint accepts JSON request body:
{ "currentPage": 150, "logDate": "2025-12-01" // Optional, defaults to today } - Endpoint validates:
bookIdexists in databasecurrentPageis numeric, >0, and ≤ book's totalPageslogDateis a valid date (defaults to today if not provided)currentPageis >= last logged page for this book (can't go backward)
- Endpoint creates or updates ReadingLog record:
- If log exists for this book+date, update currentPage
- If no log exists, create new ReadingLog record
- Returns 201 (created) or 200 (updated) with the created/updated log object
- Returns 400 error if validation fails with specific error message
- Returns 404 error if book not found
- Returns 500 error if database operation fails
- Unit and integration tests written covering all cases
Story 3.2: Pace Calculation Service
As a developer, I want a service that calculates required pace and actual pace, so that the application can show users if they're on track.
Acceptance Criteria:
-
Service module created in
backend/src/services/paceCalculationService.js -
Function
calculateRequiredPace(totalPages, currentPage, deadlineDate)implemented:- Calculates pages remaining:
totalPages - currentPage - Calculates days remaining:
deadlineDate - today(in days) - Returns required pages/day:
pagesRemaining / daysRemaining - Handles edge cases:
- If deadline is today or past: returns very high number or "Overdue"
- If already finished (currentPage >= totalPages): returns 0
- If days remaining = 0: returns pages remaining (all today)
- Calculates pages remaining:
-
Function
calculateActualPace(bookId, days = 7)implemented:- Queries last N days of ReadingLogs for the book
- Calculates pages read per day over that period (rolling average)
- Formula:
(latestPage - pageNDaysAgo) / N - Returns actual pages/day
- If insufficient data (<2 logs), returns null or 0
-
Function
calculateStatus(requiredPace, actualPace)implemented:- Compares required vs. actual pace
- Returns status: "on-track", "slightly-behind", "behind"
- Logic:
actualPace >= requiredPace: "on-track"actualPace >= requiredPace * 0.9: "slightly-behind" (within 10%)actualPace < requiredPace * 0.9: "behind"
-
Service includes comprehensive unit tests with various scenarios
Story 3.3: Get Book Progress API Endpoint
As a user, I want an API endpoint that returns my book progress with pace calculations, so that the frontend can display whether I'm on track.
Acceptance Criteria:
- Endpoint created:
GET /api/books/:bookId/progress - Endpoint queries book details and all reading logs for the book
- Endpoint uses paceCalculationService to calculate:
- Current page (from latest log)
- Pages remaining
- Days remaining
- Required pages/day
- Actual pace (7-day average)
- Status (on-track/slightly-behind/behind)
- Returns JSON response:
{ "bookId": 1, "currentPage": 150, "totalPages": 662, "pagesRemaining": 512, "deadlineDate": "2025-03-15", "daysRemaining": 45, "requiredPace": 11.4, "actualPace": 12.0, "status": "on-track", "lastLoggedDate": "2025-12-01" } - Returns 404 if book not found
- Returns 500 if calculation or database query fails
- Handles cases where no logs exist yet (currentPage = 0, actualPace = null)
- Integration test written
Story 3.4: Enhanced Book List API with Progress Data
As a user, I want the book list API to include progress calculations, so that I can see my pace status for all books at once.
Acceptance Criteria:
- Modify
GET /api/booksendpoint to include progress data for each book - For each book, calculate and include:
- currentPage (from latest log, or 0 if no logs)
- requiredPace
- actualPace
- status
- daysRemaining
- pagesRemaining
- Response structure:
{ "books": [ { "id": 1, "title": "The Name of the Wind", "author": "Patrick Rothfuss", "totalPages": 662, "coverUrl": "...", "deadlineDate": "2025-03-15", "currentPage": 150, "pagesRemaining": 512, "daysRemaining": 45, "requiredPace": 11.4, "actualPace": 12.0, "status": "on-track" } ] } - Calculation logic reuses paceCalculationService functions
- Optimized query to fetch all books and their latest logs efficiently (avoid N+1 queries)
- Returns 500 if calculation fails, with error details
- Integration test updated to verify progress data included
Story 3.5: Log Progress Modal UI
As a user, I want a quick modal to log my current page, so that I can update my progress in just a few taps.
Acceptance Criteria:
- Modal component created in
frontend/src/components/LogProgressModal.jsx - Modal triggered by tapping a book card from the home screen
- Modal displays:
- Book title and cover (for context)
- "What page are you on?" prompt
- Number input field (autofocused, numeric keyboard on mobile)
- Last logged: "Page X on [date]" (if exists)
- "Save" button (primary CTA)
- "Cancel" button or close icon
- Input validation:
- Must be a number
- Must be > 0 and ≤ total pages
- Must be ≥ last logged page (show error if trying to go backward)
- Clicking "Save" calls
POST /api/books/:bookId/logswith currentPage - Loading state shown while API call is in progress
- Success: Modal closes, home screen refreshes to show updated progress
- Error: Error message displayed in modal, user can retry
- Modal is mobile-optimized (large touch targets, easy to dismiss)
- Modal accessible via keyboard (Esc to close, Enter to submit)
Story 3.6: Progress Visualization on Book Cards
As a user, I want to see my pace status directly on each book card, so that I can quickly understand if I'm on track without opening details.
Acceptance Criteria:
- Book card component updated to display progress data from API
- Each card shows:
- Required Pace: "Target: 11 pages/day"
- Actual Pace: "Your pace: 12 pages/day (last 7 days)" (or "No data yet" if insufficient logs)
- Pages Remaining: "512 pages left"
- Days Remaining: "45 days until deadline"
- Color-coded status indicator (badge or border):
- 🟢 Green: "On track" (status = "on-track")
- 🟡 Yellow: "Slightly behind" (status = "slightly-behind")
- 🔴 Red: "Behind pace" (status = "behind")
- Status indicator includes both color AND text label (accessibility)
- If no logs yet, show neutral state: "Start logging to track pace"
- Component styling is mobile-responsive and readable on small screens
- Progress data updates after logging a new entry (home screen refresh)
Story 3.7: Book Detail Screen with Progress Details
As a user, I want a detailed view of a single book showing comprehensive progress information, so that I can dive deeper into my reading stats for that book.
Acceptance Criteria:
- Book detail screen created in
frontend/src/pages/BookDetail.jsx - Screen accessed by tapping on a book card (alternative to log modal, or secondary action)
- Screen displays:
- Book cover (large)
- Title and author
- Total pages and deadline date
- Progress Summary:
- Current page: "Page 150 of 662"
- Progress bar showing % complete
- Pages remaining and days remaining
- Pace Metrics:
- Required pace: "11.4 pages/day to finish on time"
- Actual pace: "12.0 pages/day (last 7 days)"
- Status indicator with color and text
- Last Logged: "Last updated: Page 150 on Dec 1, 2025"
- "Log Progress" button prominently displayed
- "Edit Deadline" button (future story, can be placeholder)
- "Remove Book" button (future story, can be placeholder)
- Screen is mobile-responsive
- Back button to return to home screen
- Screen fetches data from
GET /api/books/:bookId/progress
Epic 4: Calendar View & Data Visualization
Epic Goal: Provide users with a calendar view showing which days they logged reading progress and marking deadline dates, completing the core MVP feature set and enabling users to visualize their reading habits.
Story 4.1: Get Reading Logs for Calendar API Endpoint
As a user, I want an API endpoint that returns all my logged days for a book, so that the frontend can display them on a calendar.
Acceptance Criteria:
- API endpoint created:
GET /api/books/:bookId/logs - Endpoint queries all ReadingLog records for the specified book
- Returns JSON array of logs:
{ "logs": [ { "id": 1, "logDate": "2025-12-01", "currentPage": 150 }, { "id": 2, "logDate": "2025-11-30", "currentPage": 138 } ] } - Logs ordered by logDate descending (most recent first)
- Returns 404 if book not found
- Returns 200 with empty array if no logs exist
- Returns 500 if database query fails
- Integration test written
Story 4.2: Calendar Component UI (Basic)
As a user, I want a calendar view showing the days I logged reading progress, so that I can visualize my reading consistency.
Acceptance Criteria:
- Calendar view component created in
frontend/src/components/Calendar.jsx - Component displays a month view calendar (current month by default)
- Previous/next month navigation buttons
- Days with logged reading progress marked with a dot or highlight
- Current date highlighted distinctly
- Deadline date marked with a special indicator (🎯 or colored border)
- Component fetches logs from
GET /api/books/:bookId/logson mount - Component fetches book details (for deadline date) from
GET /api/books/:bookId - Days without logs appear as normal calendar days (no indicator)
- Calendar is mobile-responsive (readable on small screens)
- Uses a lightweight calendar library (e.g.,
react-calendar, or custom-built if simple enough) - Loading state shown while fetching data
- Error state shown if API calls fail
Story 4.3: Calendar Screen Integration
As a user, I want a dedicated calendar screen accessible from navigation, so that I can view my reading activity over time.
Acceptance Criteria:
- Calendar screen component created in
frontend/src/pages/CalendarView.jsx - Screen includes:
- Book selector (if multiple books exist) to choose which book's calendar to view
- Calendar component showing logged days and deadline for selected book
- Legend explaining visual indicators (dot = logged, highlighted = deadline, etc.)
- Default: Shows calendar for primary book (or first book if no primary)
- Book selector displays as dropdown or horizontal scrollable list with book covers/titles
- Changing selected book updates calendar display
- Screen accessible from bottom navigation or menu (if navigation exists)
- Mobile-responsive layout
- Back button to return to home screen
Story 4.4: Calendar View on Book Detail Screen
As a user, I want to see the calendar for a specific book on its detail screen, so that I don't have to navigate to a separate calendar view.
Acceptance Criteria:
- Book detail screen (from Story 3.7) updated to include Calendar component
- Calendar component rendered below progress metrics section
- Calendar automatically shows logs for the current book (no book selector needed)
- Calendar can be collapsed/expanded to save screen space (optional, nice-to-have)
- Calendar updates when a new log is added for the book
- Mobile-responsive: Calendar doesn't overwhelm small screens (possibly scrollable)
Epic 5: PWA Features & Production Readiness
Epic Goal: Transform the application into a fully functional Progressive Web App with offline support, installability, and mobile optimizations, then finalize production deployment to Coolify to deliver a complete, production-ready MVP.
Story 5.1: PWA Manifest & Service Worker Setup
As a user, I want the app to be installable on my mobile device, so that it feels like a native app and is easily accessible from my home screen.
Acceptance Criteria:
- PWA manifest file created in
frontend/public/manifest.json:- App name: "Book Reading Tracker" (or final name)
- Short name: "ReadTrack" (or similar)
- Description, theme color, background color
- Icons for various sizes (192x192, 512x512 minimum)
display: "standalone"for app-like experiencestart_url: "/"andscope: "/"
vite-plugin-pwaconfigured invite.config.js- Service worker generated for offline caching
- Static assets (JS, CSS, images) cached for offline access
- API responses cached with network-first or cache-first strategy where appropriate
- "Add to Home Screen" prompt appears on supported browsers
- App icon and splash screen display when launched from home screen
- Service worker updates automatically when new version deployed
- App works offline (cached pages accessible, with graceful degradation for API calls)
- PWA audit (Lighthouse) passes with score >80
Story 5.2: Offline Support & Sync Strategy
As a user, I want to log reading progress even when offline, so that I don't lose data if I don't have internet connection.
Acceptance Criteria:
- Service worker caches critical app shell (HTML, CSS, JS)
- Reading logs can be entered offline and stored in IndexedDB (or similar local storage)
- When connection restored, queued logs sync to backend API automatically
- UI indicates when user is offline (banner or icon)
- UI indicates when data is being synced
- Conflicts handled gracefully (e.g., if same book/date logged offline then online)
- User can view previously loaded book list and progress data offline
- Search for new books disabled offline (requires API call)
- Offline mode tested on mobile devices (airplane mode)
Story 5.3: Mobile Responsiveness & Touch Optimization
As a user, I want the app to work smoothly on my phone with touch-friendly interactions, so that it's easy to use on small screens.
Acceptance Criteria:
- All screens tested and responsive on screen sizes: 320px, 375px, 414px, 768px, 1024px, 1920px
- Touch targets minimum 44x44px for all interactive elements (buttons, links, inputs)
- Form inputs use appropriate input types (
type="number"for page numbers,type="date"for dates) - Mobile keyboards optimized (numeric keyboard for page input)
- Scroll behavior smooth and natural on mobile (no janky scrolling)
- No horizontal scrolling on mobile (all content fits within viewport)
- Text readable without zooming (minimum 16px font size for body text)
- Images and covers optimized for mobile (lazy loading, appropriate sizes)
- Pull-to-refresh works on home screen for updating book list
- Tested on real devices: iOS (iPhone) and Android
Story 5.4: Performance Optimization
As a user, I want the app to load quickly and respond instantly, so that I can log my progress without waiting.
Acceptance Criteria:
- Lighthouse performance score >80 on mobile, >90 on desktop
- First Contentful Paint <1.5 seconds on 3G connection
- Time to Interactive <3 seconds on 3G connection
- Frontend bundle size <500KB (gzipped)
- Images optimized (compressed, appropriate formats, lazy loaded)
- API responses compressed (gzip enabled on backend)
- Critical CSS inlined or loaded first
- Non-critical JavaScript lazy loaded
- Database queries optimized (indexes used, no N+1 queries)
- API response times <200ms for common endpoints (GET /api/books, POST /api/books/:id/logs)
Story 5.5: Error Handling & User Feedback
As a user, I want clear error messages and feedback when something goes wrong, so that I understand what happened and how to fix it.
Acceptance Criteria:
- All API errors return user-friendly error messages (not technical stack traces)
- Frontend displays error messages in a consistent UI pattern (toast notifications, inline errors)
- Network errors handled gracefully ("Unable to connect. Please check your internet connection.")
- Validation errors show specific field-level feedback ("Deadline must be in the future")
- Loading states shown for all async operations (spinners, skeleton screens)
- Success feedback shown after actions (e.g., "Book added!" or "Progress logged!")
- 404 errors handled with "Not Found" page and navigation back to home
- 500 errors handled with "Something went wrong" message and retry option
- Empty states provide clear CTAs ("No books yet. Add your first book!")
- Offline state clearly communicated to user
Story 5.6: Production Deployment to Coolify
As a developer, I want the application deployed to Coolify production environment, so that it's accessible to the user via a public URL with HTTPS.
Acceptance Criteria:
- Coolify project configured with:
- Frontend container (serving React build via nginx or similar)
- Backend container (Node.js Express API)
- PostgreSQL database container
- Environment variables configured in Coolify (DATABASE_URL, API URL, etc.)
- Database migrations run successfully on production database
- HTTPS enabled via Coolify (automatic SSL with Let's Encrypt)
- Custom domain configured (if applicable) or Coolify subdomain used
- Health check endpoints monitored (
/api/health) - Application accessible via public URL
- PWA installable from production URL
- Database backups configured (automated via Coolify PostgreSQL management)
- Deployment documented in
docs/deployment.mdwith rollback procedure
Story 5.7: Testing & Quality Assurance
As a developer, I want comprehensive testing to ensure the MVP works correctly, so that we can ship a reliable product.
Acceptance Criteria:
- Unit tests written for:
- Frontend: Pace calculation logic, form validation, utility functions
- Backend: API endpoints, paceCalculationService, openLibraryService
- Integration tests written for:
- All backend API endpoints with test database
- Frontend API integration (mocked backend responses)
- Test coverage >70% for critical business logic (pace calculation, logging, validation)
- Manual testing checklist completed:
- Add book flow (search, select, set deadline, add)
- Log progress flow (tap book, enter page, save)
- View book list with progress metrics
- View calendar with logged days
- Install PWA on mobile device
- Use app offline, sync when online
- Responsive design on multiple screen sizes
- Cross-browser testing completed (Chrome, Safari, Firefox on desktop; Safari iOS, Chrome Android)
- Accessibility testing (keyboard navigation, screen reader basics)
- Performance testing (Lighthouse audits pass thresholds)
- Critical bugs fixed, known issues documented
Checklist Results Report
(This section will be populated after running the PM checklist. For now, proceeding to Next Steps.)
Note to Developer: Before finalizing this PRD, run the PM checklist (.bmad-core/checklists/pm-checklist.md) to validate completeness, identify gaps, and ensure all requirements are testable and implementable.
Next Steps
UX Expert Prompt
UX Expert, please review this PRD and create wireframes or design specifications for the Book Reading Tracker app. Focus on:
- Mobile-first design for all screens (Book List, Add Book, Log Progress Modal, Book Detail, Calendar)
- Visual hierarchy emphasizing pace metrics and status indicators
- Touch-friendly interactions and input patterns
- Minimal, text-forward aesthetic with clear information density
- Color palette for status indicators (green/yellow/red) with accessibility considerations
Refer to the User Interface Design Goals section for detailed requirements. Deliverables: Wireframes (low-fi or high-fi) for core screens and interaction patterns.
Architect Prompt
Architect, please review this PRD and create the technical architecture document for the Book Reading Tracker app. Use this PRD as input and focus on:
- Detailed API endpoint specifications (request/response schemas, validation rules, error codes)
- Database schema refinement (indexes, constraints, relationships)
- Frontend component architecture (component tree, state management strategy, routing)
- Service layer design (backend services, external API integration patterns)
- Security considerations (input validation, CORS, HTTPS, data privacy)
- Deployment architecture (Docker container configuration, Coolify setup, environment management)
- Testing strategy (unit, integration, E2E considerations)
Refer to the Technical Assumptions section for technology stack decisions. Deliverables: Architecture document detailing system design, API specs, component diagrams, and deployment plan.
PRD created using BMAD-METHOD™ framework Based on Project Brief (docs/brief.md) and Brainstorming Session (docs/brainstorming-session-results.md)