All notable changes to the lab. The app is a single self-contained
index.html; versions refer to feature sets, not package releases.
Four modes that make the lab useful beyond play.
?preset= (any preset incl.
hidden), ?ui=0 kiosk, ?zen=1, ?sound=0|1, ?fps=30 frame cap,
?breathe=1, ?bench=1, composable with ?seed=. URL-driven
sessions are ephemeral and never overwrite saved settings.gl_VertexID/texelFetch. Deck section with count
(9k/16k/37k), size and brightness; toggleable; hidden on WebGL1.Goal: sessions that hold attention for 30–40 minutes.
Response to first-session feedback ("launched it but left after some minutes"): the early game now rewards, breathes, and invites returning.
og.jpg).manifest.webmanifest (fullscreen, maskable icons) and a
versioned cache-first service worker (sw.js): installable from the
browser, runs fully offline over HTTPS/localhost.scripts/smoke.mjs) on every push: boots, stirs, fails on any error.fonts/ (WOFF2, latin subsets); zero third-party requests
(GDPR: no visitor IPs to Google), works offline.:focus-visible outlines; prefers-reduced-motion
disables the opening burst and defaults surprises off; instant toasts.e.key (the character produced) instead of
e.code (the physical US-QWERTY position), so Z triggers zen mode
on German QWERTZ and other non-US layouts — previously the printed Y
key did.PROMPT.md / prompt.html — the from-zero build prompt, in
markdown and as a styled page with a copy button.f1b0253The engagement update: the lab now rewards staying, returning, and poking at the edges.
?seed= URL that reproduces the flow
exactly on any machine.🔒 ??? chips with hover hints and unlock
with a discovery toast. Progress persists across sessions.rheo.webm.Headless Chromium (Playwright): clean boot with zero console errors;
onboarding fires and advances on the first stroke; ?seed= URLs load
deterministic flows; walls deflect ink (screenshot-verified); gallery
snapshot persists and renders; Maelstrom unlocks at 150 strokes;
rheometer reads live values; a 1.5 s recording produced a 2.3 MB WebM;
session report downloads populated.
6677914A single-file, zero-dependency interactive fluid simulation.
README.md and as a styled
standalone docs.html.Tracked on the project board: moderated usability tests (kit prepared, needs human participants) and a WebGPU compute backend with WebGL fallback (planned as a dedicated milestone).
# Changelog — RHEO · fluid lab
All notable changes to the lab. The app is a single self-contained
`index.html`; versions refer to feature sets, not package releases.
## v2.8.1 — Tappable toasts (2026-06-11)
### Added
- **Discovery toasts are actionable**: tapping "✦ you discovered: …"
applies the freshly unlocked preset immediately (amber-rimmed, hover
glow; the toast layer stays pointer-transparent otherwise). The
comeback toast likewise: tap loads the fresh flow of the day.
## v2.8 — Useful modes (2026-06-11)
Four modes that make the lab useful beyond play.
### Added
- **Breathe** — guided breathing sessions (Box 4·4·4·4 / Relax 4·7·8 /
Coherent 5·5; 2/5/10 min): converging ring + lift on the inhale,
diverging ring + settle on the exhale, serif phase overlay with timer
and breath counter, Esc to end. Surprises/tips pause during sessions.
- **Ambient display / OBS URL API** — `?preset=` (any preset incl.
hidden), `?ui=0` kiosk, `?zen=1`, `?sound=0|1`, `?fps=30` frame cap,
`?breathe=1`, `?bench=1`, composable with `?seed=`. URL-driven
sessions are ephemeral and never overwrite saved settings.
- **Music mode** — opt-in microphone FFT (512 bins): bass-beat
detection fires palette bursts scaled by intensity; sensitivity dial;
audio never leaves the device; session-only.
- **Benchmark** — standardized 20 s run (4 phases sweeping sim/ink
resolution under a deterministic Lissajous stir), resolution-weighted
score with per-phase fps, clipboard share line, best score persisted.
## v2.7.1 — Sound on by default (2026-06-10)
### Changed
- **Sound is now on by default** (browsers still gate audio behind the
first interaction, so it starts with the first touch/click). Stored
configs are migrated once; turning it off afterwards is respected.
## v2.7 — Ghosts (2026-06-10)
### Added
- **Ghost loops** — a loop pedal for strokes: **G** (or the deck's
⏺ Record loop) captures up to 20 s of drawing at splat granularity
(position, force deltas, dynamics radius, inkless flag); the passage
then replays forever as an autonomous performer with a fresh palette
color each pass. Up to 3 simultaneous ghosts with play/pause/delete,
persisted in localStorage, excluded from stroke/experiment counters.
## v2.6 — Stardust (2026-06-10)
### Added
- **Stardust particle layer** (WebGL2) — up to ~37 000 tracer particles
advected by the velocity field: positions in an RGBA32F (16F fallback)
ping-pong texture, updated by a fragment pass with lifespan, respawn
and wall avoidance, rendered as additive soft points colored by the
local ink via `gl_VertexID`/`texelFetch`. Deck section with count
(9k/16k/37k), size and brightness; toggleable; hidden on WebGL1.
- **Stylus pressure** — on pen input, pressure scales the splat radius
on top of the speed-based dynamics.
## v2.5 — Feel & spectacle (2026-06-10)
### Added
- **Sunrays** — volumetric light shafts: a brightness-derived occlusion
mask of the ink is radially blurred from the screen centre and
modulates ink and glow (Glow & rays section: toggle + Ray weight).
- **Vortex tool** — right-drag spins a Rankine-style vortex at the
pointer (shift reverses direction); **V** or the Brush tool selector
enables it on touch. Pure rotation — no ink, no stroke counting.
- **Brush dynamics** — stroke speed scales splat radius (Dynamics dial,
default 0.35): fast strokes paint wide like a loaded brush.
- **Musical strokes** — with Sound on, each ink stroke plays a soft
pentatonic sine pluck, stereo-panned to where it lands, layered over
the existing activity drone.
## v2.4 — The Lab Notebook (2026-06-10)
Goal: sessions that hold attention for 30–40 minutes.
### Added
- **Lab Notebook** — an 18-experiment chain shown one goal at a time in a
compact widget with a live progress bar: stirring, inkless pushing,
bursts, presets, a 60 tex/s storm, kaleido drawing, wall building and
stirring against it, velocity/pressure field visits, filling a third of
the canvas with ink, gravity pours, gallery snapshots, seeded flows,
max-swirl drawing, 30 s of zen, and a free-research capstone. Progress
is measured against real simulation state — peak flow speed and ink
coverage are read back from the GPU on WebGL2 (activity proxies on
WebGL1) — persists across sessions, doubles as a deep feature tour, and
paces out to a relaxed 30–40 minutes. Dismissable; toggle lives under
Surprises & sound. Touch-aware task wording.
- **Two gated presets** — Singularity (8 experiments) and Glasswing (16)
extend the unlock chain to ✦ n/8.
- Session reports now include experiments completed.
## v2.3 — Retention update (2026-06-10)
Response to first-session feedback ("launched it but left after some
minutes"): the early game now rewards, breathes, and invites returning.
### Added
- **Three new unlockable presets** — Undertow (15 strokes), Kaleidos
(20 strokes in 4-way symmetry), Riptide (build with the wall brush) —
and Maelstrom rebalanced from 150 to 60 strokes, so the first
discovery lands inside the first minute of play.
- **Discovery counter** — the stats chip shows ✦ n/6.
- **Idle drift** — when stirring stops and the ink fades, gentle blooms
keep the canvas alive; it never sits dead black (toggle in Surprises &
sound; off for reduced-motion users).
- **Rotating tips** — up to three per session, drawn without repeats
from a touch- or keyboard-appropriate pool, surfacing untried features.
- **Comeback hook** — returning on a new day greets with the visit
streak ("day 3 in the lab") and points at the fresh flow of the day.
### Changed
- **First surprise within 45–80 s** (was 2–4 minutes — after most short
sessions had already ended); subsequent events keep the slow cadence.
## v2.2 — Production readiness (2026-06-10)
### Added
- **Identity & link previews** — favicon, app icons (192/512 + maskable +
apple-touch), meta description, theme-color, Open Graph/Twitter cards
with a generated 1200×630 preview image (`og.jpg`).
- **PWA** — `manifest.webmanifest` (fullscreen, maskable icons) and a
versioned cache-first service worker (`sw.js`): installable from the
browser, runs fully offline over HTTPS/localhost.
- **CI** — GitHub Actions workflow runs a headless Playwright smoke test
(`scripts/smoke.mjs`) on every push: boots, stirs, fails on any error.
- **Adaptive quality** — sustained FPS < 30 lowers ink resolution one
notch (once per session, with a toast).
- **Help link** — a "?" in the deck header opens the documentation.
### Changed
- **Self-hosted fonts** — Instrument Serif and IBM Plex Mono now load
from `fonts/` (WOFF2, latin subsets); zero third-party requests
(GDPR: no visitor IPs to Google), works offline.
- **Legal footer** — Impressum and privacy policy links on all pages.
- **Accessibility** — `:focus-visible` outlines; `prefers-reduced-motion`
disables the opening burst and defaults surprises off; instant toasts.
## v2.1.1 — International keyboard fix (2026-06-10)
### Fixed
- Shortcuts now match on `e.key` (the character produced) instead of
`e.code` (the physical US-QWERTY position), so **Z** triggers zen mode
on German QWERTZ and other non-US layouts — previously the printed Y
key did.
## v2.1 — Mobile support (2026-06-09)
### Changed
- **Bottom-sheet deck** — on screens ≤ 700 px the deck docks full-width at
the bottom with safe-area padding; it starts closed so the fluid owns the
screen, behind a "rheo" chip. Stats, hint, toasts and the footer credit
reflow for narrow viewports.
- **Touch ergonomics** — on coarse pointers all sliders, checkboxes,
selects, chips and buttons grow to comfortable tap sizes.
- **No-keyboard paths** — a "Zen (Z)" button joins the Actions row;
double-tap exits zen on touch; tapping a locked preset chip reveals its
unlock riddle (hover hints don't exist on touch); Share uses the native
share sheet when available.
- **Performance defaults** — devicePixelRatio capped at 2; first run on a
touch device starts at ink resolution 512 (the dial still goes up).
- **Adapted copy** — hint line and the onboarding tour use touch wording
(no shift-drag or keyboard references).
- Added `PROMPT.md` / `prompt.html` — the from-zero build prompt, in
markdown and as a styled page with a copy button.
## v2 — Play & discovery (2026-06-09) · commit `f1b0253`
The engagement update: the lab now rewards staying, returning, and poking
at the edges.
### Added
- **Flow of the day & share links** — "Today's flow" derives a complete
mood (palette, swirl, fades, symmetry, forces, glow, opening splat
choreography) deterministically from the date; "Random flow" rolls a
named seed; "Share" copies a `?seed=` URL that reproduces the flow
exactly on any machine.
- **Paintable walls** — a wall brush (**O**, or the Brush tool selector)
paints solid obstacles into the domain. The obstacle mask is sampled in
the splat, advection, and projection passes, so fluid parts around
walls and ink cannot enter them. Walls render as warm stone with a rim
light, can be erased selectively or cleared, and survive window
resizes.
- **Gallery** — unusually energetic moments are auto-captured (activity-
scored, at most one per 20 s) into nine persisted thumbnails; clicking
one restores the full settings that produced it. "Snapshot now" pins
manually.
- **Unlockable presets** — Maelstrom (150 lifetime strokes), Tidepool
(3 minutes of total stirring), and Eclipse (Swirl 60 + brush force
≥ 15 000) ship as locked `🔒 ???` chips with hover hints and unlock
with a discovery toast. Progress persists across sessions.
- **Surprise events** — every 2–4 minutes of active play one of three
rare ambient events fires: a comet streak, a ring bloom, or a 4-second
gravity surge. Implemented as transient force offsets that never touch
saved settings; one checkbox disables them.
- **Reactive audio** — an opt-in WebAudio drone (two detuned sawtooth
oscillators through a resonant low-pass) whose cutoff and volume follow
a decaying fluid-activity measure fed by every splat.
- **Zen mode** — **Z** hides all UI and lets the lab drift with a slow
breathing wind and occasional gentle blooms.
- **Rheometer** — WebGL2-only live measurements read back from the GPU at
2 Hz: mean/peak speed, mean kinetic energy, RMS vorticity, with a
graceful fallback when float readback is unavailable.
- **WebM recording** — Record ⏺ captures the canvas via MediaRecorder
(VP9 preferred) and downloads `rheo.webm`.
- **Session reports** — a downloadable standalone HTML report with
session stats, lifetime progress, discoveries, seed, embedded gallery
shots, and the full settings table.
- **First-run onboarding** — four quiet toast steps driven by what the
user actually does (stir → shift-drag → presets → shortcuts); shown
exactly once.
- **Footer credit** — © 2026 Thorsten Meyer · Powered by
[Thorsten Meyer AI](https://thorstenmeyerai.com/), in the app and the
docs page.
### Verification
Headless Chromium (Playwright): clean boot with zero console errors;
onboarding fires and advances on the first stroke; `?seed=` URLs load
deterministic flows; walls deflect ink (screenshot-verified); gallery
snapshot persists and renders; Maelstrom unlocks at 150 strokes;
rheometer reads live values; a 1.5 s recording produced a 2.3 MB WebM;
session report downloads populated.
## v1 — Initial release (2026-06-09) · commit `6677914`
A single-file, zero-dependency interactive fluid simulation.
### Added
- **GPU solver** — Jos Stam's *Stable Fluids* in WebGL fragment shaders:
semi-Lagrangian advection, vorticity confinement, configurable Jacobi
pressure solve, gradient subtraction; half-float ping-pong textures
with WebGL2→WebGL1 fallbacks, format renderability probing, manual
bilinear filtering where needed, context-loss recovery, resize
settling.
- **Control deck** — collapsible panel with ~40 dials across presets,
simulation, forces, brush, auto bursts, display, glow, and actions;
all settings persist to localStorage.
- **Presets** — Default, Sumi ink, Incense, Neon, Aurora, Fever dream,
Molasses.
- **Color systems** — rainbow cycle, random per stroke, five curated
palettes (Aurora, Ember, Glacier, Orchid, Verdant), fixed color;
mirror (2-way) and kaleido (4-way) symmetry brushes.
- **Display modes** — ink with pseudo-3D shading and dithering, plus
velocity / pressure / vorticity field visualizers with gain control.
- **Glow** — bright-pass prefilter with soft knee, 8-level blur chain,
intensity dial.
- **Interaction** — drag to stir + ink, shift-drag for force only,
multi-touch; Space/S/R/C/H shortcuts; FPS/grid stats chip; PNG export.
- **Documentation** — full reference in `README.md` and as a styled
standalone `docs.html`.
## Open / planned
Tracked on the project board: moderated usability tests (kit prepared,
needs human participants) and a WebGPU compute backend with WebGL
fallback (planned as a dedicated milestone).