┌─────────────────────────────────────────────────────────────────┐
│ Chapter System │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Web Client │ ◄─────► │ Caddy │ │
│ │ (Next.js) │ HTTPS │ (Reverse │ │
│ │ │ │ Proxy) │ │
│ └──────────────┘ └──────┬───────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Chapter Server │ │
│ │ (Fastify) │ │
│ └────┬───┬───┬────┘ │
│ │ │ │ │
│ ┌──────────────────┘ │ └─────────────┐ │
│ │ │ │ │
│ ┌────▼────┐ ┌───────▼──────┐ ┌─────▼──────┐ │
│ │PostgreSQL│ │ Redis │ │ Kokoro │ │
│ │ (Data) │ │ (Cache) │ │ TTS │ │
│ └──────────┘ └──────────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Purpose: User interface for reading books and listening to audiobooks
Technology:
- Next.js 14 with App Router
- React 18
- Tailwind CSS + shadcn/ui
- Zustand (state management)
- TanStack Query (API calls)
- Howler.js (audio playback)
Key Features:
- Server-side rendering
- Responsive design
- Dark mode support
- Offline-capable (future)
Routes:
/- Landing page/login- Authentication/library- Book library/reader/:bookId- Reading interface/settings- User preferences
Purpose: Backend API handling all business logic
Technology:
- Node.js 20
- Fastify 4 (high-performance HTTP server)
- Prisma (ORM)
- JWT authentication
- TypeScript
Modules:
- User registration and login
- JWT token generation and validation
- Password hashing (bcrypt)
- Session management
- EPUB upload and parsing
- Book metadata extraction
- Chapter and paragraph storage
- Tokenization
- Cover image handling
- Multi-level position tracking
- Reading/audiobook mode switching
- Position synchronization
- Session time tracking
- Kokoro service integration
- Voice management
- Audio chunk generation
- Cache management
- User profile management
- Settings (TTS, reading preferences)
- User-book relationships
Purpose: Primary data store (embedded, zero-config)
Schema:
Users (authentication, preferences)
├── UserBooks (user-book junction)
└── ReadingProgress (position tracking)
Books (metadata, statistics)
├── Chapters (structured content)
│ └── Paragraphs (tokenized text)
└── TTSCache (audio cache)Why SQLite:
- Zero configuration - just a file
- No separate database server to manage
- Simple backups (copy one file)
- Perfect for self-hosted use case
- Handles concurrent reads well
Indexes:
- Primary keys on all tables
- Foreign key indexes for relationships
- Composite indexes for common queries
Purpose: High-speed caching and session storage
Usage:
- Session data
- Frequently accessed book metadata
- User preferences cache
- Rate limiting counters
- Temporary TTS job state
TTL Strategy:
- Sessions: 7 days
- Metadata: 1 hour
- Preferences: 24 hours
Purpose: Text-to-speech generation
Technology:
- Python 3.11
- Flask (HTTP server)
- Kokoro ONNX model
- ONNX Runtime
API:
POST /synthesize- Generate audioGET /voices- List voicesGET /health- Health check
Performance:
- CPU: ~1-2x realtime
- GPU: ~5-10x realtime
- Model cache: ~500MB-2GB
Purpose: TLS termination and routing
Features:
- Automatic HTTPS
- HTTP/2 support
- Load balancing (future)
- Rate limiting (future)
Routes:
/api/*→ Chapter Server/*→ Web Client
User uploads EPUB
↓
[Web Client] POST /api/books (multipart)
↓
[API Server] Receives file
↓
[EPUB Parser] Extracts metadata, chapters
↓
[Tokenizer] Splits into words/punctuation
↓
[Database] Stores structured data
↓
[Storage] Saves EPUB file and cover
↓
[Response] Returns book metadata
↓
[Web Client] Displays book in library
User opens book
↓
[Web Client] GET /api/books/:id/chapter/0
↓
[API Server] Fetches chapter + paragraphs
↓
[Database] Returns tokenized content
↓
[Response] JSON with chapter data
↓
[Web Client] Renders readable text
↓
User scrolls (position tracked)
↓
[Web Client] PUT /api/progress/:bookId
↓
[API Server] Updates position
↓
[Database] Saves multi-level position
User switches to audiobook mode
↓
[Web Client] Requests audio for current position
↓
[API Server] GET /api/tts/audio/:chunkId
↓
[Cache Check] Hash = f(text + voice + settings)
↓
Cache Hit?
├─ Yes → [Storage] Read cached WAV file
│ ↓
│ [Response] Stream audio
│ ↓
│ [Web Client] Play audio
│
└─ No → [API Server] POST to Kokoro service
↓
[Kokoro] Generate speech via ONNX
↓
[Response] WAV audio data
↓
[Storage] Cache WAV file
↓
[Database] Store cache metadata
↓
[Response] Stream audio
↓
[Web Client] Play audio
1. User registers/logs in
2. Server validates credentials
3. Server generates JWT (7-day expiration)
4. Client stores token (httpOnly cookie or localStorage)
5. Client includes token in Authorization header
6. Server validates token on each request
7. Token refresh before expiration
- User-Book Access: Users can only access their own books
- Admin Routes: Future admin panel (not implemented)
- Rate Limiting: Future implementation
- Passwords: bcrypt hashed (10 rounds)
- JWT Secrets: Environment variable (must be changed in production)
- File Upload: Validated file type, size limit
- SQL Injection: Prevented by Prisma ORM
/app/storage/
├── books/
│ ├── {hash}.epub # Original EPUB files
│ └── {hash}-cover.jpg # Cover images
└── audio/
├── {chunkHash}.wav # Cached TTS audio
└── {chunkHash}.wav
- Books: SHA-256 hash of EPUB content
- Audio: Hash of (text + voice + settings)
- Shared books don't duplicate storage
- Max Size: Configurable (default 10GB)
- Eviction: LRU (least recently used)
- Cleanup: Background job (future)
- Users: Hundreds (single server)
- Books: Thousands (limited by disk)
- Concurrent TTS: 1-5 requests (CPU/GPU dependent)
-
Horizontal Scaling:
- Multiple API servers behind load balancer
- Shared PostgreSQL and Redis
- Distributed file storage (S3, MinIO)
-
TTS Scaling:
- Multiple Kokoro instances
- Queue-based job processing
- Dedicated TTS workers
-
Database Scaling:
- Read replicas for queries
- Connection pooling
- Partitioning by user/book
-
Caching Improvements:
- CDN for static assets
- Redis cluster
- Edge caching
services:
redis (cache)
kokoro (TTS)
server (API + SQLite)
web (UI)
caddy (proxy)- Separate Databases: Dedicated PostgreSQL/Redis servers
- TTS Workers: Multiple Kokoro instances
- Load Balancing: Multiple API/web servers
- Monitoring: Prometheus + Grafana
- Backups: Automated PostgreSQL backups
/health- API server/api/tts/health- TTS service- Database connection
- Redis connection
- Disk space
- Request latency (p50, p95, p99)
- TTS generation time
- Cache hit rate
- Active users
- Books uploaded
- Storage usage
- Error rates
- 2-3x faster
- Built-in TypeScript support
- Modern plugin system
- Better async/await handling
- Better TypeScript integration
- Auto-generated types
- Migration system
- Cleaner query API
- Self-hosted (privacy, cost)
- No API dependencies
- Frontier quality
- See WHY_KOKORO.md
- Simpler configuration
- Faster builds
- Better caching
- Active development
- Larger ecosystem
- Better documentation
- Server components
- Vercel optimization (optional)
- WebSockets: Real-time progress sync across devices
- Message Queue: Background job processing (RabbitMQ, Redis Queue)
- CDN Integration: Static asset delivery
- Microservices: Separate TTS, EPUB processing services
- GraphQL: Flexible API queries
- Edge Functions: Serverless API endpoints
- Service Mesh: Inter-service communication (Kubernetes)
- Hot reloading (tsx, next dev)
- Debug logging
- Source maps
- Local databases
- HTTP (no TLS)
- Compiled builds
- Minimal logging
- Minified code
- Remote databases
- HTTPS (Caddy)
- Health checks
- Graceful shutdown
- Database: Daily PostgreSQL dumps
- EPUB Files: Sync to S3/backup storage
- Audio Cache: Regeneratable, don't backup
- Configuration: Version controlled
- Restore PostgreSQL from backup
- Restore EPUB files from backup
- Restart services
- Regenerate audio cache as needed
- RTO: 1 hour (time to restore)
- RPO: 24 hours (daily backups)
- Improve with continuous replication
For more information: