Cosmic Breathing — A Nebula That Breathes With You
An interactive meditation where a nebula expands and contracts with your breath — 5 breathing patterns, breath-synced Web Audio ambient, Canvas nebula rendering
The Starting Point — I Needed to Rest
When you're deep in code, time beyond the monitor dissolves. At 3 AM you look up and realize your shoulders are locked solid, and your breathing has gone shallow without you noticing.
While building space simulations and games, I found I needed the exact opposite — a space where nothing needs to be operated, where all you have to do is breathe. Just watch a nebula swell and shrink in time with your lungs.
Designing Breathing Patterns
Breathwork isn't a simple timer. Each technique has a different ratio of inhale, hold, exhale, and rest — and each ratio affects the body differently.
const PATTERNS: Record<PatternId, PatternDef> = {
relax: { phases: [inhale(4), hold_in(4), exhale(6)] }, // Relaxation
box: { phases: [inhale(4), hold_in(4), exhale(4), hold_out(4)] }, // Box
sleep: { phases: [inhale(4), hold_in(7), exhale(8)] }, // 4-7-8 Sleep
coherent: { phases: [inhale(5.5), exhale(5.5)] }, // Coherence
sigh: { phases: [inhale(2.5), inhale(1.5), exhale(7)] }, // Cyclic Sigh
};
The 4-7-8 sleep pattern comes from Dr. Andrew Weil's breathing method. The long exhale activates the parasympathetic nervous system. Coherence breathing (5.5s–5.5s) is known to optimize heart rate variability (HRV). Cyclic sigh — a double inhale followed by a long exhale — was validated in Stanford research.
The Nebula Breathes
Breath progress (progress: 0~1) is mapped through easeInOut to the nebula radius. Inhale expands it; exhale contracts it.
function getBreathScale(state: BreathDrawState): number {
const ep = easeInOut(progress);
if (phase === 'inhale') return ep; // 0 → 1 expansion
if (phase === 'hold_in') return 1; // maximum
if (phase === 'exhale') return 1 - ep; // 1 → 0 contraction
return 0; // minimum
}
Nebula color also responds to breath. As inhale deepens, a cool purple (80,60,180) linearly interpolates to warm pink (200,100,160). The deeper you breathe in, the warmer the nebula grows.
Nebula rendering uses an OffscreenCanvas batching technique — draw everything unblurred first, then apply a single blur filter pass. Since blur cost scales with pixel_count × radius², this is far more efficient than blurring individual elements.
Sound Follows Breath
The ambient pad layers 3–4 closely spaced sine waves to create natural beating. 110Hz and 111.5Hz — a 1.5Hz difference produces a slow undulation.
// Breath-synced drone: volume and frequency rise together on inhale
if (phase === 'inhale') {
targetGain = 0.06 + progress * 0.06; // 0.06 → 0.12
targetFreq = 55 + progress * 10; // A1(55Hz) → C#2(65Hz)
}
On inhale, the drone oscillator climbs from 55Hz to 65Hz, thickening the sound. On exhale, it descends back to 55Hz, opening up the space. This subtle 10Hz shift gives breath a physical dimension.
Each breathing pattern uses different pad frequencies. The sleep pattern is based on 82.41Hz (E2) for a deeper, lower tone; the box pattern uses 130.81Hz (C3) for a clearer timbre.
Streaks and Stats
Consistency matters in meditation. Each session's duration is accumulated, and consecutive days are tracked.
// On session completion
const today = new Date().toISOString().slice(0, 10);
const lastDate = storageGet<string>('breathing:lastDate', '');
const prevStreak = Number(storageGet<string>('breathing:streak', '0'));
const yesterday = new Date(Date.now() - 86400000).toISOString().slice(0, 10);
const newStreak = lastDate === yesterday ? prevStreak + 1 : lastDate === today ? prevStreak : 1;
How many consecutive days you've breathed, how many total minutes you've accumulated. It doesn't mean much in itself — but it's a small nudge to open it again tomorrow for just three minutes.
Closing Thoughts
I never expected to build a meditation app while making a space simulator.
But watching a nebula expand and contract while matching your breath, you realize the boundary between simulation and meditation is thinner than you'd think. Both are about creating rhythm — one follows the laws of physics, the other the rhythm of your body.
When your shoulders lock up in front of the monitor, try opening it for just three minutes.