Back to Portfolio
ReadLib Application Interface Preview
Web • Local-First • Privacy React 19 • IndexedDB

ReadLib — Offline Book Manager

A private, local-first library and personal reading companion with an embedded PDF document reader, persistent offline IndexedDB storage, and zero server fees.

Role: Frontend & Offline Systems Architect
Privacy: 100% On-Device • Zero Tracking
$0
Server Costs

100% local-first — zero backend, zero hosting costs.

∞
Storage Limit

IndexedDB stores multi-GB PDFs with zero browser throttling.

64KB
Chunk Buffer

Range-request streaming keeps 300MB textbook RAM usage <5MB.

100%
Offline Ready

Survives page reloads and browser restarts without internet.

Technologies & Libraries

React 19 TypeScript Vite 8 IndexedDB pdf.js (Mozilla) React Router v7 Glassmorphism CSS

The Problem & Core Idea

Most contemporary book management tools force users into cloud accounts, subscriptions, and proprietary file locking. If your internet drops or the service shuts down, your library is inaccessible.

ReadLib was built on the Local-First software principle: your books, PDFs, and reading progress stay permanently on your machine inside IndexedDB. The app loads instantly even with zero connectivity.

PDF Import Pipeline

Every imported PDF flows through four async stages before appearing in your library:

Step 1
File Drop
User drags PDF — FileReader reads raw ArrayBuffer
Step 2
Cover Render
pdf.js renders page 1 to hidden canvas → WebP thumbnail
Step 3
IndexedDB Write
Binary blob + metadata stored as separate transactional entries
Step 4
Shelf Update
React state updates, card appears in "To Read" shelf instantly

Key System Capabilities

Visual Shelf Organization

Books organized into three distinct reading statuses: To Read, Reading, and Completed. Cards display custom auto-generated cover thumbnails, page counts, and percentage progress.

Embedded Canvas PDF Reader

A native-feeling document viewer built with pdf.js rendering directly to an HTML5 canvas. Supports keyboard page-turning, full-screen mode, zoom controls, and continuous scroll.

Automatic Position Sync

Every page turn triggers an async write to IndexedDB recording the exact page number and percentage completed — pick up immediately where you left off across sessions.

Auto-Generated Cover Thumbnails

Upon drag-and-drop import, pdf.js silently renders page 1 to an offscreen canvas and exports a high-density WebP thumbnail stored alongside the book record.

Instant In-Memory Search & Filter

Search by title, author, or tag with sub-5ms query response time across large libraries by running lookups entirely in-memory over IndexedDB indices.

Backup & Migration Engine

One-click export produces a portable JSON backup of metadata, reading history, and bookmarks — importable into any other browser instance with zero friction.

Technical Implementation: IndexedDB Storage Adapter

Separating heavy binary PDF blobs from lightweight book metadata keeps the UI nimble. Shelf lists and search queries only read metadata; the full binary blob is fetched on-demand only when the reader opens:

db.ts
// IndexedDB Storage Layer — readlib-db
interface BookMeta {
  id: string;
  title: string;
  author: string;
  totalPages: number;
  currentPage: number;
  status: 'to-read' | 'reading' | 'completed';
  coverBlob?: Blob;      // WebP ~30KB
  addedAt: number;
  lastReadAt: number;
}

// Heavy binary stored separately
interface BookContent {
  id: string;            // Foreign key to BookMeta.id
  pdfBlob: Blob;         // Full PDF binary (up to 500MB+)
}

Engineering Challenges & Solutions

Challenge 1: Large PDF Memory Pressure in Browser

Loading multi-hundred-megabyte textbooks into standard JavaScript memory crashes mobile browser tabs. Solved by streaming PDF byte arrays in chunks using pdf.js Range requests rather than loading entire blobs into RAM.

Challenge 2: Cover Thumbnail Extraction Blocks Main Thread

Rendering page 1 of large PDFs on the main thread caused visible UI freezes. Mitigated by deferring rasterization to after the modal animation completes, keeping interactions fluid.

Design Decisions & Trade-offs

Zero Server Dependency

Why: Absolute privacy — no data ever leaves the device. Trade-off: Multi-device sync requires manual JSON export/import with no real-time collaboration.

pdf.js Over Custom Renderer

Why: Battle-tested, handles thousands of PDF edge cases. Trade-off: Adds ~2MB to bundle; depends on Mozilla CDN for font maps.

Automatic Cover Thumbnails

Why: Users never need to hunt for cover images — every PDF renders its own. Trade-off: First import of a large PDF is slower as page 1 rasterizes.

What I'd Do Differently

I'd move the thumbnail extraction pipeline to a Web Worker to eliminate main-thread freeze on large PDF imports entirely. I'd also explore the Background Sync API for opt-in encrypted cloud backup — letting users sync to Google Drive or Dropbox without breaking the local-first privacy promise.

Lessons Learned & Outcomes

The local-first architecture taught me that offline capability is not an afterthought but a design constraint that shapes every decision. Streaming large PDFs safely required rethinking how browsers handle memory, and the custom thumbnail pipeline proved that even complex media processing can run client-side when done incrementally.

ReadLib demonstrates that privacy-respecting, fully offline applications are not only possible but can deliver a polished, performant reading experience without any server dependency.

Previous Project CineVault Next Case Study UniLib