A playful 3D squishy playground with soft-body physics, cute custom lettering, PNG downloads and optional AI material editing.
See the codeHappiness is squeezable. A playful 3D squishy playground with soft-body deformation, cute personalization, recorded sound textures and optional AI material editing.
Pick a shape, press and hold to sink deeper, then release and watch it recover. Make it yours with a little message, a cute font and your favorite text color, and download a PNG of your creation.

Visitor sticker: “You’re squishy vibe no. …” assigns one visit number per browser every 24 hours. Refreshing keeps the same number. The persistent counter starts from its launch and is separate from Vercel Web Analytics. A random token is saved locally for 24 hours; clearing browser storage or changing browsers counts again.
Vercel Web Analytics is enabled in production. Analytics URLs exclude query strings.
The interface uses English throughout. Optional material and appearance settings are saved locally; prompts are not saved.
git clone https://github.com/Daniele-Cangi/squishy-lab.git
cd squishy-lab
npm ci
npm run dev
Open http://127.0.0.1:5173. Use Node 22.13+ on the 22.x line, or 24+, and a browser supporting WebGL 2. Node 22.19.0 and npm 11.6.2 were tested on Windows. Blender is needed only for asset authoring.
Local development displays Local demo · no AI and uses a limited, deterministic description interpreter. Try:
A purple mochi, very soft, with a slow return.Same, but a little firmer.Keep the color and make it recover faster.Make it flatter.Hold Space/Enter while the canvas or Hold to squish control is focused. Release to recover. Escape resets the canvas, or exits fullscreen when expanded. Rotate view changes the camera; Reset shape restores the current material. The footer's Clear saved squishy removes saved material and appearance settings.
The public site is hosted on Vercel, with a same-origin gateway to a private Cloudflare Worker using @cf/qwen/qwen3-30b-a3b-fp8. Genuine Turnstile verification protects AI requests.
English description + optional current material
→ Vercel gateway → private Cloudflare Worker → Workers AI
→ validated material patch → deterministic compiler
→ local physics cage + embedded Three.js surface
The model returns bounded material data, never executable code, shaders or meshes. A request has at most one repair within its timeout budget. Presets, squishing, personalization, PNG downloads and sound do not use AI.
The public AI allowance is 3 verified requests per public IP in a rolling 24-hour window, persisted with a Cloudflare Durable Object. Each slot expires 24 hours after use; devices sharing an IP share the allowance. Requests that begin inference count even if unsupported, cancelled or unsuccessful. Invalid requests and failed verification do not consume a slot. Minute rate limits also apply. No login is required.
For opt-in local live inference, authenticate using npx wrangler login and run npm run dev:ai, then open http://127.0.0.1:5174. This separate adapter keeps credentials server-side and caps the evaluation session at 12 model calls. Read the setup documents before enabling it.
A 216-particle / 750-tetrahedron CPU cage uses XPBD distance and volume constraints. A welded 5,402-vertex visual surface follows the cage, including its lettering and decorations. Physics runs at a fixed 120 Hz with bounded catch-up, supports, inversion barriers and rejected unsafe steps.
Pressure ramps over 0.85 seconds. Sustained holds progressively deepen and widen the contact until second six; dragging moves the contact and adds depth. No hardware pressure sensor is required. The simulation is a tuned toy material, not a calibrated engineering model; arbitrary self-collision is not implemented and only one pointer deforms the object.

Clear Jelly cube after an AI color-only edit to coral pink; shape and material are preserved.

src/shared/ contains the spec, compiler and AI contract. src/physics/ is independent of rendering and hosting. src/scene.ts handles rendering and interaction; src/decorations.ts binds details and custom lettering to the surface. src/sound.ts manages recorded audio. server/ and worker/ implement the API gateway and provider.
The editable workshop contains named reference skins, print meshes and hidden cage references. The browser consumes public/assets/collection-details.json; it does not require Blender at runtime.
npx tsx scripts/export-workshop.ts
blender -b --factory-startup --python scripts/blender-collection.py
Blender 5.2.2 LTS was tested. The authoring script uses installed Arial Bold when available, otherwise Blender's built-in font. Shapes and generic product lettering are original geometry inspired by familiar squishy silhouettes, without brand affiliation.
See collection notes, design notes and deformation notes.
npm run check # typecheck, lint, unit tests, production build
npx playwright install chromium # install the browser if needed
npm run test:browser # interaction, API, mobile, fullscreen and downloads
npm run evaluate:ai # explicit MOCK evaluation; no remote inference
npm run measure:physics # numerical deformation and recovery traces
npm run measure:surface # rendered-surface indentation profiles
npm run worker:check # local Worker bundle/dry run; does not publish
GitHub Actions runs checks and browser tests on Linux using software rendering. CI does not deploy or call live AI. Vercel's Git integration publishes the frontend separately. Browser viewport emulation is not a physical iPhone test. Historical AI campaigns and numerical recordings are documented in the verification report.
Manipulation and presets run locally after loading. Audio loads on demand; custom lettering fonts are bundled locally. Interface typography uses Google Fonts with system fallbacks. There is no guaranteed offline restart or service worker.
Live descriptions are sent to Cloudflare Workers AI. Do not include personal information. Prompts and raw IP addresses are not logged by the application. Turnstile uses the IP transiently; the daily quota stores timestamps keyed by an HMAC-derived IP identifier. Optional settings stay in the browser. No user accounts or prompt history are implemented.
Application code is MIT licensed. Audio and fonts have separate licenses:
The solver follows the XPBD paper and the physical/visual separation demonstrated in Ten Minute Physics. Delay state and the semantic compiler are application-specific approximations.
Made for August, certified squishy expert. ☺
TypeScript
87.1%
CSS
7.8%
Python
4.4%
A playful 3D squishy playground with soft-body physics, cute custom lettering, PNG downloads and optional AI material editing.
See the codeHappiness is squeezable. A playful 3D squishy playground with soft-body deformation, cute personalization, recorded sound textures and optional AI material editing.
Pick a shape, press and hold to sink deeper, then release and watch it recover. Make it yours with a little message, a cute font and your favorite text color, and download a PNG of your creation.

Visitor sticker: “You’re squishy vibe no. …” assigns one visit number per browser every 24 hours. Refreshing keeps the same number. The persistent counter starts from its launch and is separate from Vercel Web Analytics. A random token is saved locally for 24 hours; clearing browser storage or changing browsers counts again.
Vercel Web Analytics is enabled in production. Analytics URLs exclude query strings.
The interface uses English throughout. Optional material and appearance settings are saved locally; prompts are not saved.
git clone https://github.com/Daniele-Cangi/squishy-lab.git
cd squishy-lab
npm ci
npm run dev
Open http://127.0.0.1:5173. Use Node 22.13+ on the 22.x line, or 24+, and a browser supporting WebGL 2. Node 22.19.0 and npm 11.6.2 were tested on Windows. Blender is needed only for asset authoring.
Local development displays Local demo · no AI and uses a limited, deterministic description interpreter. Try:
A purple mochi, very soft, with a slow return.Same, but a little firmer.Keep the color and make it recover faster.Make it flatter.Hold Space/Enter while the canvas or Hold to squish control is focused. Release to recover. Escape resets the canvas, or exits fullscreen when expanded. Rotate view changes the camera; Reset shape restores the current material. The footer's Clear saved squishy removes saved material and appearance settings.
The public site is hosted on Vercel, with a same-origin gateway to a private Cloudflare Worker using @cf/qwen/qwen3-30b-a3b-fp8. Genuine Turnstile verification protects AI requests.
English description + optional current material
→ Vercel gateway → private Cloudflare Worker → Workers AI
→ validated material patch → deterministic compiler
→ local physics cage + embedded Three.js surface
The model returns bounded material data, never executable code, shaders or meshes. A request has at most one repair within its timeout budget. Presets, squishing, personalization, PNG downloads and sound do not use AI.
The public AI allowance is 3 verified requests per public IP in a rolling 24-hour window, persisted with a Cloudflare Durable Object. Each slot expires 24 hours after use; devices sharing an IP share the allowance. Requests that begin inference count even if unsupported, cancelled or unsuccessful. Invalid requests and failed verification do not consume a slot. Minute rate limits also apply. No login is required.
For opt-in local live inference, authenticate using npx wrangler login and run npm run dev:ai, then open http://127.0.0.1:5174. This separate adapter keeps credentials server-side and caps the evaluation session at 12 model calls. Read the setup documents before enabling it.
A 216-particle / 750-tetrahedron CPU cage uses XPBD distance and volume constraints. A welded 5,402-vertex visual surface follows the cage, including its lettering and decorations. Physics runs at a fixed 120 Hz with bounded catch-up, supports, inversion barriers and rejected unsafe steps.
Pressure ramps over 0.85 seconds. Sustained holds progressively deepen and widen the contact until second six; dragging moves the contact and adds depth. No hardware pressure sensor is required. The simulation is a tuned toy material, not a calibrated engineering model; arbitrary self-collision is not implemented and only one pointer deforms the object.

Clear Jelly cube after an AI color-only edit to coral pink; shape and material are preserved.

src/shared/ contains the spec, compiler and AI contract. src/physics/ is independent of rendering and hosting. src/scene.ts handles rendering and interaction; src/decorations.ts binds details and custom lettering to the surface. src/sound.ts manages recorded audio. server/ and worker/ implement the API gateway and provider.
The editable workshop contains named reference skins, print meshes and hidden cage references. The browser consumes public/assets/collection-details.json; it does not require Blender at runtime.
npx tsx scripts/export-workshop.ts
blender -b --factory-startup --python scripts/blender-collection.py
Blender 5.2.2 LTS was tested. The authoring script uses installed Arial Bold when available, otherwise Blender's built-in font. Shapes and generic product lettering are original geometry inspired by familiar squishy silhouettes, without brand affiliation.
See collection notes, design notes and deformation notes.
npm run check # typecheck, lint, unit tests, production build
npx playwright install chromium # install the browser if needed
npm run test:browser # interaction, API, mobile, fullscreen and downloads
npm run evaluate:ai # explicit MOCK evaluation; no remote inference
npm run measure:physics # numerical deformation and recovery traces
npm run measure:surface # rendered-surface indentation profiles
npm run worker:check # local Worker bundle/dry run; does not publish
GitHub Actions runs checks and browser tests on Linux using software rendering. CI does not deploy or call live AI. Vercel's Git integration publishes the frontend separately. Browser viewport emulation is not a physical iPhone test. Historical AI campaigns and numerical recordings are documented in the verification report.
Manipulation and presets run locally after loading. Audio loads on demand; custom lettering fonts are bundled locally. Interface typography uses Google Fonts with system fallbacks. There is no guaranteed offline restart or service worker.
Live descriptions are sent to Cloudflare Workers AI. Do not include personal information. Prompts and raw IP addresses are not logged by the application. Turnstile uses the IP transiently; the daily quota stores timestamps keyed by an HMAC-derived IP identifier. Optional settings stay in the browser. No user accounts or prompt history are implemented.
Application code is MIT licensed. Audio and fonts have separate licenses:
The solver follows the XPBD paper and the physical/visual separation demonstrated in Ten Minute Physics. Delay state and the semantic compiler are application-specific approximations.
Made for August, certified squishy expert. ☺
TypeScript
87.1%
CSS
7.8%
Python
4.4%