How we architected, optimized, and scaled the Times of India digital ePaper — from a blank React project to India's most-read digital newspaper.
When I joined Harns Technologies in 2021, one of my first large-scale assignments was the Times of India ePaper platform — a product that would eventually serve 10M+ digital daily active users and sit inside an ecosystem with 60M+ monthly active app users. This is the story of the decisions we made, the performance bottlenecks we hit, and how we resolved them.
Starting From Scratch
We started with a blank React project. The requirement was clear: build a digital replica of the print newspaper that loads fast, works across devices, integrates ads revenue, and can be reused across multiple regional ePaper properties. That last point turned out to be the most architecturally important decision we made.
Instead of building a monolithic app, we designed a shared component library from day one — pages, navigation, search, text-to-speech, and ad slots were all isolated into composable units. This allowed us to launch three additional regional ePapers on top of the same architecture, each with different branding but zero duplicated logic.
SSR + Context API for State
The platform is server-side rendered. SSR was non-negotiable for two reasons: SEO (news content needs to be crawlable) and first-contentful-paint (users landing on the ePaper via Google search should see content immediately, not a spinner).
For state management we went with React Context API rather than Redux — the app state is mostly read-heavy (current edition, selected page, zoom level) with infrequent mutations. Context avoided Redux boilerplate without sacrificing the ability to share state deeply across the component tree.
The Archive Problem: 20 Seconds → Under 1 Second
The archive view — a grid of every past edition going back years — was our biggest performance crisis. The initial implementation loaded and rendered every edition card into the DOM simultaneously. On a slow connection or low-end device, this caused a 20+ second render block that made the page completely unusable.
Building something interesting?
I'm open to new projects, collaborations, and conversations.
The fix was list virtualization. We only rendered the cards currently within (or near) the viewport, and destroyed cards that scrolled far out of view. The result: DOM nodes dropped from several thousand to under a hundred at any time. Render time collapsed to under one second — a 20× improvement that unblocked the archive product launch entirely.
- Only visible rows rendered — DOM size stayed constant regardless of total data
- Scroll position maintained perfectly via item height estimation
- Lazy hydration for individual cards below the fold
- Image lazy-loading combined with virtual scroll for bandwidth savings
Text-to-Speech Accessibility
One feature I'm particularly proud of is the text-to-speech reader, built using the Web Speech API. Readers could highlight any article and have it read aloud — useful for accessibility and for commuters who want to consume news hands-free. The implementation required careful handling of browser compatibility, playback controls, and pitch/rate settings, all without any third-party TTS library.
Ads, Analytics, and Revenue
Integrating Google AdSense and GTM into an SSR React app without degrading Core Web Vitals is genuinely tricky. Ad scripts are notorious for layout shift (CLS) and blocking the main thread (TBT). We deferred all ad initialization until after first contentful paint, used fixed-size ad slot placeholders to prevent layout shift, and loaded GTM asynchronously with a nonce-based CSP strategy.
Key Takeaways
- Design for reuse early — a shared component library across 4 ePapers saved months of future work
- List virtualization is essential for any data-heavy scrollable surface
- SSR + careful hydration strategy is the right default for content-heavy news products
- Defer third-party scripts aggressively to protect Core Web Vitals
- Web Speech API can deliver real accessibility value without external dependencies