AI Book Reader: Deep Case Study
A privacy-first web app that turns personal documents and web articles into audiobooks using multiple AI TTS providers, built entirely client-side, with offline reading, audio caching and an immersive reader.
AI Book Reader is a privacy-first, browser-based application that converts PDFs, EPUBs and web articles into immersive audiobooks using multiple AI text-to-speech providers, without uploading a single file to a server.
Executive Summary#
Unlike typical audiobook tools, it:
- Works entirely client-side
- Supports multiple TTS engines (Browser, Gemini, OpenAI, ElevenLabs)
- Caches generated audio to minimize API costs
- Preserves reading progress and playback history
- Provides a real reader-like experience with chunk highlighting
- Supports both documents and live web articles
Built as an all-in-one AI narration platform.
Problem Statement#
Traditional audiobook solutions suffer from:
- Lack of support for personal documents
- Privacy concerns due to cloud uploads
- Expensive subscriptions
- Robotic voices
- No support for web articles
- No offline capability
- Poor reading UX
Solution#
Create a unified AI reading platform that:
- Reads personal files locally
- Supports premium AI voices when available
- Works offline using browser TTS
- Handles large documents via chunking
- Preserves structure and formatting
- Minimizes API usage via caching
- Tracks reading history
Key Features#
Multi-Source Input
- EPUB
- Web article links
- Testing mode sample text
Multi-Engine TTS Support
| Provider | Type | Use-case |
|---|---|---|
| Browser Native | Offline | Free fallback |
| Gemini TTS | Cloud | Balanced quality |
| OpenAI TTS | Cloud | Natural voices |
| ElevenLabs | Cloud | Premium narration |
Chunk-Based Reading Engine
Large content is split into manageable segments:
- Prevents API limits
- Enables auto-play sequencing
- Supports pause/resume
- Allows per-chunk caching
Audio Caching System
Generated audio is stored locally:
- Reduces API cost
- Improves responsiveness
- Enables replay without regeneration
Library and Playback History
Tracks:
- Uploaded items
- Last played timestamp
- Reader used
- Playback history
- Unique entries only
Reader UX Enhancements
- Translucent highlight for active chunk
- Paragraph preservation
- Adjustable voice settings
- Auto-play next chunk toggle
- Provider-specific controls
- Theme support
Privacy-First Design
- Files processed locally
- Encrypted API keys stored in local storage
- No backend storage
- Direct provider communication
System Architecture (High Level)#
The whole pipeline runs in the browser. Content flows from the user through processing and a provider-agnostic adapter layer, then into playback and a local cache.
User
↓
React Frontend (SPA)
↓
Content Processing Layer
↓
TTS Adapter Layer
↓
Provider APIs / Browser TTS
↓
Audio Playback Engine
↓
Local Cache + HistoryFrontend Architecture#
UI Layer (React + shadcn)
├─ Home / Library
├─ Reader View
├─ Settings
└─ Help
State Layer
├─ Global Settings Store
├─ Reader State
└─ Library State
Service Layer
├─ File Parser
├─ Link Scraper
├─ Chunk Generator
├─ TTS Adapter
└─ Cache ManagerReading Flow (Sequence)#
Upload File / Paste Link
↓
Text Extraction
↓
Chunk Generation
↓
User clicks Play
↓
Check Cache
├─ Found → Play immediately
└─ Not found → Call TTS API
↓
Save Audio Blob
↓
Play AudioTTS Provider Adapter Pattern#
Each provider implements a unified interface, so the rest of the app never knows which engine is talking. Adapters absorb provider-specific differences: request formats, voice parameters, authentication, rate limits, and streaming vs batch audio.
interface TTSAdapter {
generateSpeech(
text: string,
settings: VoiceSettings
): Promise<Blob>;
}
// Pick the best available engine, fall back gracefully
const engine = pickEngine(settings) ?? browserTTS;
const audio = await engine.generateSpeech(chunk, settings);Every provider implements the same generateSpeech(text, settings) contract, so the rest of the app never knows which engine is talking.
Caching Strategy#
Caching is based on both content and settings, so a voice or speed change correctly misses the cache instead of replaying stale audio.
Cache Key =
hash(
text chunk +
provider +
voice +
speed +
pitch +
emotion +
model
)Storage:
- IndexedDB for large blobs
- LocalStorage for metadata
Hashing every parameter that affects the waveform (not just the text) means a voice or speed change correctly misses the cache instead of replaying stale audio.
IndexedDB quotas vary by browser and device. Large libraries need an eviction policy, or the cache will silently fail to write on constrained mobile devices.
Web Article Processing Pipeline#
URL Input
↓
Fetch HTML
↓
Content Extraction
↓
Sanitization
↓
Structure Reconstruction
↓
Chunking
↓
ReaderHandles titles, paragraphs, lists and sections.
Data Persistence Model#
Stored locally.
Library Item
id;
title;
type; // PDF | EPUB | LINK
format;
chunks;
addedAt;
lastPlayed;
readerUsed;Playback History
itemId;
datetime;
reader;
settingsSnapshot;Performance Optimizations#
- Lazy chunk generation
- On-demand audio generation
- Audio caching
- Minimal re-renders
- Client-side processing
- No server latency
Trade-Offs Considered#
No Backend Architecture
Advantages
- Maximum privacy
- Lower infrastructure cost
- Simpler deployment
Disadvantages
- No cross-device sync
- Browser storage limits
Chunking Strategy
Necessary for long documents, API limits, streaming UX and fine-grained caching.
Security Considerations#
- API keys stored locally only
- No server transmission
- No tracking
- No telemetry
Future Improvements#
Potential roadmap:
- Cross-device sync (optional cloud)
- Voice cloning support
- Annotation and bookmarks
- Multi-language translation
- Podcast-style playback
- Mobile PWA mode
- Multiple voices in a story
- Document OCR support
Why This Project Stands Out#
This is not a simple CRUD application. It demonstrates:
- Applied AI integration
- System design thinking
- UX engineering
- Performance optimization
- Privacy-centric architecture
- Multi-provider abstraction
- Product-level decision making
Deployment Model#
Yet to be deployed, but here is an example:
Static Hosting (Vercel / Netlify / GitHub Pages)
↓
Runs entirely in browserNo backend required.