# svelte-fluid — Agent Skill

> WebGL Navier–Stokes fluid simulation as a Svelte 5 component library.
> Multi-instance, resize-stable, deterministic seeding. MIT, zero runtime deps.

Package: `svelte-fluid` · Requires Svelte 5 · Homepage: https://svelte-fluid.dev

## Install

```sh
npm install svelte-fluid   # or: bun add svelte-fluid
```

## Mental model (engine background)

- A thin Svelte 5 component (`<Fluid>`) hands a `<canvas>` to a framework-agnostic `FluidEngine` (WebGL2/WebGL1). The engine never imports Svelte.
- Each component instance owns its own GL context, FBOs, programs — many instances coexist on a page. Browsers cap WebGL contexts (~8–16/tab), so use `lazy` on dense pages.
- The sim is a real incompressible fluid solver: advection → (viscosity) → divergence → pressure (Jacobi) → gradient subtract, then dye advection, vorticity confinement (`curl`), bloom/sunrays/shading display.
- Determinism: pass `seed` for reproducible initial splats; the seed survives resize (the engine tears down + rebuilds on resize but keeps the seed).
- Lifecycle: all WebGL access is deferred to `onMount` (SSR-safe). `autoPause` (default true) stops the RAF loop when offscreen/hidden; `lazy` defers engine creation until in view.
- Runtime prop changes go through `setConfig`, which classifies each field: hot scalars (next frame), keyword recompiles (shading/bloom/sunrays/reveal/distortion), FBO rebuilds (resolutions), or construct-only (seed, initial splat counts).

## Components

- `<Fluid>` — Core component. Renders the WebGL fluid sim on a canvas; accepts all FluidConfig props.
- `<FluidBackground>` — Fixed full-viewport fluid behind page content, with DOM exclusion zones.
- `<FluidReveal>` — Uses the fluid as an opacity mask to reveal slotted content underneath.
- `<FluidDistortion>` — Velocity-driven image warping of a supplied src image.
- `<FluidStick>` — Physics-level dye sticking to text/shape masks (e.g. a word).
- `<FluidText>` — Fluid confined inside text letterforms — wraps Fluid with an svgPath text-mode container and auto aspect-ratio via measureText().

Minimal usage:

```svelte
<script>
  import { Fluid } from 'svelte-fluid';
</script>

<div style="width: 100%; height: 420px">
  <Fluid />
</div>
```

`<Fluid>` fills its parent; no props are required. Give the parent a size.

## Key config groups

- Physics: `curl`, `densityDissipation`, `velocityDissipation`, `pressure`, `pressureIterations`, `viscosity`, `splatRadius`, `splatForce`, `maxTimeStep`, `substeps`.
- Auto splats: `autoSplatRate`, `autoSplatCount`, `autoSplatVelocityX/Y`, `autoSplatCenterX/Y`, `autoSplatBandWidth/Height`, `autoSplatSwirl`.
- Visuals: `shading`, `colorful`, `bloom` (+`bloomIntensity`/`bloomThreshold`), `sunrays` (+`sunraysWeight`), `backColor` ({r,g,b} 0–255), `transparent`.
- Shapes: `containerShape` — `circle`, `roundedRect`, `frame`, `annulus` (analytical SDF) or `svgPath` (text/path rasterized to a mask). `glass` adds refraction.
- Flow scenes: `flow` (FlowConfig) for solver-native sources/outlets/forces/scalar fields + `obstructions` the fluid flows around (`obstructionColor` paints them).
- Presetting: `presetSplats` (construct-only initial splats), `seed`.

See the full prop reference: https://svelte-fluid.dev/docs/configuration

## Imperative API (FluidHandle via bind:this)

```svelte
<script>
  let fluid;
</script>
<Fluid bind:this={fluid} />
<!-- fluid.handle.splat(x, y, dx, dy, color) | randomSplats(n) | pause() | resume() | isPaused -->
```

## Presets (zero-config wrappers)

Import and drop in — each pins a tuned `<Fluid>` config. Forwarded props: `width`, `height`, `class`, `style`, `seed`, `lazy`, `splatOnHover`, `aria-label`, `backColor` (flow presets also `pointerInput`).

- **LavaLamp** (classic) — Warm buoyant blobs rising in a glass vessel.
- **Plasma** (classic) — A confined full-spectrum plasma ball churning at center.
- **InkInWater** (classic) — India-ink droplets blooming as they sink through dark water.
- **FrozenSwirl** (classic) — A single icy whirlpool that spins out and freezes in place.
- **Aurora** (classic) — Layered green and magenta ribbons glowing like northern lights.
- **CircularFluid** (container) — Vivid fluid swirling inside a circular container.
- **FrameFluid** (container) — Fluid circulating around a rectangular picture-frame cutout.
- **AnnularFluid** (container) — A ring-vortex orbiting between two concentric circles.
- **SvgPathFluid** (container) — Fluid confined to an ampersand glyph (text container shape).
- **Toroidal** (container) — A violent full-spectrum storm circulating in a toroidal ring.
- **GasFlare** (flow) — A hot buoyant jet rising from a flare-stack nozzle.
- **Venturi** (flow) — Bernoulli's principle: flow accelerating through a pinched throat.
- **Karman** (flow) — Flow past a cylinder, evoking a von Kármán vortex street.
- **TeslaValve** (flow) — Throughflow routing through a passive Tesla-valve channel.

```svelte
<script>
	import { LavaLamp } from 'svelte-fluid';
</script>

<LavaLamp />
```

Full forkable recipes for every preset: https://svelte-fluid.dev/llms-full.txt

## Gotchas

- SSR: components are SSR-safe (engine starts in `onMount`); nothing renders fluid on the server.
- Dense pages: set `lazy` to stay under the WebGL context cap.
- Accessibility: respect `prefers-reduced-motion` in your own auto-animation triggers; pass `aria-label`.
- Colors: `backColor` is 0–255 RGB; splat/dye colors in `presetSplats` are 0–1 (HDR, can exceed 1).
