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

seedicon

v0.1.0

Published

Deterministic SVG avatars generated from any string seed (wallet address, UUID, user id) — no image storage, no uploads.

Readme

seedicon

Deterministic SVG avatars generated from any string — a wallet address, a UUID, a user ID, an email. Same seed in, same avatar out, every time, forever. No image storage, no uploads, no CDN.

npm install seedicon

Why

If you let users upload a profile picture, you also have to store it, resize it, moderate it, and serve it. Most apps don't need any of that — they need something in the avatar slot that's consistent and looks intentional. seedicon generates that something on the fly from a seed you already have, so the only thing you store is a string (or nothing at all, if you just derive it from the user's id every time you render).

Usage

import { generateAvatar } from "seedicon";

const svg = generateAvatar({ seed: "0xba32...eD56" });
// '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" ...>...</svg>'

svg is a plain string — write it to a file, inject it with innerHTML, or embed it as a data URI:

import { generateAvatarDataUri } from "seedicon";

const src = generateAvatarDataUri({ seed: user.id });
// '<img src="data:image/svg+xml,..." />'

Options

generateAvatar({
  seed: "anything",              // required — the only thing that determines the output
  style: "pixels",               // see the list below — default "pixels"
  size: 64,                       // SVG width/height in user units — default 64
  radius: 0,                      // corner radius, e.g. 12 for rounded, size/2 for a circle — default 0
});

Nine styles, pick whichever fits your product (or let users pick).

Three of them are output-compatible with an existing library — the same seed produces the exact same image, so you can swap the library out without changing anybody's avatar:

| Style | What it looks like | Compatible with | | --- | --- | --- | | pixels | Mirrored pixel grid, the wallet-avatar classic | blockies | | jdenticon | Geometric shapes with four-fold rotational symmetry | Jdenticon | | stellar | 7×7 mirrored bit grid, the "space invader" look | stellar-identicon-js (for real Stellar addresses) |

The other six are seedicon's own:

| Style | What it looks like | | --- | --- | | identicon | Five symmetric rows of pixels — the classic dev-tool identicon | | ring | Concentric rings in seed-derived colors and thicknesses | | lifehash | An organic pattern grown with a Game of Life automaton | | marble | Two soft, blurred organic blobs over a flat color | | waves | Layered wave bands in shades of a single hue | | gradient | A soft two/three-color diagonal gradient |

Importing a single style

The package root resolves styles by name, so it has to reference all nine and no bundler can drop the ones you never call. If you only use one style, import it directly and you get that renderer plus the shared core — nothing else:

import { ring, ringDataUri } from "seedicon/ring";

const svg = ring({ seed: user.id, size: 40, radius: 20 });

Every style has an entry point named after it: seedicon/pixels, seedicon/identicon, seedicon/jdenticon, seedicon/stellar, seedicon/ring, seedicon/lifehash, seedicon/marble, seedicon/waves, seedicon/gradient. The <Avatar> component takes style names, so it pulls in all nine — if bundle size matters more than the convenience, call the single-style function and render the markup yourself.

React

import { Avatar } from "seedicon/react";

<Avatar seed={user.walletAddress} style="pixels" size={40} />;

Unlike canvas-based generators, this renders synchronously to SVG — no useEffect + ref dance, no flash of an empty avatar, and it works during server-side rendering (Next.js, Remix, etc.) because there's no canvas or window involved. react is a peer dependency and only needed if you import from seedicon/react.

Database

Store the seed you already have (a user id, a wallet address) and call generateAvatar at render time — nothing to persist. If you'd rather store a ready-to-use value (e.g. because you want to let the style be changed independently of re-deriving it), a plain string column works fine too:

// on signup
user.image = "pixels"; // or generateAvatarDataUri({ seed: user.id, style: "pixels" })

// on render
<Avatar seed={user.id} style={user.image /* any style name */} />

Migrating from blockies

The pixels style is a port of the blockies algorithm, verified against @download/blockies cell-for-cell and color-for-color. Swapping the libraries does not change a single avatar:

- import { createIcon } from "@download/blockies";
- const canvas = createIcon({ seed: address, size: 8, scale: 8 });
- ref.current.appendChild(canvas);
+ import { Avatar } from "seedicon/react";
+ <Avatar seed={address} size={64} />

What you gain is that it renders during SSR: no <canvas>, no DOM ref, no useEffect, no flash of empty avatar on first paint.

One thing to watch: casing. An Ethereum address exists in two forms — lowercase (0xba32…ed56) and checksummed (0xBa32…eD56) — and they are different strings, so they produce different avatars. blockies behaves the same way; it does not normalize either. Whatever your app passes today, keep passing exactly that, or normalize once at the edge:

<Avatar seed={address.toLowerCase()} />

seedicon deliberately does not lowercase for you: usernames and emails are seeds too, and Maria should be free to differ from maria.

Determinism

seedicon has no randomness and no I/O. The same { seed, style, size, radius } always produces byte-for-byte identical SVG markup, on any platform. It's not a cryptographic hash — don't use it for anything security-sensitive — it only needs to spread seeds out visually, which a fast 32-bit hash does well enough.

Credits

Three styles are ports. Their algorithms are not ours, and the test suite compares seedicon's output against the original packages on every run so compatibility cannot quietly drift:

  • pixelsblockies by Erin Dachtler and Alex Van de Sande (MIT).
  • jdenticonJdenticon by Daniel Mester Pirttijärvi (MIT).
  • stellarstellar-identicon-js by Lobstrco (ISC). Real Stellar public keys are decoded exactly as the original does; any other seed falls back to a SHA-1 digest, since an arbitrary string has no key bytes to read.

Each was reimplemented to emit SVG rather than paint to a canvas — that is the part seedicon adds, and it is why these work during SSR.

The remaining styles are original implementations, inspired by:

  • identicon and waves — the styles of the same name in DiceBear (created by DiceBear, CC0 1.0).
  • lifehashLifeHash by Blockchain Commons (BSD-2-Clause). Same mechanism — a Life automaton colored by how long each cell survived — at a fraction of the size.
  • ring and marble — the themes of the same name in Boring Avatars.

License

MIT