work

BREATHE

inhale. exhale. repeat.

shipped
April 2026
stack
three.js · Web Audio API · WebXR hand rig
live
breathe.somedaystudios.xyz

What it is

Seven minutes of box breathing. 432 seconds, 27 cycles, each one four seconds inhale, four hold, four exhale, four hold. A dithered cosmic background, a narrated story, and a rigged hand forming a mudra that opens and closes with your breath.

No build step

The entire app is static files. Three.js loads via an importmap from a CDN, the dev server is a forty-line static file server, and there are zero npm dependencies. git clone and open it.

This isn't minimalism for its own sake. The app has to run identically in five years, and the surest way to guarantee that is to have nothing to rebuild.

The audio

The drone is generated, not sampled — three detuned sawtooth oscillators plus a fifth, through a low-pass filter with an LFO. Singing-bowl chimes mark each phase transition, and a G5 bell closes the session. Twenty-seven narration clips play over the top, one per cycle.

Colors move through the spectrum across the session, red at the start to white at the end, one hue per cycle.

What was hard

iOS audio. Mobile Safari won't start audio outside a user gesture, and a meditation app that opens silent is a broken meditation app. Every audio path unlocks inside the first tap, including the narration element that doesn't play until seconds later.

Lazy narration. Twenty-seven audio clips is a lot to load up front. They stream in as the session progresses so the first breath starts immediately.