db.

Afterlight documentation

Afterlight documentation

Play Afterlight, use its controls and keyboard shortcuts, share scenes, understand how the WebGL and Web Audio engine works, and run it locally.

LiveAny modern browser with WebGL (Canvas 2D fallback)

Play

Open Afterlight. Hold and drag the light, then release it to let the field settle. Choose Nebula, Bloom or Tidal, and adjust flow, energy and color.

ControlWhat it does
Send a pulseMakes an expanding wave.
SoundTurns on the ambient synth; gestures play notes.
Save imageDownloads a PNG without the controls.
Share sceneCopies a link that restores the world, palette, variation, flow and energy.
Hide controlsGives the artwork the whole screen.

Keyboard

KeyAction
1, 2, 3Change world
PSend a pulse
RNew variation
SToggle sound
SpacePause
HHide controls
Arrow keysPull the light (when the field is focused)
EscRestore controls or close a dialog

Shortcuts do not override form controls or browser shortcuts. Reduced motion starts paused; press Resume motion to animate. Hidden tabs stop rendering and suspend sound. If WebGL cannot start, a simpler Canvas 2D artwork appears.

How it works

Seeded particle positions feed custom WebGL shaders that morph between three forms, color by position and respond to an attractor and an expanding pulse. A separate Web Audio graph produces the pad and gesture notes. Scene settings live in the URL fragment.

FileRole
src/engine.jsRendering, fallback, animation lifecycle and image export
src/audio.jsOpt-in synthesis and audio lifecycle
src/state.jsBounded, versioned URL state
src/main.jsControls, input, sharing and accessibility

Run locally

Requires Node.js 22.12 or newer.

Terminal
git clone https://github.com/baney75/afterlight.git
cd afterlight
npm ci
npm run dev
Terminal
npm test
npx playwright install chromium
npm run test:browser
npm run build

Browser tests cover scene changes, pause and reduced motion, URL restoration, image export, missing WebGL, sound lifecycle and layouts at desktop, phone and landscape sizes. dist/ is a static site that can be hosted in a subdirectory.

Something unclear or out of date? Open an issue on GitHub.