npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dilukangelo/fluidkit

v0.5.0

Published

Framework-agnostic GPU fluid simulation for the web. Decoupled sim engine and pluggable render modes.

Readme

fluidkit

Live demo → · npm

fluidkit demo

| melting logo | wet jelly | |---|---| | lava gradient-map | flow around text | | neon glow | refraction |

Framework-agnostic GPU fluid simulation for the web. The sim engine (Stable Fluids on WebGL2) produces velocity/dye field textures; pluggable render modes consume them — smoky dye, flat posterized "sticker" liquid, or your own fragment shader.

Status: v0.5 — WebGL2 core with five render modes (dye, threshold, ramp, displacement, custom); pointer, ambient, programmatic, mask, and audio emitters; obstacles; React/Vue/Svelte adapters; CDN build; experimental WebGPU backend (try it).

Building with an AI coding agent? Point it at AGENTS.md — a complete guide with landing-page recipes, the liquid-vs-smoke look formula, and pitfalls.

Quickstart

npm install @dilukangelo/fluidkit
import { createFluid, threshold } from '@dilukangelo/fluidkit'

const fluid = createFluid(canvas, {
  emitters: { pointer: true, ambient: { strength: 0.2 } },
  render: threshold({
    levels: [{ cutoff: 0.1, color: '#ffc7ff' }],
    background: 'transparent',
  }),
})

That's it — interactive fluid on your canvas. Omit render for the classic smoky dye look.

API

fluid.splat(x, y, dx, dy, { color: '#ffc7ff', radius: 0.25 }) // programmatic droplet, x/y in [0,1], y up
fluid.params.curl = 45                                        // all sim params live-tunable
fluid.setRenderMode(dye())                                    // swap looks at runtime
const tex = fluid.getTexture('dye')                           // raw WebGLTexture for three.js/pixi
fluid.pause(); fluid.resume(); fluid.destroy()

Sim params (all optional in createFluid options, all live-tunable via fluid.params): simResolution (128), dyeResolution (1024), curl (30), pressureIterations (20), pressure (0.8), velocityDissipation (0.2), densityDissipation (1.0), gravity (0 — set 100–400 for pours/waterfalls), wind (0), speed (1), splatRadius (0.25), splatForce (6000).

Render modes

  • dye({ brightness, glow, glowRadius, background }) — classic smoky multicolor, with an optional neon halo.
  • threshold({ levels, background, outline, softness, lighting }) — up to 8 posterized levels with per-level alpha, edge AA, comic/sticker outline stroke, and wet-jelly lighting (gradient-derived normal + specular).
  • ramp(['#0b0212', '#c0245e', '#ffe8d6']) — gradient-map: dye density drives a color ramp.
  • displacement({ source, strength, chromatic }) — the flow field distorts an image, canvas, or video with optional chromatic aberration (refraction/glass effects).
  • custom({ frag, uniforms }) — your GLSL ES 3.00 fragment shader; sample uDye, uVelocity, uPressure, use uTime and texelSize.

Emitters

  • pointer: true | { color, intensity, radius, dragOnly } — fixed color or palette per pointer, dye density, hover vs drag.
  • ambient: true | { strength, count, colors, radius } — configurable autonomous wanderers.
  • fluid.setEmitterMask(textMask('your logo'), { color, strength }) — dye pours out of any text or image mask.
  • fluid.setObstacle(textMask('FLOW')) — fluid flows around the mask; letters appear as negative space.
  • splat() for anything programmatic, or the onFrame(t, dt) option to drive emitters without managing your own loop.

Sim extras: gravity (pours), wind (side drift), speed (slow motion / time scale) — all live-tunable via fluid.params. autoQuality (on by default) halves dye resolution under sustained frame overruns. fluid.reset() clears the fields; fluid.screenshot() returns a PNG data URL; resizes preserve the fluid instead of flashing empty.

Framework adapters & extras

// React
import { FluidCanvas } from '@dilukangelo/fluidkit/react'
<FluidCanvas render={threshold({ ... })} onReady={f => f.splat(0.5, 0.5, 0, 400)} />
<!-- Vue 3 -->
<FluidCanvas :options="{ render: ramp(['#000', '#f0f']) }" @ready="f => ..." />
<!-- import { FluidCanvas } from '@dilukangelo/fluidkit/vue' -->

<!-- Svelte (action, zero deps) -->
<canvas use:fluid={{ render: dye({ glow: 1 }), onReady: f => ... }} />
<!-- import { fluid } from '@dilukangelo/fluidkit/svelte' -->

<!-- Plain script tag / CodePen -->
<script src="https://unpkg.com/@dilukangelo/fluidkit/dist/fluidkit.iife.js"></script>
<script> fluidkit.createFluid(canvas, { render: fluidkit.dye({ glow: 1 }) }) </script>
// Sound-reactive: bass erupts from the bottom, treble sparkles on top
import { createAudioEmitter } from '@dilukangelo/fluidkit/audio'
const audio = await createAudioEmitter(fluid, { source: audioElement }) // omit source = microphone

threshold({ bubbles: { density, rise, size } }) adds rising carbonation specks. Masks accept videos or live: true canvases — an animated logo that pours while it moves.

Behavior you get for free

  • Pauses when the tab is hidden or the canvas scrolls off-viewport.
  • Respects prefers-reduced-motion (opt out with respectReducedMotion: false).
  • Recovers from WebGL context loss; resizes with the canvas; multiple instances per page; destroy() releases all GPU resources.
  • SSR-safe: importing the package touches no browser globals.

WebGPU (experimental)

import { createFluidGPU, isWebGPUSupported } from '@dilukangelo/fluidkit/webgpu'

const fluid = isWebGPUSupported()
  ? await createFluidGPU(canvas, { emitters: { pointer: true } })
  : createFluid(canvas) // WebGL2 fallback

The full sim pass graph ported to WGSL compute. v0 scope: dye rendering + pointer/ambient/ programmatic splats + all live sim params (gravity, wind, speed included). Threshold/ramp/ displacement/custom modes, masks, and obstacles remain WebGL2-only for now.

Examples

The demo ships twenty looks, all driven through the public API (source in demo/main.ts — each is a copy-paste starting point):

dye smoky multicolor · threshold posterized purple · custom ink-on-paper · soda pink liquid pour · waterfall raining streams · fountain rainbow jet · goo outlined metaball cursor · aurora hover-reveal · chrome liquid iridescence · contour living topographic map · neon glowing smoke · lava gradient-map · smoke gray plume in the wind · fire flame ramp · fizz carbonated seltzer · jelly lit slime · logo melting wordmark · collide flow around invisible text · refract image distortion · hero typography over fluid

Hit tune in the demo for live sliders over every sim param + copy-config.

Develop

npm install
npm run dev    # live demo at localhost:5173 with mode switcher
npm test       # host-side unit tests (node 22.6+ / 24)
npm run build  # ESM + .d.ts to dist/

Requires WebGL2 with EXT_color_buffer_float (any non-ancient device).

MIT