The Story of FocusFlow

The Inspiration: Drowning in a Sea of Words

It all started with a feeling I think we all know too well: digital overload. My browser was a graveyard of good intentions, filled with dozens of tabs of articles I swore I’d read. My work required me to get through reports and documentation, and my personal reading list was only getting longer. I was constantly reading, but I felt like I was treading water, never truly getting ahead. My focus was fractured, and I'd often find myself rereading the same paragraph multiple times.

I became fascinated with the concept of "flow state"—that magical zone of deep, effortless concentration. I wondered, "What if I could create a tool that not only helps me read faster, but also helps me get into that state of flow?" The idea wasn't just about speed, but about the quality of focus. This was the spark that ignited FocusFlow.

The Build: From a Simple Script to a Flowing Experience

I decided to build this on the web, making it universally accessible. I chose a simple, lightweight stack: HTML, Tailwind CSS, and vanilla JavaScript. I wanted to prove that a powerful user experience didn't require a heavy framework.

Phase 1: The Core Mechanic

My first version was basic. It took a block of text, split it into individual words wrapped in <span> tags, and used a setInterval loop to highlight them one by one. It worked, but it felt clunky and robotic. The highlight jumped jarringly from one word to the next. It was fast, but it wasn't "flow."

Phase 2: Finding the Flow

The real breakthrough came when I asked myself how I could make the highlight move. Instead of highlighting the words themselves, I created a separate <div> to act as a "highlight bar." I made it an absolutely positioned element and, within my JavaScript loop, I calculated the exact position and size of the next word.

Then, instead of just appearing there, I used a simple CSS transition on the highlight bar's top, left, width, and height properties. The result was transformative. The highlight now glided smoothly from one word to the next, elegantly crossing line breaks and creating a visual momentum that was incredibly compelling to follow. This was the "flow" I had been searching for.

Phase 3: Making it a Real Tool

With the core experience feeling right, I built the application around it. I added the features a real user would need:

  • A File Dropzone: I implemented a drag-and-drop area using the FileReader API, allowing users to load their own .txt files.
  • A "Try Sample" Option: For first-time users, I added a button that instantly loads a pre-written text to demonstrate the app's functionality.
  • User Controls: The WPM (Words Per Minute) slider and Start/Pause/Reset buttons gave users full control over their reading experience.

Challenges Faced

The Positioning Puzzle

The biggest technical hurdle was perfecting the smooth-gliding highlight. Getting an absolutely positioned <div> to align perfectly with inline text across different screen sizes was tricky. It required a deep dive into DOM element properties like offsetTop, offsetLeft, and offsetWidth, and ensuring the parent container had position: relative to create the correct coordinate system. The z-index also proved crucial to ensure the text always appeared on top of the highlight bar.

Handling Dynamic Content

When a user uploads a new file, the entire text content and its corresponding HTML structure need to be rebuilt from scratch. I had to write clean, reusable functions like loadTextIntoReader() and resetReaderState() to manage this process, ensuring that old event listeners were cleared and the application state was properly reset before loading in new content.

What I Learned

User Experience is Iterative

The journey from the jarring word-by-word highlight to the smooth-gliding bar taught me that the first solution is rarely the best. That single iterative change, driven purely by the "feel" of the application, made all the difference.

The Power of Vanilla JavaScript

Building this without a framework was incredibly rewarding. It forced me to engage directly with the DOM and understand the core web APIs that frameworks often abstract away. It was a great reminder that for a focused, single-purpose application, vanilla JS is not only sufficient but often faster and more efficient.

Details Define the Design

Small details, like adding a "dragover" state to the dropzone or ensuring the WPM slider updated the speed in real-time, were vital in elevating the project from a simple script to a polished, intuitive tool.


FocusFlow started as a solution to my own problem, but it grew into a passion project and a deep learning experience. It's a testament to the idea that with a clear vision and an iterative approach, you can create tools that not only solve a problem but do so with a touch of elegance and flow.

Built With

  • css
  • eslint
  • node.js
  • postcss
  • tailwind
  • typescript
  • useeffect`
  • useref`-for-local-state-**component-architecture**-?-modular
Share this project:

Updates