First release
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Build output
|
||||
dist/
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.claude
|
||||
|
||||
# Editor directories and files
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Local config
|
||||
*.local
|
||||
@@ -0,0 +1,24 @@
|
||||
## Commits and code style
|
||||
|
||||
- 2 space indents
|
||||
- Always commit build and asset files
|
||||
- One logical change per commit
|
||||
- Keep commit messages concise (one line), use sentence case
|
||||
- Update CHANGELOG.md after each change
|
||||
- Use present tense in commits and CHANGELOG.md
|
||||
- Use sentence case for headings (not Title Case)
|
||||
- Never use bold text as headings, use proper heading levels instead
|
||||
- Always add an empty line after headings
|
||||
- No formatting in CHANGELOG.md except `inline code` and when absolute necessary
|
||||
- Use `*` as bullets in CHANGELOG.md
|
||||
- Never use Claude watermark in commits (FORBIDDEN: "Co-Authored-By")
|
||||
- No emojis in commits or code
|
||||
- Keep CHANGELOG.md date up to date when adding entries
|
||||
|
||||
## Claude Code workflow
|
||||
|
||||
- Always add tasks to the Claude Code to-do list and keep it up to date. Show todo list to user.
|
||||
- Review your to-do list and prioritize before starting.
|
||||
- If new tasks come in, don't jump to them right away—add them to the list in order of urgency and finish your current work first. Use FIFO (First in First out) in order.
|
||||
- Do not ever guess features, always proof them via looking up official docs, GitHub code, issues, if possible.
|
||||
- When looking things up, do not use years in search terms like 2024 or 2025.
|
||||
@@ -0,0 +1,89 @@
|
||||
# Speed reader
|
||||
|
||||
A web-based speed reading tool using Rapid Serial Visual Presentation (RSVP) with Optimal Recognition Point (ORP) alignment.
|
||||
|
||||
## What is RSVP?
|
||||
|
||||
RSVP (Rapid Serial Visual Presentation) is a reading technique that displays text one word at a time at a fixed focal point. This eliminates saccades (eye movements) that normally slow down reading, allowing for significantly faster reading speeds.
|
||||
|
||||
## The science behind it
|
||||
|
||||
### Optimal Recognition Point (ORP)
|
||||
|
||||
When reading normally, your eyes don't land at the center of words. Research shows that fixations tend to occur slightly left of center, at what's called the Optimal Viewing Position (OVP) or Optimal Recognition Point (ORP). This position allows for fastest word recognition.
|
||||
|
||||
The ORP position follows the Spritz algorithm:
|
||||
|
||||
- 1 character: 1st letter
|
||||
- 2-5 characters: 2nd letter
|
||||
- 6-9 characters: 3rd letter
|
||||
- 10-13 characters: 4th letter
|
||||
- 14+ characters: 5th letter
|
||||
|
||||
### Fixed focal point
|
||||
|
||||
Traditional RSVP displays center each word, requiring small eye adjustments. This implementation aligns each word's ORP at the exact same screen position, so the highlighted letter never moves. Your eyes stay completely still while words flow around the focal point.
|
||||
|
||||
### Variable timing
|
||||
|
||||
The display time for each word is adjusted based on:
|
||||
|
||||
- Word length (longer words get more time)
|
||||
- Punctuation (sentence-ending punctuation triggers a longer pause)
|
||||
|
||||
This mimics natural reading rhythm where comprehension requires variable processing time.
|
||||
|
||||
### Research findings
|
||||
|
||||
Studies have shown that RSVP reading can achieve speeds of 500+ words per minute, though comprehension tends to decrease above 350-400 WPM for complex texts. The technique works best for:
|
||||
|
||||
- Light reading and familiar content
|
||||
- Skimming and preview reading
|
||||
- Building reading speed gradually
|
||||
|
||||
Note: Extended RSVP reading can cause visual fatigue. Take breaks.
|
||||
|
||||
## Features
|
||||
|
||||
- Adjustable reading speed (50-1500 WPM)
|
||||
- ORP highlighting with fixed focal point (Spritz algorithm)
|
||||
- Variable word timing based on length and punctuation
|
||||
- EPUB and TXT file support
|
||||
- Progress tracking with position memory per text
|
||||
- Keyboard shortcuts
|
||||
- Adjustable side opacity
|
||||
- Dark theme optimized for reading
|
||||
- Settings persisted to localStorage
|
||||
|
||||
## Running locally
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Then open http://localhost:5173
|
||||
|
||||
## Building for production
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
Output will be in the `dist` folder.
|
||||
|
||||
## Inspiration and similar projects
|
||||
|
||||
- [Original RSVP Speed Reader](https://snowfluke.github.io/rsvp-speed-reader/)
|
||||
- [Spritz](https://spritz.com/) - The commercial product that popularized ORP-based RSVP
|
||||
- [OpenSpritz](https://github.com/Miserlou/OpenSpritz) - Open source Spritz implementation
|
||||
- [speedread](https://github.com/pasky/speedread) - Terminal-based Spritz-alike in Perl
|
||||
- [rsvp-reading](https://github.com/thomaskolmans/rsvp-reading) - Svelte-based RSVP reader with PDF/EPUB support
|
||||
- [LetoReader](https://github.com/Axym-Labs/LetoReader) - Self-hostable speed reader with chunking and highlighting
|
||||
- [tspreed](https://github.com/n-ivkovic/tspreed) - Terminal RSVP reader in POSIX shell
|
||||
|
||||
## Scientific references
|
||||
|
||||
- Masson, M. E. J. (1983). Conceptual processing of text during skimming and rapid sequential reading. _Memory & Cognition_, 11(3), 262-274.
|
||||
- Rayner, K., Schotter, E. R., Masson, M. E., Potter, M. C., & Treiman, R. (2016). So much to read, so little time: How do we read, and can speed reading help? _Psychological Science in the Public Interest_, 17(1), 4-34.
|
||||
- Benedetto, S., Carbone, A., Pedrotti, M., Le Fevre, K., Bey, L. A. Y., & Baccino, T. (2015). Rapid serial visual presentation in reading: The case of Spritz. _Computers in Human Behavior_, 45, 352-358.
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>RSVP Speed Reader</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
Generated
+1883
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "rsvp-speed-reader",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"jszip": "^3.10.1",
|
||||
"lucide-react": "^0.460.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"vite": "^6.0.0"
|
||||
}
|
||||
}
|
||||
+1203
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Inter", sans-serif;
|
||||
background-color: #0a0a0a;
|
||||
color: #ffffff;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.mono {
|
||||
font-family: "JetBrains Mono", monospace;
|
||||
}
|
||||
|
||||
#root {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
textarea:focus,
|
||||
button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
button:focus,
|
||||
button:focus-visible,
|
||||
button:active {
|
||||
outline: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.icon-btn:hover {
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
.wpm-control:hover .wpm-value {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.wpm-btn:hover {
|
||||
color: #ccc !important;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App.jsx";
|
||||
import "./index.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
);
|
||||
@@ -0,0 +1,6 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
})
|
||||
Reference in New Issue
Block a user