One call to morph
morphTo() takes a shape and returns a promise that resolves on arrival. Setting a new shape while one is on screen interpolates between them on its own clock, with its own choreography.
Shapes and SVG
A WebGL2 particle field that morphs into any SVG. Zero dependencies, 12.4 KB gzipped, and it will run the whole simulation on a worker if you ask it to.

npm i stipple-glimport { Stipple, shapeFromURL } from 'stipple-gl';
const field = new Stipple('#hero');
await field.morphTo(await shapeFromURL('/logo.svg'));That is the entire API surface for most uses. Everything else is opt-in — and if you want to check before you build, isSupported() tells you whether WebGL2 is available so an unsupported browser gets a fallback rather than an exception.
import { isSupported, Stipple } from 'stipple-gl';
if (isSupported()) new Stipple('#hero');
else document.querySelector('#hero').classList.add('static-fallback');stipple-gl/react ships its own 'use client' directive, so Particles drops straight into a Next.js App Router server component with no wrapper and no dynamic import.
import { Particles } from 'stipple-gl/react';
export default function Hero() {
return <Particles count={3500} shape="/logo.svg" />;
}Props are compared structurally rather than by reference, so writing options inline is fine — an idle re-render of the parent reaches the engine as nothing at all. See React for the detail.