Speed reading has become essential for developers and power users who consume large amounts of technical documentation, research papers, and online content. Building an AI speed reader Chrome extension allows you to process text intelligently, highlight key concepts, and present content in optimized formats. This guide covers the architecture, implementation, and practical considerations for creating a production-ready speed reading extension.
How Speed Reader Extensions Work
Speed reader Chrome extensions operate on a simple principle: instead of your eyes scanning across lines of text, words appear one at a time in a fixed position on your screen. This eliminates the time spent on eye movements and allows your brain to process information more efficiently.
The core mechanism involves three main components:
- Text Extraction: Capturing readable text from web pages, PDFs, or other sources
- Word Parsing: Splitting text into individual words and calculating display durations
- Presentation Engine: Displaying words at controlled speeds using RSVP or similar methods
Modern implementations often include features like pause controls, speed adjustment, progress tracking, and chunking options that group words for easier comprehension.
Core Architecture
A Chrome extension consists of three main components: the manifest file, background scripts, and content scripts. For an AI speed reader, you’ll need to handle text extraction, AI processing, and display optimization.
// manifest.json
{
"manifest_version": 3,
"name": "AI Speed Reader",
"version": "1.0.0",
"permissions": ["activeTab", "scripting"],
"host_permissions": ["<all_urls>"],
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content.js"]
}],
"background": {
"service_worker": "background.js"
}
}
The manifest declares the permissions your extension needs. The activeTab permission lets you access the current page when the user invokes the extension, while scripting enables programmatic injection of JavaScript.
Text Extraction Strategies
Extracting readable text from web pages requires handling various HTML structures. The Document Object Model (DOM) provides methods to traverse and extract content effectively.
// content.js - Text extraction utility
function extractReadableText() {
// Remove unwanted elements
const unwantedSelectors = [
'script', 'style', 'nav', 'header', 'footer',
'aside', '.advertisement', '.sidebar', '[role="navigation"]'
];
unwantedSelectors.forEach(selector => {
document.querySelectorAll(selector).forEach(el => el.remove());
});
// Extract main content using common patterns
const contentSelectors = [
'article', 'main', '[role="main"]', '.post-content',
'.article-content', '.entry-content', '#content'
];
for (const selector of contentSelectors) {
const element = document.querySelector(selector);
if (element && element.textContent.length > 500) {
return element.textContent;
}
}
// Fallback: return body text
return document.body.innerText;
}
This extraction strategy removes navigation, ads, and decorative elements before retrieving the main content. Adjust the selectors based on the websites you target most frequently.
Chunking and Processing
Once you have the text, divide it into digestible chunks. For AI processing, each chunk should contain complete sentences to maintain context.
// Text chunking with sentence boundary detection
function chunkText(text, maxChunkSize = 500) {
const sentences = text.match(/[^.!?]+[.!?]+/g) || [text];
const chunks = [];
let currentChunk = '';
for (const sentence of sentences) {
if ((currentChunk + sentence).length > maxChunkSize && currentChunk.length > 0) {
chunks.push(currentChunk.trim());
currentChunk = '';
}
currentChunk += sentence;
}
if (currentChunk) {
chunks.push(currentChunk.trim());
}
return chunks;
}
This function uses sentence-ending punctuation as natural break points. The maxChunkSize parameter controls the length of each segment, which directly impacts processing speed and AI model context windows.
For multi-word chunking, displaying 2-3 words at once can improve comprehension for some readers:
function getChunks(words, chunkSize = 2) {
const chunks = [];
for (let i = 0; i < words.length; i += chunkSize) {
chunks.push(words.slice(i, i + chunkSize).join(' '));
}
return chunks;
}
Display Modes for Speed Reading
Speed readers typically offer multiple display modes. Three popular approaches include:
- RSVP (Rapid Serial Visual Presentation): Displays one word at a time at a fixed position
- Chunked display: Shows multiple words per frame at optimal reading positions
- Highlighter mode: Highlights key phrases while the user scrolls through the text
Here’s an implementation of a simple RSVP reader:
// RSVP Reader implementation
class RSVPReader {
constructor(containerElement) {
this.container = containerElement;
this.words = [];
this.currentIndex = 0;
this.wpm = 300;
}
loadText(text) {
this.words = text.split(/\s+/);
this.currentIndex = 0;
}
setSpeed(wpm) {
this.wpm = Math.max(60, Math.min(1000, wpm));
}
start() {
this.intervalId = setInterval(() => {
if (this.currentIndex >= this.words.length) {
this.stop();
return;
}
this.render(this.words[this.currentIndex]);
this.currentIndex++;
}, 60000 / this.wpm);
}
stop() {
clearInterval(this.intervalId);
}
render(word) {
const center = Math.floor(word.length / 2);
const pivotIndex = Math.max(0, center - 1);
const before = word.slice(0, pivotIndex);
const pivot = word[pivotIndex] || '';
const after = word.slice(pivotIndex + 1);
this.container.innerHTML = `
<span class="rsvp-before">${before}</span>
<span class="rsvp-pivot">${pivot}</span>
<span class="rsvp-after">${after}</span>
`;
}
}
The RSVP reader focuses on the “pivot letter” (typically the character just left of center), which the eye naturally fixates on during reading. This technique reduces eye movement and increases reading speed.
Progress Indicators
Visual feedback helps readers gauge remaining content and maintain focus:
function updateProgress(current, total) {
const percentage = (current / total) * 100;
document.getElementById('progress-bar').style.width = `${percentage}%`;
document.getElementById('progress-text').textContent =
`${current} / ${total} words`;
}
Integrating AI Summarization
For AI-powered features, you can integrate with language models to generate summaries or extract key points. Here’s a pattern for connecting to an API:
// AI summarization handler
async function summarizeChunk(chunk, apiKey) {
const response = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: 'claude-3-haiku-20240307',
max_tokens: 200,
messages: [{
role: 'user',
content: `Summarize this text in 3 bullet points:\n\n${chunk}`
}]
})
});
const data = await response.json();
return data.content[0].text;
}
This example uses Claude API, but you can adapt the pattern for other models. The summarization feature helps users quickly grasp the main points before committing to full reading.
Keyboard Controls for Power Users
Developers and power users expect keyboard-driven interfaces. Map common keys for reader control:
// Keyboard controls
document.addEventListener('keydown', (e) => {
switch(e.key) {
case ' ':
e.preventDefault();
reader.isPlaying ? reader.stop() : reader.start();
break;
case 'ArrowRight':
reader.stop();
reader.currentIndex = Math.min(
reader.words.length - 1,
reader.currentIndex + 10
);
break;
case 'ArrowLeft':
reader.stop();
reader.currentIndex = Math.max(0, reader.currentIndex - 10);
break;
case 'ArrowUp':
reader.setSpeed(reader.wpm + 50);
updateSpeedDisplay(reader.wpm);
break;
case 'ArrowDown':
reader.setSpeed(reader.wpm - 50);
updateSpeedDisplay(reader.wpm);
break;
case 'Escape':
reader.stop();
break;
}
});
Space toggles play/pause, arrow keys navigate by word or sentence, and speed adjustments happen with up/down arrows. This mimics media player conventions that power users are familiar with.
Performance Considerations
When building a speed reader, consider these performance aspects:
- Memory usage: Process text in chunks rather than loading entire articles into memory
- DOM manipulation: Minimize reflows by batching UI updates
- Network calls: Cache API responses and implement request debouncing
- Extension size: Lazy-load AI modules only when needed
- Pre-process words: Split text into arrays once rather than repeatedly
- Use requestAnimationFrame for smoother UI updates when combining with animations
- Implement debouncing for speed adjustment to prevent rapid restarts
- Cache extracted text in storage if users frequently revisit pages
For text processing on the client side, Web Workers prevent UI blocking during heavy computation:
// Offload processing to a Web Worker
const worker = new Worker('text-processor.js');
worker.postMessage({ text: rawText, options: chunkingOptions });
worker.onmessage = (e) => {
displayChunks(e.data.chunks);
};
Extension Popup Interface
The popup provides quick controls without requiring full-page takeover:
<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
<style>
body { width: 300px; padding: 16px; font-family: system-ui; }
.controls { display: flex; gap: 8px; margin: 12px 0; }
button { flex: 1; padding: 8px; cursor: pointer; }
.speed-control { display: flex; align-items: center; gap: 8px; }
input[type="range"] { flex: 1; }
</style>
</head>
<body>
<h3>AI Speed Reader</h3>
<div class="speed-control">
<span id="wpm-display">300 WPM</span>
<input type="range" id="speed" min="100" max="800" value="300">
</div>
<div class="controls">
<button id="start-btn">Start</button>
<button id="extract-btn">Extract</button>
</div>
<div id="status"></div>
<script src="popup.js"></script>
</body>
</html>
Syntax-Aware Tokenization for Code Content
Developers often read pages containing code snippets. A syntax-aware tokenizer can detect and handle code blocks differently from prose:
function tokenizeWithCode(text) {
const codeBlockRegex = /```[\s\S]*?```/g;
const parts = text.split(codeBlockRegex);
return text.match(codeBlockRegex) || [];
}
This allows your reader to slow down for technical terms or skip code blocks entirely, depending on user preference.
Alternative Focus Point: ORP at 30% Offset
While the center-pivot method works well, some implementations use the Optimal Recognition Point (ORP) positioned at roughly 30% from the start of a word, which better matches natural eye fixation:
function highlightORP(word) {
const orpIndex = Math.floor(word.length * 0.3);
return word.slice(0, orpIndex) +
'<strong>' + word[orpIndex] + '</strong>' +
word.slice(orpIndex + 1);
}
Selecting vs. Building
Several quality extensions exist for different use cases. When evaluating existing options, consider:
- Open source extensions that allow customization and inspection of the underlying algorithms
- Extensions that work offline for reading saved articles or documents
- Privacy-focused options that don’t send your reading data to external servers
Many developers build custom implementations tailored to specific workflows, such as reading documentation, processing research papers, or quickly scanning emails.
Testing Your Extension
Load your extension in Chrome by navigating to chrome://extensions/, enabling Developer mode, and selecting the extension directory. Test on various websites to ensure text extraction handles different page structures.
Use Chrome DevTools to debug content scripts and background service workers. The Console panel shows logs from both contexts when you select the appropriate frame.
Building an AI speed reader extension combines DOM manipulation, text processing, and optional AI integration. Start with the core reading functionality, then layer on advanced features based on user feedback and your specific use cases. Most users find they can comfortably read at 400-500 WPM after consistent practice, starting from 200-250 WPM and increasing gradually.
Related Reading
- Claude Code for Beginners: Complete Getting Started Guide
- Best Claude Skills for Developers in 2026
- Claude Skills Guides Hub
Built by theluckystrike — More at zovo.one