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

pondscape

v0.1.3

Published

A living, realistic pond for the web: physically based water, caustics, lily pads, koi and axolotls, rendered with WebGL2.

Readme

pondscape

A pond rendered by pondscape: koi, an axolotl, lily pads and water lilies over a sunlit pond floor, with a ripple spreading from a tap

A living pond for the web. Real-time water with physically based ripples and caustics, lily pads and water lilies, swaying grass, koi and axolotls, all rendered with WebGL2 into a single canvas.

  • Water that behaves like water. Ripples follow the physics of real surface waves: they spread into trains of rings, travel at real speeds, and fade the way they do in a pond. A finger dragged through the water leaves a proper wake.
  • Light that's computed, not painted. Sunlight is traced through the moving surface to draw the bright web of caustics on the pond floor. The water absorbs colour with depth, and everything casts soft shadows.
  • Creatures with behaviour. Koi wander, rest, startle, dive and rise to the surface. Axolotls walk with a salamander's gait, swim, and come up for air. Both react to taps.
  • Light enough for any page. One canvas, no dependencies, about 33 KB gzipped.

Install

npm install pondscape

Use it

Any page

<canvas id="pond" style="width: 100%; height: 100vh"></canvas>
<script type="module">
  import { createPond } from "pondscape";

  const pond = createPond(document.getElementById("pond"), {
    fish: 6,
    axolotls: 2,
  });
</script>

The canvas can be any size; the pond fills it and follows it when it resizes. Call pond.destroy() when you remove it.

React

import { Pond } from "pondscape/react";

export function Hero() {
  return (
    <div style={{ height: "100vh" }}>
      <Pond options={{ fish: 6, axolotls: 2 }} fallback={<p>Your browser can't show the pond.</p>} />
    </div>
  );
}

<Pond> fills its parent. It's a client component (it carries "use client"), so it works in the Next.js App Router as is.

| Prop | | | --- | --- | | options | Any of the options below. Read once when the pond mounts; give it a new key to start over with new options. | | onReady(pond) | Called with the pond as soon as it's created, e.g. to make ripples yourself or pause it while it's off screen. May return a cleanup function. | | fallback | Shown instead of the pond on devices that can't run it. | | className, style | Passed to the canvas. |

Options

| Option | Default | | | --- | --- | --- | | fish | 6 | The koi: a count, in a mix of varieties, or a list of fish. Up to 16. | | axolotls | 2 | The axolotls: a count, in a mix of morphs, or a list of axolotls. Up to 8. | | lilies | 9 | Lily pads on the surface. | | flowers | 3 | Water lilies blooming on the pads. | | stones | 6 | River stones on the pond floor. Up to 16. | | grass | 5 | Clumps of grass in the shallows. | | seed | 1 | Lays out the pond: stones, plants, where creatures start, their patterns. The same seed always gives the same pond. | | waves | 0.4 | Strength of the gentle waves that are always moving. 0 is still water. | | size | 0.8 | How many metres of pond the canvas's shorter side shows. Ripples move at real speeds, so this sets how fast they cross the screen. | | depth | 0.25 | Pond depth, as a fraction of the canvas height. | | interactive | true | Ripple and startle creatures when the pond is tapped or dragged across. | | quality | "high" ("medium" on touch devices) | "low", "medium" or "high": the detail of the surface and light. | | maxPixelRatio | 2 | Cap on device pixel ratio, to keep large screens fast. | | palette | | Colours, any of: bed (the floor), water (what white looks like through half a pond of it), murk (light scattered by the water), sky (reflected in it). Hex strings. |

Koi

createPond(canvas, {
  fish: [
    { variety: "kohaku" },
    { variety: "tancho", length: 0.24 },
    { variety: "karasu" },
  ],
});

| Field | | | --- | --- | | variety | "kohaku", "sanke", "showa", "tancho", "ogon", "platinum" or "karasu". Patterned varieties get a pattern of their own from the pond's seed. | | length | Body length in metres, without the tail. Default 0.18 to 0.26. | | mark | A custom marking on the head (see below). |

Custom marks

Give a koi its own mark on the head: a shape drawn as a natural colour patch, with a softly wandering edge. On a tancho it takes the place of the round red spot.

{
  variety: "tancho",
  mark: {
    // SVG path data in a 100 × 100 box. The top edge points to the snout.
    path: "M50 12 L84 50 L50 88 L16 50 Z", // a diamond
    colour: "#c8321a", // default: koi red
    strength: 0.9,     // 0 to 1; lower blends it into the pattern
    // stroke: 12,     // draw the path as a line this wide instead of filling it
  },
}

Axolotls

createPond(canvas, {
  axolotls: [{ morph: "leucistic" }, { morph: "golden", length: 0.22 }],
});

| Field | | | --- | --- | | morph | "leucistic", "golden", "wild", "copper" or "melanoid". | | length | Length in metres, snout to tail tip. Default 0.18 to 0.23. |

The pond object

createPond() returns, and onReady receives:

| | | | --- | --- | | ready | A promise that resolves when the first frame is drawn. The shaders compile in the background first, which can take a moment the first time a browser sees them; until then the canvas is hidden, so whatever is behind it shows. Rejects if they fail to compile. | | ripple(x, y, { strength }) | Makes a ripple at a point, in CSS pixels from the canvas's top-left. strength: 1 is a fingertip tap. | | pause(), resume() | Stop and restart the animation, e.g. while the pond is scrolled out of view. | | fps | Frames per second, averaged over the last second. | | canvas | The canvas it draws into. | | destroy() | Stops the pond and frees its GPU memory. |

Also exported: isPondSupported(), defaultPalette, koiVarieties, axolotlMorphs, and the TypeScript types for everything above.

Browser support

Any browser with WebGL2 that can render to floating-point textures: current Chrome, Edge, Firefox and Safari (iOS 15 and later). Check with isPondSupported(), or use the React component's fallback. createPond() throws on devices that can't run it.

License

MIT