Inspiration
Self-guided EMDR and "bilateral tapper" apps are everywhere now — a dot slides back and forth, you follow it, and it's meant to take the edge off. But almost all of them share the same blind spot: they run entirely on self-report. You drag a 0–10 distress slider, and the app trusts that number completely. The trouble is, the number you type is rarely how activated your body actually is — people under-report, over-report, or just don't know. And worse, most of these apps happily let you pick your most painful memory on the very first screen, with no check that you're steady enough to go there. That's the opposite of how any clinician would pace it.
We wanted something that reads the body even a little, and that treats readiness and safety as the main event rather than fine print. Along the way we realized the same eye-tracking engine that calms an anxious nervous system is also a recognized tool in concussion recovery — so we leaned into that too.
What it does
Lenis guides you through gentle, EMDR-style bilateral stimulation — a soft, breathing "fluffball" that eases side to side while your eyes follow — and adapts the pace to the sound of your voice, not a slider.
- Vocal-adaptive pacing. Between sets, you speak for a few seconds. Lenis analyzes the sound of your voice on-device — pitch variability, speech pace, energy — into a rough arousal proxy, and sets the next set's speed from it. Sound keyed-up and the fluffball visibly slows; sound settled and it stays easy. It's a mechanism you can watch happen.
- On-device coaching, no API key. A free, in-browser transcript plus a rule-based coach turns your check-in into a short, warm prompt and a pacing decision — and quietly flags crisis language to route you to real help. No cloud model, nothing uploaded.
- Safety as a feature. A consent gate, always-visible crisis resources, a live slower/stop control, guidance to close your eyes and follow the sound if the motion makes you dizzy, and a self-report-vs-voice comparison that shows when your words and your body disagree.
- Honesty on purpose. A built-in "About the evidence" screen states plainly what's well-supported (EMDR for PTSD), what's genuinely debated (whether the eye movements themselves add much), and what's a proof-of-concept (our voice read).
- A concussion recovery mode. The same smooth-pursuit engine powers clinician-aligned oculomotor exercises — smooth pursuit and saccades — with a symptom check before and after, and a summary you can bring to your clinician. Symptom-titrated: a little challenge is expected, a real flare is your cue to stop.
How we built it
Lenis is a single-page React + Vite + TypeScript app built as a small state machine (welcome → evidence → recovery → setup → session → check-in → close). The bilateral-stimulation engine lives on an HTML <canvas>: eased side-to-side motion that decelerates at the edges the way a therapist's hand does, stereo-panned tones through the Web Audio API, and haptic taps. The friendly fluffball is drawn procedurally — layered, light-shaded fur, glossy eyes, a subtle breathing scale, and a twinkling starfield behind it.
For the voice work we used Pitchy for pitch detection and Meyda for energy, blending pitch variability, speech continuity, and loudness into a 0–1 arousal proxy. The reasoning layer is deliberately on-device and key-free: free Web Speech API transcription plus a rule engine, written behind a small Guidance interface so a hosted model could drop in later without touching the UI. No backend, no auth, no persistence — deployed as a static site on Render.
Challenges we ran into
Dizziness was the big one — and the most important. Early on, following the target made testers genuinely nauseous. We treated that as a safety signal, not a UI nit: we narrowed the sweep, slowed the default pace, added a live in-session speed control, and built a "close your eyes and follow the sound" path so the whole thing works without visual tracking at all. That same insight is what makes the concussion mode credible.
Being honest about the evidence was harder than expected. It was tempting to add lots of pretty movement patterns and imply they were therapeutic — so we cut them to the two with actual support and wrote an evidence-disclosure screen instead. And doing the "AI" without an API key meant designing the reasoning as an on-device rule engine over the vocal signal and a free local transcript, which keeps audio private and lets the whole thing run offline.
Accomplishments that we're proud of
The pace visibly changes from your voice — a differentiator a judge can see with their own eyes, not just read about. The design is genuinely private: no audio, transcript, or data ever leaves the device. We built a friendly, huggable character that keeps sessions calm and low-stimulation. And above all, we treated clinical humility and safety as features — the readiness ethos, crisis routing, the evidence screen — rather than disclaimers bolted on at the end.
What we learned
Reading arousal from a voice is noisy and imperfect — and that's exactly the point. Pairing an imperfect signal with an honest self-report comparison is far more useful, and more responsible, than pretending it's a clinical instrument. We also learned that a safety-first constraint — designing around dizziness — didn't shrink the product; it opened up an entirely new use case in concussion recovery.
What's next for Lenis
A full stabilization gate: a "safe place" resourcing step plus a calm vocal baseline that must pass before deeper memory work unlocks. A richer concussion mode with convergence exercises and a longitudinal symptom graph. And an optional drop-in of a hosted model for deeper coaching, slotting cleanly behind the interface we already built.
Built with
react typescript vite web-audio-api web-speech-api pitchy meyda html5-canvas render
Try it out
- GitHub repo
- Live (Render): paste the Render URL after deploy
Built With
- html5
- meyda
- pitchy
- react
- render
- typescript
- vite
- web-audio-api
- web-speech-api

Log in or sign up for Devpost to join the conversation.