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

endgrain

v0.1.1

Published

Deterministic growth-ring identicons: every string grows its own tree.

Readme

endgrain

Identicons that grow. Every string becomes a tree, and the picture is the cut through its trunk: growth rings, heartwood and sapwood, bark, and the occasional drying crack.

five names, five trees

npm install endgrain
import { endgrain } from 'endgrain'

endgrain('ada')                          // '<svg …>' — a log, 256 px
endgrain('ada', { shape: 'circle', size: 64 })

Same string, same tree, on every machine. No dependencies. Runs in Node and in the browser.

How a tree grows

Nothing here is drawn on top of a circle and wobbled. Each tree is grown one year at a time:

  • Climate. Ring width follows a slow random walk, so good and bad years come in runs, the way they do in real cores. Rings also narrow as the trunk gets wider.
  • Lean. Trees that lean lay down more wood on one side. Each seed picks a direction and how hard it leaned, so the pith usually sits off-centre.
  • Shape. A few low harmonics give the trunk its lumps. They drift a little each year, so the outline at the bark is related to, but not the same as, the one near the pith.
  • Rings never cross. Growth is added per direction, always positive, so the result is physically possible. There is a test for it.
  • Heartwood, bark, checks. The inner years darken into heartwood; a ragged bark closes it; some trees crack from the pith, and some split in from the bark.

Every trait comes from its own random stream. Pin the species or the age and the rest of the tree stays put:

one seed in six woods

Shapes

log shows the whole section. circle and square zoom in until only wood fills the frame, which reads better at avatar sizes.

log, circle and square

API

endgrain(seed, options?) → string

| option | default | | |--------------|----------------|---| | size | 256 | width and height of the SVG | | shape | 'log' | 'log', 'circle' or 'square' | | species | from the seed | oak, walnut, cherry, maple, pine, ash | | age | from the seed | number of rings, 3 to 200 (seeds pick 14 to 45) | | background | none | any CSS color, painted behind the wood | | title | true | include an accessible <title> describing the tree |

grow(seed, options?) → tree and render(tree, options?) → string

endgrain is these two in a row. grow returns plain data (rings, bark, checks, species), handy if you want to draw it some other way.

describe(tree) → string

A 30-year-old cherry with one heart check.

This is also what goes into the SVG's <title>, so screen readers get something better than "avatar".

Command line

npx endgrain quietwright > quietwright.svg
npx endgrain ada --shape circle --size 64 -o ada.svg
npx endgrain ada --describe

Demo

Open demo.html straight from disk. It's one file with the library inlined and needs no network. npm run demo rebuilds it from src/.

Notes

  • Output is around 25–45 KB of SVG, most of it ring paths. It gzips to about a third. If you serve many at once, cache them; they never change.
  • Releases are published from GitHub Actions with npm provenance, so each version on npm can be traced to the commit that built it.
  • The look is pinned by a test. A change to how trees grow is a minor version bump, because it changes everyone's avatar.

License

MIT