Squishy Butter
Press and hold a stick of butter and watch it sink. Real soft-body physics in your browser — no install, no app store. 31 collectible skins, each with its own feel, sound and certificate of authenticity.
The Idea
Almost every squishy thing on the web is a scale animation. The object shrinks toward its middle and springs back — and it feels like rubber, because a spring is what rubber does.
I wanted the other sensation: a fingertip actually sinking into something soft. The material pushing back when you jab it, giving way when you lean slowly, holding the dent for a beat after you let go and then easing back rather than snapping.
That's a materials problem, not an animation problem. You can't get there with CSS. It needed a real deformation model running on the graphics card — and once the feel existed, everything else got built around it.
Try It
Click and hold — a quick tap only reaches about a quarter of the depth. The longer you press, the deeper it goes.
Mobile Experience
It's built for touch first — press and hold with your thumb, drag to plough a groove, pinch and spin to look around it. The whole thing runs in the browser, so there's nothing to install.
Live — press and hold
Why It Feels Right
Four decisions do most of the work, and each one is something you notice in the first three seconds without being able to name it.
- Jab it and it resists. Lean on it and it gives. Resistance rises with the square of how fast you're pressing, which is the property that actually separates memory foam from rubber. Even damping feels the same at every speed — this doesn't.
- Hold it and it keeps giving. The target depth drifts lower the longer your finger stays down, so the butter never hits a wall and stops. It's why holding is worth doing and tapping isn't.
- Let go and the dent stays. It sits there for a couple of seconds doing nothing, then eases back — and it never bounces. A spring would overshoot, and overshoot is exactly what reads as jelly. Deeper presses take longer to recover, because there's more to undo.
- Press in several places at once. Every dent is its own little simulation, so you can poke here, poke there, and watch both fade on their own schedule.
It Sizes Itself to Your Device
Each simultaneous dent costs memory on the graphics card, and the budget varies wildly — a desktop has plenty, plenty of phones have a fraction of it. Ask for more than the device has and the shader silently fails to compile, which renders as nothing at all. The butter just never appears, and it looks like a loading bug rather than a graphics one.
The shader asks the device what it can afford before deciding how much to use.
So it asks first, then compiles itself to fit — up to 48 simultaneous dents on a laptop, scaling down on weaker hardware. One codebase, no device detection, no separate mobile build.
31 Skins, Zero Image Files
Marble veining, zebra stripes that taper and fork the way real ones do, cheetah rosettes, wood grain that crowds and spreads along the ring, tie-dye, denim, camo, gold foil. Every one is drawn at runtime in code — there isn't a single image file in the project.
Which means the download stays tiny no matter how big the catalogue gets, and adding a skin is writing a function instead of running an art pipeline. That's the only reason a catalogue this size was practical for one person.
Skins aren't just colours, either. Each has its own physics — Frozen barely yields until you warm it up with your finger, and it warms where you touch it, so one end can soften while the rest stays solid. Each has its own sound, generated live and fed the dent's depth and speed every frame so it tracks what your hand is doing. And each has a rarity, a supply cap, a serial number, a written provenance story, a certificate and a trading card.
A Few Things Under the Hood
- Fur is 16 stacked layers, not a texture. Printed fur reads as fabric with a picture of fur on it. Real depth means drawing the mesh repeatedly, each copy pushed a little further out, with only the strand pixels surviving. Every layer runs the squish shader too, or the coat would stay stiff while the butter dented underneath it.
- Gold reflects the actual room. Metal looks like metal because it mirrors its surroundings. Paint the highlights into a texture instead and you get yellow plastic wearing a picture of gold.
- Limited runs are enforced in the database, not the app. Two people buying the last copy at the same instant must not both get serial #100 — so minting locks the row, checks supply, assigns the serial and issues the certificate hash inside a single transaction.
What Was Hard
Getting the feel right was mostly deleting things that were subtly wrong. A spring on release. A dent that stayed the same size no matter how hard you pressed. A drag that slid one divot around instead of ploughing a groove. Each was defensible on its own, and each one made the butter feel like a different material than I wanted.
The worst bug looked completely correct in the code. Dragging is meant to leave dents behind your finger, and the spacing check measured the gap between the cursor and the active dent — except that dent eases toward the cursor every frame. I was measuring the distance between the cursor and something chasing the cursor, so it never grew large enough to trigger, and below a certain speed dragging left no trail at all. Reading it, it looked fine. Simulating the loop outside the browser found it in one pass. That lesson stuck harder than the fix did.
Where It Stands
The engine works and the catalogue is finished: 31 skins with individual physics, sound and presentation, running at frame rate from laptops down to phones, in roughly 7,000 lines.
What's left is the shop. Accounts, server-side ownership and checkout are designed and partly written but not yet connected — that's the next build, and it's the difference between a very good toy and something people can own.
Tally was hard because four platforms and two payment systems had to be correct at once. This one is hard in a narrower way: the whole product is a feeling. It either lands or it doesn't, and there's nothing to hide behind.