stillpoint

the guide

how this site was made

stillpoint is a breathwork studio that teaches exactly one protocol — 4–7–8 — to stressed professionals. so the site does exactly one thing: it puts a working breath pacer in the center of the first viewport and lets you try a cycle before it asks for anything. the art direction is a dawn that the page moves through as you breathe — rose on the inhale, sky on the hold, dusk on the long exhale — with enormous whitespace and one idea per viewport.

palette

a dawn, split into phases

no accent color, no pure white, no black. the three sky gradients are fixed full-screen layers; only their opacity changes, so the whole page can breathe at 60fps without repainting a single gradient.

type

wide, light, lowercase

asap (variable, width axis pushed to 125%, weights around 210–380) carries the display voice: a rounded humanist sans that turns soft and unhurried when you stretch it wide and strip the weight out. hanken grotesk at 300 does the reading. there is almost no bold anywhere — emphasis comes from width, spacing, and silence — and every character on the site is lowercase, because the brand never raises its voice. the giant 4 / 7 / 8 numerals are the only loud thing, and they are the literal content of the protocol.

techniques

the breathing engine

one requestAnimationFrame loop drives everything: the blob, the ring, the countdown, and the sky. the blob is an svg path rebuilt every frame — a circle whose radius is modulated by three slow sine harmonics, then scaled by the breath:

// radius = base × breathScale × (1 + soft harmonics)
var w = 1 + wobble * ( 0.52 * Math.sin(3*a + t*0.50)
                     + 0.30 * Math.sin(5*a - t*0.34)
                     + 0.18 * Math.sin(2*a + t*0.21) );
var r = R_BASE * scale * w;

the breath scale follows the protocol timeline — 4s up, 7s shimmering hold, 8s down — through an ease-in-out sine, and everything chases its target with frame-rate–independent lerps so a dropped frame never jolts the breath:

if (ph.i === 0) s = lerp(0.62, 1.0, easeInOutSine(ph.p)); // in, 4s
if (ph.i === 1) s = 1.0 + 0.006 * Math.sin(ph.p*TAU*1.5); // hold, 7s
if (ph.i === 2) s = lerp(1.0, 0.62, easeInOutSine(ph.p)); // out, 8s
scale = lerp(scale, s, Math.min(1, dt * 9));

the progress ring’s track is three arcs whose lengths are exactly 4/19, 7/19 and 8/19 of the circumference — the structure of the ring is the protocol. the sky crossfade and the blob’s gradient stops interpolate between rose, day and dusk triplets in the same loop. under prefers-reduced-motion the form stands still and the cycle runs as a stepped, once-per-second countdown with gentle discrete sky changes.

iteration

three passes

do this yourself

a recipe

  1. give claude a subject with a built-in rhythm — a breath, a tide, a metronome — and ask for the page to physically perform it, not illustrate it.
  2. pin the palette to a real phenomenon (here: one dawn) and assign each color a moment in time, not a ui role.
  3. pick one variable font and spend its axes deliberately — width for voice, weight for volume — instead of adding more typefaces.
  4. ask for a single rAF loop that owns all motion, with targets and lerps, so every element breathes from the same clock.
  5. make structure carry data: if a ring has segments, their lengths should mean something.
  6. demand a real reduced-motion fallback and test it — a calm page that can also hold still.
  7. screenshot, critique, fix — three times, at 1440px and 390px. read the screenshots like a stranger would.
  8. end by removing one thing you like. it will hurt. do it anyway.