A comprehensive REST API for a web-based reading planner and tracker application built with Node.js, Express.js, and MySQL/MariaDB.
- User Management: Registration, login, profile management with JWT authentication
- Library Management: CRUD operations for books with metadata, genres, and series support
- Reading Plans: Create and manage reading queues with drag-and-drop ordering
- Progress Tracking: Track reading progress with automatic percentage calculations and streaks
- Auto-Generation: Generate reading plans with series interspersing
- Statistics: Comprehensive reading stats including streaks and monthly progress
- Exports: CSV, JSON, PDF reports and ICS calendar exports
- Import: LibraryThing JSON import support
The application uses a relational database with the following key tables:
users: User accounts with authenticationbooks: Book library with metadata and exclusionsseries: Book series groupinggenres&book_genres: Many-to-many genre taggingplans&plan_items: Reading queues with orderingprogress: Reading progress tracking
See schema.sql for complete database schema with indexes and constraints.
├── config/
│ └── db.js # Database connection configuration
├── controllers/
│ ├── authController.js # Authentication logic
│ ├── bookController.js # Book CRUD operations
│ ├── planController.js # Reading plan management
│ ├── progressController.js # Progress tracking
│ └── exportController.js # Data export functionality
├── middleware/
│ └── auth.js # JWT authentication middleware
├── models/
│ ├── User.js # User model
│ ├── Book.js # Book model
│ ├── Plan.js # Plan model
│ ├── Progress.js # Progress model
│ ├── Series.js # Series model
│ └── Genre.js # Genre model
├── routes/
│ ├── auth.js # Authentication routes
│ ├── books.js # Book routes
│ ├── plans.js # Plan routes
│ ├── progress.js # Progress routes
│ └── exports.js # Export routes
├── server.js # Main application entry point
├── package.json # Dependencies and scripts
├── .env.example # Environment variables template
└── schema.sql # Database schema
POST /api/auth/register- User registrationPOST /api/auth/login- User loginGET /api/auth/me- Get user profilePATCH /api/auth/users/:id- Update user profile
GET /api/books- Get books (paginated, searchable)GET /api/books/:id- Get single bookPOST /api/books- Create bookPUT /api/books/:id- Update bookDELETE /api/books/:id- Delete bookPOST /api/books/import- Import from LibraryThing JSON
GET /api/plans- Get user's plansPOST /api/plans- Create planGET /api/plans/:id- Get plan with itemsDELETE /api/plans/:id- Delete planPOST /api/plans/:id/books- Add book to planPUT /api/plans/:id/items/:itemId/order- Update item orderDELETE /api/plans/:id/items/:itemId- Remove book from planPOST /api/plans/generate- Generate advanced auto-plan with flexible rules
Auto-Generation Rules:
{
"bookIds": [1, 2, 3], // Optional: specific books to include
"seriesIds": [1, 2], // Optional: specific series to include
"rules": {
"intersperseSeries": true, // Enable series interspersing
"seriesInterval": 2, // Insert non-series every N series books
"alternateGenres": false, // Alternate single books instead of pairs
"prioritizeSeries": true, // Series books first, then non-series
"maxBooks": 50 // Maximum books in generated plan
}
}POST /api/progress/:bookId- Update reading progress with automatic percentage calculationGET /api/progress/book/:bookId- Get progress for specific bookGET /api/progress- Get all user progressGET /api/progress/stats- Get comprehensive reading statistics with Chart.js data
PATCH /api/plans/:id/recalculate- Recalculate plan estimates and adjust dates
GET /api/exports/progress/csv- Export progress as CSVGET /api/exports/progress/json- Export progress as JSONGET /api/exports/progress/pdf- Export progress as PDFGET /api/exports/plans/:planId/ics- Export plan as ICS calendar
-
Clone the Repository
git clone <repository-url> cd readingPlanner
-
Using Docker Compose (Recommended)
# Copy environment file cp .env.example .env # Build and start all services docker-compose up --build # Or run in background docker-compose up -d --build
The application will be available at:
- Frontend: http://localhost:3001
- Backend API: http://localhost:3000
- Database: localhost:3306
-
Manual Setup (Alternative)
# Install backend dependencies npm install # Set up MySQL database manually # Create database and run schema.sql # Configure environment variables cp .env.example .env # Edit .env with your database credentials # Start backend npm run dev # In another terminal, start frontend cd frontend npm install npm start
-
Server Requirements
- Ubuntu 20.04+ or similar Linux distribution
- At least 2GB RAM, 2 CPU cores
- Docker and Docker Compose installed
-
Deploy to VPS
# Clone repository on your VPS git clone <repository-url> cd readingPlanner # Copy and configure environment cp .env.example .env nano .env # Edit with production values # Build and start services docker-compose up -d --build # Check logs docker-compose logs -f # Scale if needed docker-compose up -d --scale backend=2
-
Nginx Reverse Proxy (Optional)
server { listen 80; server_name your-domain.com; location / { proxy_pass http://localhost:3001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /api { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
-
SSL with Let's Encrypt
# Install certbot sudo apt install certbot python3-certbot-nginx # Get SSL certificate sudo certbot --nginx -d your-domain.com
Required Environment Variables:
# Database Configuration
DB_HOST=db
DB_USER=reading_user
DB_PASSWORD=reading_password
DB_NAME=reading_planner
# JWT Secret (CHANGE THIS IN PRODUCTION!)
JWT_SECRET=your_super_secret_jwt_key_change_this_in_production
# Server Configuration
NODE_ENV=production
PORT=3000
# Frontend Configuration
REACT_APP_API_URL=http://localhost:3000/api# Start services
docker-compose up -d
# Stop services
docker-compose down
# View logs
docker-compose logs -f backend
docker-compose logs -f frontend
docker-compose logs -f db
# Rebuild specific service
docker-compose up -d --build backend
# Clean up
docker-compose down -v # Remove volumes too
docker system prune -a # Clean up unused imagesCommon Issues:
-
Database Connection Failed
# Check if database is healthy docker-compose ps docker-compose logs db # Reset database docker-compose down -v docker-compose up -d db
-
Port Already in Use
# Change ports in docker-compose.yml # Or stop conflicting services sudo lsof -i :3000 sudo kill -9 <PID>
-
Build Failures
# Clear Docker cache docker system prune -a docker-compose build --no-cache -
Memory Issues
# Check system resources docker stats # Increase Docker memory limit in Docker Desktop settings
- Change JWT Secret in production environment
- Use strong passwords for database
- Enable SSL/TLS for HTTPS
- Set up monitoring with health checks
- Configure backups for database volume
- Use reverse proxy for additional security
- Set up log rotation and monitoring
- All models directly interact with the database schema defined in
schema.sql - Foreign key relationships ensure data integrity
- Indexes optimize queries for large libraries (>300 books)
- Constraints prevent invalid data (e.g., unique usernames, valid percentages)
- RESTful API design supports modern frontend frameworks (React, Vue, Angular)
- JWT tokens for secure authentication
- Pagination for efficient data loading
- CORS enabled for cross-origin requests
- JSON responses with consistent error handling
- Dashboard Stats: Chart.js integration for streak charts, yearly progress, and genre distribution
- Progress Updates: Real-time percentage calculations and streak tracking
- Plan Management: Drag-and-drop ordering with dynamic recalculation
Example Frontend Stats Integration:
// Fetch comprehensive stats for dashboard
const response = await fetch('/api/progress/stats', {
headers: { 'Authorization': `Bearer ${token}` }
});
const { stats, charts } = await response.json();
// Use with Chart.js
new Chart(ctx, charts.streakChart);
new Chart(ctx2, charts.yearlyPagesChart);
new Chart(ctx3, {
type: 'pie',
data: charts.genrePieChart
});- Secure password hashing with bcrypt
- JWT tokens with 7-day expiration
- Protected routes require valid authentication
- User-specific data isolation
- Container-ready with environment-based configuration
- Connection pooling configured for production scalability
- Can be deployed with docker-compose.yml:
version: '3.8' services: app: build: . ports: - "3000:3000" environment: - DB_HOST=db - DB_USER=user - DB_PASSWORD=password - DB_NAME=reading_planner - JWT_SECRET=secret depends_on: - db db: image: mariadb:10.6 environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_DATABASE=reading_planner volumes: - db_data:/var/lib/mysql ports: - "3306:3306" command: --innodb-buffer-pool-size=1G --max-connections=1000 volumes: db_data:
The POST /api/plans/generate endpoint integrates with the database schema and frontend through:
- Database Queries: Filters unread books using
progresstable joins, groups byseries_id, applies rules - JWT Authentication: Uses middleware to ensure user-specific plan generation
- Frontend Integration: Returns plan data with items, estimates for UI display and drag-drop ordering
- Series Logic: Leverages
books.series_idandseriestable for intelligent grouping - Progress Tracking: Excludes completed books (100% progress) for accurate unread filtering
Example Frontend Integration:
// Generate plan with custom rules
const response = await fetch('/api/plans/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
seriesIds: [1, 2],
rules: {
intersperseSeries: true,
seriesInterval: 2,
maxBooks: 20
}
})
});
const { plan, items, estimates } = await response.json();
// Use plan data for UI rendering and estimates for progress tracking- Pagination: Efficient handling of large book collections
- Advanced Auto-Generation: Flexible series interspersing with customizable rules
- Configurable intervals for inserting non-series books
- Support for alternating single books or pairs
- Maximum book limits and prioritization options
- Automatic unread book filtering
- Progress Tracking: Real-time progress updates with automatic percentage calculation
- Database transactions for data consistency
- Streak tracking with date-based logic
- User-specific progress isolation
- Comprehensive Statistics: Chart.js-compatible data for dashboard visualization
- Reading streaks over time
- Yearly/monthly page counts
- Genre distribution analysis
- Monthly goal progress tracking
- Plan Recalculation: Dynamic estimate adjustments based on reading speed changes
- Export Formats: Multiple export options for data portability
- Import Support: LibraryThing JSON import for existing collections
- Password hashing with bcrypt
- JWT token-based authentication
- Input validation and sanitization
- SQL injection prevention with parameterized queries
- CORS configuration for frontend integration
- Error handling without exposing sensitive information