A symbiote button for the web. A matte, jet-black slab of goo sits on a white studio floor. Bring the cursor close and the surface reaches for it: thin, stretchy tendrils lunge out, web together like pulled mozzarella, coil around the cursor and hold on. Pull away and they neck, snap, and recoil back into the body like melted rubber.
Live demo → · 2× for big screens
Watch the full-quality clip (MP4)
One HTML file, raw WebGL2, no dependencies, no build step.
Made entirely by talking to Claude Code in plain English. The full breakdown, every round of feedback, every measurement, and a prompting playbook live in docs/.
Open index.html in a recent Chrome, Edge, Safari or Firefox. That's it.
Or serve the folder with anything static:
npx serve .Add ?scale=2 (or 3, up to 4) to the URL to render the whole scene larger. Everything scales together: the button, text, tendrils, cursor, shadows and reflections.
index.html?scale=2
- Reaches for you. As the cursor approaches, a fizz of tiny strings rises along the facing edge, then thin tendrils lunge out, curve, and latch on.
- Wraps the cursor. The cursor becomes a 3D hand icon. Each tendril winds a coil around its own finger or the wrist, passing over and tucking underneath the icon.
- Feels caught. The web tugs the hand a few pixels toward the goo and turns it with the pull. Pulling away meets a little friction; when the strands snap, it pops back onto your pointer.
- Stretches and snaps. Tendrils thin as they stretch, shed mozzarella fibres, string cheesy webs between each other, then pinch off at the neck and recoil.
- Stays alive. Every couple of seconds a small burst of strands curls out somewhere new on the edge and sinks back like a wave.
- Lifts on hover. With the cursor on the button, the whole slab rises off the floor and its shadow softens and spreads.
- Looks real. Matte rubber face, a silver label layer, a rim light with a travelling glint, an out-of-focus window reflection with slight RGB dispersion, and a layered contact shadow.
Change the text in one place:
const LABEL_TEXT = 'let’s collaborate';Or drop / paste any SVG onto the page (for example "Copy as SVG" from Figma) and it becomes the silver label. The button resizes to hug it. From code:
VenomButton.setLabel(svgString);Press T (or click Tune in the corner) for live sliders: reach, number of tendrils, snap stretch, max length, viscous flow, slither, lunge speed, magnetism, web grip, thickness, surface pull, gravity and sheen. Copy values puts the current settings on your clipboard as JSON.
The button is a real <button> element, keyboard focusable and labelled for screen readers. Listen for activation:
VenomButton.element.addEventListener('venom:activate', () => { /* … */ });- Scene: a top-down ray march of a 3D signed distance field (the slab, every tendril segment, finger coils, fibres and the cursor icon), blended with polynomial smooth-min so strands fillet into the surface. Pass 1 writes a height/normal G-buffer.
- Shading: pass 2 lights it like a black product shot: shaped studio lights, a procedural room reflection, matte and glossy materials, heightfield soft shadows, ambient occlusion and an analytic contact shadow. Pass 3 applies FXAA.
- Physics: tendrils are substepped Verlet chains (240 Hz) with length and bend constraints, volume-conserving radii, viscoelastic creep, Rayleigh–Plateau beading and pinch-off. Recoil retracts along the strand's own path, so it never buckles.
- Cursor: the arrow and hand icons are baked into signed distance fields from their SVGs, so the arrow can shape-morph into the hand and the goo can wrap a real 3D slab.
Respects prefers-reduced-motion (no tendrils, static surface) and falls back to a plain CSS button without WebGL2.
- Font: Geist by Vercel and basement.studio, SIL Open Font License 1.1 (see
fonts/Geist-OFL.txt). - Cursor artwork: the
left_ptrandhand2icons from the Figma Community file "Cursors" (source SVGs incursors/). - Techniques: smooth-min and SDF primitives after Inigo Quilez; heightfield goo inspired by Robert Leitl's Ferrofluid.
MIT © 2026 exteestudio
