// lab
A pile of
half-finished ideas.
Tech demos, animation experiments, AI prototypes — things I poke at after the client work is done. Most end up as components in real builds.
18 live
-
// live demo WebGPU Particles
Sixty thousand particles live in a GPU storage buffer while a WGSL compute shader pushes them through a curl-noise flow field, and a second render pipeline draws them additively. No Three.js — raw navigator.gpu, with a Canvas 2D fallback when WebGPU is missing.
- WebGPU
- WGSL compute
- Storage buffers
- Curl noise
Open the demo
-
// live demo Fluid
A real-time Navier-Stokes fluid solver running entirely on the GPU in raw WebGL2 — semi-Lagrangian advection, a 30-step Jacobi pressure solve, float-texture framebuffer ping-pong. Drag to stir the dye.
- WebGL2
- GLSL ES 3.00
- Float FBO ping-pong
- Navier-Stokes
Open the demo
-
// live demo Paint Worklet
A generative flow field drawn entirely by CSS. A Houdini paint worklet traces brand-colored streamlines through procedural noise, repainted each frame by animated @property custom values — no canvas, no render loop. Sliders retune it live; non-Houdini browsers fall back to a gradient.
- CSS Houdini
- Paint API
- registerPaint
- @property
Open the demo
-
// live demo Scroll-Driven
Parallax, scroll-triggered reveals, and a pinned scrubbed scene — driven by native CSS scroll-driven animations with zero JavaScript animating anything. The compositor is the engine; unsupported browsers get a clean, readable static layout.
- animation-timeline: scroll()
- view() timelines
- @property
- 0 JS
Open the demo
-
// live demo Anchored UI
Tooltips, menus, and popovers that tether to their triggers with native CSS Anchor Positioning and the Popover API — zero JS positioning math. Drag the edge probe to watch position-try fallbacks reflow the popover around the viewport corners, with a centered fallback where anchoring is not supported yet.
- CSS Anchor Positioning
- position-try
- Popover API
- @starting-style
Open the demo
-
// live demo Audio Worklet
A generative drone-and-arpeggio synth where every sample is computed inside an AudioWorkletProcessor on the audio render thread. The main thread only nudges AudioParams; an AnalyserNode drives the canvas visualizer.
- Web Audio
- AudioWorklet
- AudioParam
- AnalyserNode
Open the demo
-
// live demo Particle Storm
A few thousand particles, mouse attraction, GPU-friendly motion. Three.js with InstancedMesh + a custom update loop that respects prefers-reduced-motion.
- Three.js
- InstancedMesh
- requestAnimationFrame
Open the demo
-
// live demo Shader Bloom
A fullscreen GLSL fragment shader — time-driven plasma with mouse-reactive distortion. Pure ShaderMaterial inside a Three.js plane.
- Three.js
- GLSL
- ShaderMaterial
Open the demo
-
// live demo Spline Scene
An ambient 3D scene designed in Spline, embedded via the official spline-viewer web component. Lazy-loaded so the runtime JS only fetches when the canvas comes into view.
- Spline
- spline-viewer
- Web Component
Open the demo
-
// live demo Cursor Physics
A spring-driven custom cursor with magnetic snap to interactive elements and click ripple. Vanilla JS, no library.
- CSS transforms
- requestAnimationFrame
- Spring math
Open the demo
-
// live demo Scrollscape
A pinned Three.js icosahedron whose rotation, scale, camera dolly, and wireframe color all scrub off a single scrollY input. No GSAP, no ScrollTrigger.
- Three.js
- position: sticky
- scrollY-driven
- Vanilla JS
Open the demo
-
// live demo AI Pulse
Token-by-token streaming UI with a breathing pulse on the request indicator. Production-ready shell wired to a pre-recorded response so it runs without an API key in the browser.
- Vanilla JS
- ReadableStream
- Anthropic SDK (prod)
- Netlify Functions (prod)
Open the demo
-
// live demo Rive Room
A Rive state machine playing on canvas via the official @rive-app/canvas runtime, loaded from CDN at idle. Currently a community .riv — swap URL for custom.
- Rive
- @rive-app/canvas
- State machine
- CDN runtime
Open the demo
-
// live demo View Transitions
Stage that swaps between Scene A and Scene B using the native View Transitions API — 24 distinct animations, CSS-controlled keyframes, clean fallback for unsupported browsers.
- View Transitions API
- CSS keyframes
- Native browser
Open the demo
-
// live demo WebGL Bloom
Three.js post-processing pipeline — EffectComposer + UnrealBloomPass on a real 3D scene. Emissive materials actually glow, the way film does, not a CSS filter approximation.
- Three.js
- EffectComposer
- UnrealBloomPass
- MeshStandardMaterial
Open the demo
-
// live demo Audio Reactive
A self-contained Web Audio synth — two detuned oscillators, LFO on filter cutoff — feeding an AnalyserNode that drives a real-time canvas visualizer.
- Web Audio API
- OscillatorNode
- AnalyserNode
- Canvas 2D
Open the demo
-
// live demo Tilt Cards
The Apple TV / Vision Pro card hover effect — CSS preserve-3d with a JS-driven radial highlight that tracks the cursor for that glossy "tilt to catch the light" feel.
- CSS preserve-3d
- perspective
- requestAnimationFrame
Open the demo
-
// live demo Metaballs
Three.js MarchingCubes generating an isosurface from overlapping spherical influences. Blobs merge when close, split when distant. CPU mesh rebuild every frame.
- Three.js
- MarchingCubes
- Isosurface
- Phong shading
Open the demo
// nerd-sniping welcome
Got a demo idea?
If there's a library / API / effect you want to see riffed on, send it. I'll see if it makes the list.