Skip to content

Adding a particle layer

A particle-geometry component creates a layer, writes positions into it, and disposes it on unmount. It renders nothing itself.

See Particles for the layer API.

export function Star({ points }: StarProps) {
const ctx = useFabric()
effect(() => {
const g = ctx.gpu(); if (!g) return
const style = untrack(() => ({ /* one-time reads */ }))
const layer = createParticleLayer(g, capacity, style)
cleanup(() => disposeParticleLayer(g, layer))
})
return null
}

The untrack is required. The create effect reads style props once to build the layer. If those props are reactive — flux accessors are — reading them inside the effect tracks them, and moving a style slider re-runs the effect, which disposes the layer and re-creates it empty. Nothing pushes the geometry again, so the points disappear. untrack makes the effect depend on ctx.gpu() only; the layer’s own wire() handles later style changes.

The data signal is the exception. samples is the redraw trigger and is meant to be tracked. Only one-time setup reads go inside untrack.

  • Keep it small. Layer components are statically imported, so they land in the eager chunk rather than a lazy one.
  • Add no WGSL. Reuse the shared particle pipeline. A new shader would make the component a build-tooling concern.
  • Never add a type: field. The build scans for it to decide which SDF primitives survive, and yours would pin one nothing uses.
  • Do not add region markers unless you mean them.
  • Do not call initParticles. Boot already created the primary buffers, and a second caller destroying them conflicts with the first.

Take geometry data as a prop and let the layout file own the subscription. A component that imports the transport layer couples the library to it and blocks extraction.