Inspiration

Attention on screens has fallen from about 2.5 minutes in 2004 to about 47 seconds (Gloria Mark, UC Irvine), and studies of college students find them distracted for roughly a third of the time they set aside to study. Routine tasks like brushing your teeth or getting through everyday to-dos are where focus and executive function break down, not only for the average student, but especially for people with autism and/or ADHD. Story-based supports have shown benefits for focus and routine building, including toothbrushing. So I made content a function of behavior: the story only advances while you're doing the task.

As a student at Virginia Tech, where our motto is Ut Prosim, "That I May Serve." I wanted to build something that serves the people around me, and the Hokie community is a big one. Virginia Tech enrolled nearly 39,000 students in 2024–25, about 31,000 undergraduates and 7,800 graduate students. At that scale, even a small share of students who struggle to focus or keep routines ,especially while they are away from home, is thousands of people. VT's own Hokie Wellness team has made digital well-being a campus priority, and Storry gives students something to better thier focus, skills, and routines that isn't just another motivational productivity app.

I built it to work for the different students on campus:

  • Neurodivergent students. For students with autism, ADHD or dyslexia, Storry has a dyslexia-friendly mode, a low-stimulation mode with no animation or blur, and adjustable contrast and text size. Sensory load and reading style are the student's to set.
  • International students. Virginia Tech's 2025 first-year class came from 66 countries, and roughly 4,000 students on campus are international. Storry writes and narrates stories in 16 languages with native-language voices, so a student can hear a story in their home language, or practice a language they're learning during a routine they already do every day.
  • Younger family members. Kid mode uses simple words and a playful look. It works for siblings, for students with kids of their own, and for the wider Blacksburg community.
  • Everyone else. It runs in any browser, with no app to install, no account to create, and no data leaving the device.

What it does

You can pick a task (brush your teeth, work out, tidy up, or set your own length of time for a task) and a genre for your story. Gemini writes the story and ElevenLabs narrates it sentence by sentence. Narration advances only while a sensor says you're active. When you stop, it pauses with a gentle vibration cue, then resumes when you move. The ending stays locked until the task is done, so you're pulled through to the finish line- forcing you to complete the task.

Each session records on-task percentage, distraction count, and longest unbroken focus streak. Reports cover 7 days, 30 days or all time, with a per-task breakdown, a trend against your earlier sessions, and a 7-day chart with screen-reader labels.

Storry runs in 16 languages, including right-to-left Arabic. Accessibility modes include dyslexia-friendly text across the whole app, low stimulation (no animation or blur), kid mode, low and high contrast, four text sizes, and silent reading with captions.

How I built it

Architecture Storry is a single-page web app (plain HTML, CSS and JavaScript, no framework) hosted on Vercel. A few small serverless functions keep the API keys off the browser.

The state machine only ever sees one number between 0 and 1, so it doesn't care what produced it. Right now that's an Arduino with a photoreceptor, plugged in over USB and read in Chrome or Edge through Web Serial. My sketch prints a light, motion line for every reading (0 to 1023). A reading counts as motion if it differs by more than 15 from either of the two before it. That catches a hand moving. while completing the task.

Sensing. Arduino sends a reading over USB, and the browser reads it with the Web Serial API. The sketch decides "moving" when the newest reading differs from either of the two before it by more than 15.

Story generation

Gemini writes the title and chapter 1 first, so the story starts almost immediately. The rest is written while chapter 1 plays. The story is split into sentences and narrated one at a time. Each sentence stops the moment you stop moving and picks up where it left off when you start again. The next few sentences are fetched ahead of time, so pausing and resuming feels instant. Story length is sized to match the task and your narration speed. The ending is a cliffhanger that only unlocks when the task is finished.

Narration Each sentence is its own ElevenLabs request. I send the sentences before and after it too, so the pacing carries from one clip to the next. Clips are cached and the next three are fetched ahead of time, which is why pause and resume feel instant.

Sentence splitting had to handle each language's punctuation, like Spanish ¿ ¡. I also set up native-language narrator voices, so non-English stories don't sound like an English speaker reading them.

When things break. I wanted every failure to say what happened instead of going quiet. A missing API key, no story server, an exhausted quota and an upstream error each show a different message.

If the first Gemini call fails, a built-in story plays with a notice. If the second call fails after one retry, the story wraps up early with a closing line in the listener's language. If ElevenLabs fails, the device's own voice takes over. A "Check my setup" button tests the story server and the voice.

Privacy Sensor readings stay on the device. Sessions are stored in localStorage, there are no accounts, and API keys live in Vercel environment variables.

Testing I ran Playwright tests with mocked endpoints and injected sensor events. They cover pause and resume, distraction counting, the failure paths and the reports.

Challenges I ran into

Time to first word Writing the whole story before playing anything made the app feel dead, so I split generation into two calls. I measured time to first audio at 1.5 minutes.

Noisy signals A photoresistor reacts to anything that changes the light: a flickering lamp, a phone screen, someone walking past. Comparing against the last two readings, a grace period before pausing, and a calibrated holder mode all helped a lot. It still can't tell real movement from a shadow.

Closed ecosystems Apple Health and smart toothbrushes have no web API, and I didn't have the hardware to build native companions. So I pivoted to a small wearable sensor for now, in the future I would like to expand to syncing smart technology for expansion.

Accessibility as a toggle My first dyslexia mode only changed the story text, so it barely looked different. I rebuilt it as a theme-level mode that changes the whole app.

Accomplishments that I'm proud of

A working loop where a real sensor decides whether a story plays: photoresistor, state machine, Gemini, ElevenLabs. Two-phase generation with schema validation and a fallback at every step, so it never just goes silent. 16 languages, including right-to-left Arabic. Accessibility modes that stack: dyslexia, low stimulation, contrast and text size all work together.

What I learned

In a real-time app, latency is the whole experience. Prefetching, generating while playing and splitting the story into sentences changed how it feels more than any choice of model. I also learned that accessibility can't be added on at the end. It has to be part of the design system.

What's next

Companion apps for Apple Watch and smart toothbrushes through the storrySignal bridge, and testing with a large demographic of college students, autistic students, international/multilingual students, and students with ADHD.

Built With

Share this project:

Updates

Submission history