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

@nbot/flowers

v0.2.0

Published

Deterministic, dependency-free botanical SVG flowers. One seed, one flower, the same everywhere, forever.

Readme

flowers

Procedural botanical SVGs, grown from a seed. Hand it a string and you get an SVG flower; the same string grows the same flower on any machine. The point is determinism: a flower can be regrown from its seed instead of stored.

Deterministic, dependency-free, isomorphic. One species today, a five-petaled plumeria; the vocabulary is built so others can grow beside it.

Install

pnpm add @nbot/flowers

Usage

import { cultivar, plumeria } from "@nbot/flowers";

const svg = plumeria({ seed: "2026-06-14" });
const name = cultivar({ seed: "2026-06-14" }); // "pink pearl", "rainbow × gold", ...

plumeria returns a complete <svg> string. It renders the same flower on the server and in the browser, with no dependencies to carry along.

Design

The pinwheel. A real plumeria overlaps like a pinwheel: every petal covers one neighbor and slips under the other, all the way around, which no single draw order can close. The renderer draws the five petals, then redraws the first clipped inside the last (render.ts, the wedge). The sliver restores the missing overlap, contact shadow included.

Petals (petal.ts). Each petal is a Beta kernel t^a·(1-t)^b offset along the normal of a parabolic midrib. The covering flank is broad, the tucked flank slim, different exponents per side. The midrib's parabola is emitted as an exact quadratic Bézier (control point (0, -L/2)); the outline is Catmull-Rom converted to cubics, sampled densest where the kernel curves hardest. Each petal is born already upright: its lean is the phase of the corolla's fifth harmonic, the exact measure of how far a five-fold figure is turned, so one petal stands skyward and the star needs no correction downstream.

Genomes (genome.ts). A flower is a sampled genome: one of eight cultivar recipes, modeled on real frangipani (Celadine, Rainbow, Pink Pearl, Sunset, Fuchsia, Gold, Candy Stripe, Carmine), or, some days, a hybrid of two, printed at a per-bloom exposure (pale and milky through deep and saturated). Recipes are spans in OKLCH; every sampled tone stays in the perceptual neighborhood of its cultivar.

Color (color.ts). All mixing happens in OKLCH with shortest-arc hue, so a gold-to-pink ramp passes through warm orange instead of grey. Gradient stops are sampled along OKLCH geodesics and converted to hex only at the edge of the system, gamut-mapped by walking chroma down.

No outlines. Petals separate the way photographs do: a double contact shadow under every covering edge (crisp line opening into penumbra), a thin rim of light on the waxy edge, and one key light from the top left, cast as a per-petal gradient so the corolla reads as a rounded dome instead of five flat cut-outs. Pale cultivars, which would melt into light paper, also take a soft inner shadow along the free edge. A radial mask fades the contact shadows near the hub, so the center stays lit instead of falling in its own shade.

The throat. Two registers: a steady shared core, plus a flame ellipse per petal so the gold reads as a star, its edge torn into tongues by per-petal turbulence displacement. A warm glow pools at the hub and bleeds up each petal, so the heart reads lit from within. Vein fans die into the body before the rim, fine radial fibers weave an iris-like texture, and an anisotropic grain runs lengthwise like real petal striations.

The grade. A final pass over the whole flower, the way a phone's auto mode balances a shot: a gentle contrast curve plus a touch of saturation and luminance, so the corolla reads with depth instead of flat and pale. It is softened on pale cultivars, whose near-white petals a full lift would blow into the background.

The moon (moon.ts). Pass a date and the moon of that day is arithmetic on it (one known new moon and the synodic month). Full-moon blooms come out paler and silvery.

Bloom. The SVG can carry its own entrance: petals unfurl around the hub with a staggered fade, honoring prefers-reduced-motion. It is opt-in (bloom: true); the default is the settled flower, which is what static rasterizers and favicons want. The petal group ids (<uid>g0 to <uid>g4) are exposed, so a different entrance can be driven from outside.

Glow. By default the flower carries no backdrop, since a library should not assume the surface it lands on. Pass glow: true and it rests on a soft ground: a warm shade on paper, a faint throat-colored halo on dark. Presentation is opt-in, like the animation.

Theming. Light and dark are the same geometry, re-toned. Both themes lift chroma so the colors read vivid, the light theme more, since warm paper washes pale petals out by simultaneous contrast. Element ids embed the theme, so two flowers of the same seed can share one document and url(#...) still resolves the right one.

API

plumeria(options): string   // a complete <svg> document
cultivar(options): string   // the name of the flower that seed grows

| option | type | default | | | --- | --- | --- | --- | | seed | string | | identity; same seed, same flower | | date | string? | undefined | ISO day; the moon of that day pales the bloom | | bloom | boolean? | false | true adds the opening animation | | glow | boolean? | false | true rests the flower on a soft ground glow | | theme | "light" \| "dark" | "light" | re-tones, never restructures | | size | number? | 480 | width/height attributes; viewBox is always 480 |

The contract, locked by tests: deterministic per (seed, theme); structure identical across themes; ids disjoint across themes; every url(#...) reference defined in-document; numerically sound and comfortably under 48 KB.

Layout

src/
  shared/
    color.ts    OKLCH to sRGB, perceptual mixing
    prng.ts     xmur3 + sfc32, deterministic randomness
    moon.ts     lunar phase from the date
  plumeria/
    genome.ts   cultivar recipes and sampling
    petal.ts    petal geometry
    bloom.ts    the opening animation, opt-in
    render.ts   composition: layers, shadows, svg

shared knows nothing of any one flower; a second species lives beside plumeria, reuses shared, and never touches it.

License

MIT