Generated with tools/gen_manual_art.py (gemini-3-pro / 3.1-flash /
2.5-flash), consistent picture-book style, no text in images, ~480KB total.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Page views and relay joins/session-lengths appended as JSON lines. Uniques
via daily-salted hash — no IPs, no cookies, no client-side code, no third
parties. tools/stats_report.py prints a per-day table.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
--tokens FILE gates session hosting: hosts present an access code, patients
join live sessions freely (no code), un-joined connections can't relay, and
joined members can't spoof state into other rooms. Easy Mode grows a gentle
access-code card (one-computer mode stays free/ungated); advanced panel gets
a token field; patient view shows a waiting note and auto-retries.
manual.html: picture-book how-to, images slot in under img/manual/.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BLS.relayUrl() picks the relay endpoint: bundled server.py keeps
ws://host:8787; served over https or from a subpath it becomes same-origin
wss://host/<base>/ws. Patient/join links are now path-relative so subpath
hosting works. server.py gains --bind and --http-port for reverse-proxy
setups where 8000 is taken.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
easy.html: giant start/stop, plain-word sliders (how fast / how big / how
loud), friendly sound names (Ocean/Beep/Click/Knock), big color dots,
duration chips, live preview strip of the patient view, same safety notice.
Auto-connects to the relay when served over http with a persistent random
room id — patient link is one big copy button, no Detect IP step.
Advanced panel untouched, linked both ways; server opens easy.html first.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- First-run safety notice (photosensitivity, clinical use, privacy); glow
rate capped at 2.5Hz below the photosensitive trigger band
- Patient data: initials/code hint, Export All / Wipe All buttons
- Relay sessions get crypto-random room ids instead of guessable room-1
- Fix: Pan Sync off now actually stops pink-noise panning
- Fix: slider drags no longer audibly restart the noise source
- Fix: switching pink->discrete preset no longer leaves noise running
- Fix: Speed Boost no longer compounds into stored speed across reloads
- Fix: patient/preset names HTML-escaped in lists
- Fix: patientViewport now relays over LAN (old server dropped it)
- server.py rewritten stdlib-only: static site + WS relay in one process,
no pip/venv; setup.sh/bat deleted, start scripts are now 3 lines
- MIT LICENSE added; README rewritten with safety-first quick start
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Extracted patient logic from `patient.html` to `js/patient.js` for better maintainability.
- Optimized `js/bls.js` renderer to reduce garbage collection by reusing objects in the draw loop.
- Decoupled state persistence from state updates. Added a `persist` flag to `setState` and `mergeState`.
- Disabled state persistence in the Patient view and Admin preview to prevent excessive `localStorage` writes, significantly improving performance on low-end hardware.
- Cleaned up `js/admin.js` to explicitly handle persistence only when necessary.