One product, two readers, and only one of them gets the defaults

Bookflow is a reading and listening app for students who need throughput and dyslexic readers who need access. I built it alone, and gave the defaults to one audience and the ceiling to the other.


role
Solo founder
product, design, engineering
timeline
2026, ongoing
live on Google Play
scope
~100 screen states
React Native · Expo · Supabase
status
Live
actively maintained · Android

I designed and built Bookflow alone. The hardest decision in it was which of its two users the defaults belong to.

Three Bookflow screens side by side on a phone: the reader with a word highlighted mid-sentence, listen mode with the audio player open, and an AI-generated chapter summary.
fig 1 · Upload a PDF or EPUB, or pick from two hundred public domain classics. Then read it, listen to it, or both at once.

Two people who cannot finish a book

Ama is a student with more assigned reading than hours, working on a phone rather than a laptop. She needs throughput, and she needs it cheap.

David has dyslexia. He can read, but decoding costs enough attention that comprehension suffers. Audio alone loses him the text. Text alone loses him the pace.

Bimodal mode, where the text highlights word by word as the audio plays, serves both of them. It does two completely different jobs.


Word-level was built for David

The same passage shown twice side by side, with a whole sentence highlighted on the left and a single word highlighted on the right.
fig 2 · Sentence-level is simpler to build and would have been fine for Ama. For David it fails: his eye still has to search inside the sentence for where the audio is, which is the exact cost bimodal mode exists to remove.
Close-up of the reader with the highlight sitting on a single word, alongside the character-level timestamp data driving it.
fig 3 · The sync runs off character-level timestamps from ElevenLabs, so the highlight follows the actual audio rather than an assumed pace.

Where it breaks

Bookflow's playback speed selector showing the range from 0.5x to 3x, with the usable bimodal band marked between 0.75x and 1.5x.
fig 4 · Above about 2x the highlight moves faster than an eye can track. The sync is still correct. It has just stopped being an anchor and become noise.

Granularity should change with speed. Past the threshold, word-level should degrade to line highlighting, or drop the highlight and keep only position tracking. A fixed granularity across a 6x range was always going to break at one end. Known, not shipped.


The defaults went to Ama

The Bookflow reader on first open: reading mode, a serif typeface, and the chapter list shown before the text.
fig 5 · Reading mode, not listening. Serif. Chapter list first. Every default out of the box is hers.
The typography panel open over the reader, with bimodal mode switched on and the typeface set to Lexend, with OpenDyslexic listed as an alternative.
fig 6 · David’s configuration is one tap away. Close enough to reach, not forced on everyone.
An AI-generated chapter summary shown beside a set of practice questions created from the same chapter.
fig 7 · The AI layer splits the same way. Summaries, practice questions and Q&A are study aids, and they are Ama’s.
The same page of the same book shown twice: on the left in the default configuration with a serif typeface and no highlighting, on the right with bimodal mode on, Lexend, and a word highlighted mid-playback.
fig 8 · Same book, same page, two readers.

Built alone

Architecture diagram for Bookflow: a React Native and Expo client, a Supabase backend with a ten-table schema, row-level security and Edge Functions for file processing, RevenueCat for subscriptions, and ElevenLabs for narration and timestamps.
fig 9 · Roughly a hundred screen states across seven batches, then the build. Product strategy, design system, engineering and go-to-market, all solo.

The usual argument against magic link only is that OAuth is what people expect and signup friction costs conversion.


What the testing was, and was not

A paid closed beta. Over twenty testers, recruited and compensated, on real devices, asked for structured feedback on usability, functionality and accessibility.

That is twenty compensated testers, not twenty users. Presenting it as traction is the only thing that could damage this project, and it does not need the help.

The screen Bookflow shows when an uploaded file cannot be parsed, explaining what went wrong and offering a next step.
fig 10 · Parsing fails on scanned and encrypted PDFs. The screen names the step that failed rather than showing a blank canvas, and sends the reader to Full mode, where the original page layout still works.

Two findings came back. Some PDFs would not parse, which breaks the core promise at the first thing a new user ever does. And the narration needed to sound more natural, which reads as polish and is not, at least not for David: a synthetic voice adds processing cost to someone already spending effort on decoding. Same fix, cosmetic for one reader and load-bearing for the other.

Both are fixed.

~100

screen states, seven batches, one maintainer

20+

paid beta testers on real devices, not users

200

public domain classics in the library

1

auth surface: magic link only


What is still open

When a summary condenses a chapter Ama is about to be tested on, she cannot see what it left out, and nothing in the interface gives her a reason to doubt it.

Confidence in a summary is not the same as accuracy, and Bookflow does not yet distinguish them.

The sourcing dashboard ran into the same problem with AI procurement recommendations, and the answer there was a confidence score, a plain-language explanation, and an override that takes one action. A summary in Bookflow has none of the three.