A personal RSVP (Rapid Serial Visual Presentation) speed reading web app using the ORP (Optimal Recognition Point) focal letter technique. Read at speeds from 150-1200 WPM with a highlighted focal letter for optimal word recognition.
- RSVP Display: One word at a time with customizable speed (150-1200 WPM)
- ORP Focal Letter: Highlighted letter at the optimal recognition point for faster processing
- Launch Mode: 3-2-1 countdown followed by gradual speed ramp from 150 WPM to your target
- Smart Pausing: Automatic micro-pauses at punctuation for natural reading flow
- Progress Tracking: Resume reading from where you left off
- Text Paste: Direct text input
- PDF Upload: Drag-and-drop PDF support
- URL Fetch: Import articles from any website
- Premium Services: Authenticated access to Substack, Financial Times, The Spectator, The Economist, NY Times, and Wall Street Journal
- Offline Reading List: Save articles to IndexedDB for offline access
- PWA Installable: Add to home screen on mobile devices
- Share Target: Share articles directly from your browser to Speed Reader
- Cross-Device Sync: QR code to transfer settings and credentials to mobile
- Bookmarklet: One-click article saving from any website
- Chrome Extension: Capture HttpOnly cookies for premium services
- Keyboard Shortcuts: Space (play/pause), Arrow keys (speed/skip), R (restart)
- Touch Gestures: Tap to play/pause, swipe to skip
- Dark/Light/System Theme: Automatic or manual theme switching
- Focal Color Picker: Customize the highlight color
- Mobile Responsive: Works on any device
- Node.js 18+
- npm or yarn
# Clone the repository
git clone https://github.com/Burstall/speed-reader.git
cd speed-reader
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env.local
# Edit .env.local and set APP_PASSWORD
# Run development server
npm run devCreate a .env.local file with:
APP_PASSWORD=your-secure-passwordThe app is designed for Vercel deployment:
# Install Vercel CLI (optional)
npm i -g vercel
# Deploy
vercelOr connect your GitHub repository to Vercel for automatic deployments.
- Login with your configured password
- Add content via one of three methods:
- Paste text directly
- Upload a PDF file
- Enter an article URL
- Adjust speed using the slider or arrow keys
- Press Space or click Play to start reading
- Use Launch Mode for a countdown and gradual speed ramp-up
| Key | Action |
|---|---|
| Space | Play / Pause |
| Up Arrow | Increase speed |
| Down Arrow | Decrease speed |
| Left Arrow | Skip back 10 words |
| Right Arrow | Skip forward 10 words |
| R | Restart from beginning |
| Gesture | Action |
|---|---|
| Tap | Play / Pause |
| Swipe Left | Skip forward |
| Swipe Right | Skip back |
- Open Speed Reader and expand the "Quick Save" section in the sidebar
- Drag the "Save to Speed Reader" button to your bookmarks bar
- When on any article you want to save, click the bookmarklet
- The article will be fetched, saved to your Reading List, and available offline
- Install the PWA: Visit Speed Reader in your mobile browser, tap the share/menu button, select "Add to Home Screen"
- When reading an article in your browser, tap Share
- Select Speed Reader from the share menu
- The article will be saved to your Reading List
To read paywalled articles from services like Substack, FT, or The Spectator, you need to provide your session cookies. There are three methods:
The extension can capture HttpOnly cookies that JavaScript bookmarklets cannot access.
- Install the extension (see Browser Extension Setup below)
- Go to the premium service site and log in to your account
- Click the Speed Reader extension icon in your toolbar
- Click "Capture Cookies"
- Click "Open Speed Reader" - cookies are automatically imported
If you can't use the extension:
- Go to the premium service site and log in
- Open DevTools (
F12) → Application tab → Cookies - Find the session cookie (e.g.,
substack.sidfor Substack) - Copy the Value column
- In Speed Reader, expand Premium Access → click Connect → paste the value
The bookmarklet only captures non-HttpOnly cookies. Most premium services use HttpOnly cookies for sessions, so this method may not work:
- Expand "Premium Access" in the sidebar
- Click "Connect" next to the service
- Drag the bookmarklet to your bookmarks bar
- Click it while logged in to the service
Once connected, articles from that service will automatically use your credentials.
Transfer your settings and premium credentials from desktop to mobile:
- On desktop, expand "Sync to Mobile" in the sidebar
- Scan the QR code with your phone camera
- On mobile, tap "Import All Settings"
This syncs your WPM, theme, focal color, and all premium service cookies.
- Framework: Next.js 14+ (App Router)
- Language: TypeScript
- Styling: Tailwind CSS
- State Management: Zustand with persist middleware
- Offline Storage: IndexedDB
- PDF Parsing: pdf-parse
- HTML Parsing: Cheerio
- Deployment: Vercel
├── extension/ # Chrome extension for cookie capture
│ ├── manifest.json # Extension manifest (v3)
│ ├── popup.html # Extension popup UI
│ ├── popup.js # Cookie capture logic
│ ├── generate-icons.html # Icon generator utility
│ └── icons/ # Extension icons (generated)
│
└── src/
├── app/ # Next.js App Router pages
│ ├── api/ # API routes
│ │ ├── auth/ # Authentication
│ │ ├── fetch/article/ # Article fetching
│ │ ├── parse/pdf/ # PDF parsing
│ │ └── save/ # Article saving
│ ├── auth/receive/ # Cookie capture handler
│ ├── login/ # Login page
│ ├── share/ # PWA share target
│ └── sync/ # Cross-device sync import
├── components/
│ ├── reader/ # RSVP reader components
│ └── sidebar/ # Sidebar components
├── hooks/ # Custom React hooks
├── lib/ # Utility libraries
│ ├── auth.ts # Authentication helpers
│ ├── offlineStore.ts # IndexedDB operations
│ ├── orp.ts # ORP algorithm
│ └── sync.ts # Cross-device sync encoding
├── store/ # Zustand stores
│ ├── authStore.ts # Premium service credentials
│ ├── historyStore.ts # Reading history
│ └── readerStore.ts # Reader state
└── middleware.ts # Auth middleware
The Chrome extension provides the most reliable way to capture premium service cookies, including HttpOnly cookies that bookmarklets cannot access.
-
Generate the icons:
# Open the icon generator in Chrome # File location: extension/generate-icons.html
- Open
extension/generate-icons.htmlin Chrome - Right-click each icon canvas → "Save image as..."
- Save to
extension/icons/asicon16.png,icon48.png,icon128.png
- Open
-
Load the extension:
- Open Chrome and navigate to
chrome://extensions/ - Enable "Developer mode" (toggle in top-right corner)
- Click "Load unpacked"
- Select the
extensionfolder from this repository
- Open Chrome and navigate to
-
Configure your app URL:
- Click the Speed Reader extension icon in your toolbar
- Enter your deployed Speed Reader URL (e.g.,
https://your-app.vercel.app) - The URL is saved automatically for future use
The extension uses Chrome's cookies API to read all cookies for the current domain, including HttpOnly cookies that are inaccessible to JavaScript running on the page. When you click "Capture Cookies":
- Extension reads all cookies for the current site
- Formats them as a cookie header string
- Opens your Speed Reader app with cookies in the URL
- The
/auth/receivepage saves them to your local storage
| Service | Domain | Session Cookie |
|---|---|---|
| Substack | *.substack.com | substack.sid |
| Financial Times | ft.com | FTSession |
| The Spectator | spectator.co.uk | spectator_session |
| The Economist | economist.com | ec_session |
| NY Times | nytimes.com | NYT-S |
| Wall Street Journal | wsj.com | wsjregion |
The extension also supports custom domains - if you're on a site not in this list, it will still capture cookies and let you use them.
- Cookies are sent directly to YOUR Speed Reader instance via URL parameters
- No data is sent to any third-party servers
- Cookies are stored only in your browser's localStorage
- The extension only activates when you click it (no background tracking)
# Run development server
npm run dev
# Type check
npm run lint
# Build for production
npm run build
# Start production server
npm start- Password authentication with secure session tokens
- Credentials stored locally in browser (never sent to external servers)
- Premium service cookies stored in localStorage per-device
- All sensitive routes protected by middleware
MIT
- Inspired by Selah and other RSVP readers
- ORP (Optimal Recognition Point) research for focal letter positioning