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

memphisify

v1.0.2

Published

Turn backgrounds into geometric patterns

Readme

memphisify

Scatter Memphis-style confetti shapes across any element. Zero dependencies, vanilla JS.

Memphisify fills any DOM element — buttons, headings, hero sections, card backgrounds — with a randomly scattered field of geometric shapes. Configure it declaratively with data-* attributes or drive it from code, and export the result as a crisp SVG or PNG.

<div
  data-memphisify
  data-colors="#FF3B6B,#FFC23B,#3BD4FF,#7B5CFF,#33D685"
  data-background="#15131C"
  data-density="9"
  data-size="8"
  data-overlap="true">
</div>

Install

npm install memphisify
pnpm add memphisify
yarn add memphisify

Or drop it in from a CDN:

<script src="https://unpkg.com/memphisify"></script>

Quick start

Declarative (auto-init)

Tag any element with data-memphisify and Memphisify fills it on page load:

<section
  data-memphisify
  data-colors="#FF3B6B,#3BD4FF,#7B5CFF"
  data-background="#15131C"
  data-density="12"
  data-size="14">
  <h1>Celebrate</h1>
</section>

<script type="module">
  import 'memphisify/auto';
</script>

memphisify/auto scans the document for [data-memphisify] elements, fills each from its attributes, and re-scatters on resize.

Programmatic

import { memphisify } from 'memphisify';

const el = document.querySelector('#hero');

const instance = memphisify(el, {
  colors: ['#FF3B6B', '#FFC23B', '#3BD4FF', '#7B5CFF', '#33D685'],
  background: '#15131C',
  density: 9,
  size: 8,
  overlap: true,
});

// Re-scatter (e.g. on click) for a fresh random layout
el.addEventListener('click', () => instance.scatter());

// Tweak any option live
instance.update({ density: 20, size: 12 });

// Tear down — removes generated shapes and listeners
instance.destroy();

Options

| Option | Attribute | Type | Default | Description | |--------------|--------------------|-----------------------|---------------|-------------| | colors | data-colors | string[] / CSV | 5-color set | Hex colors picked at random per shape. As an attribute, pass a comma-separated list. | | background | data-background | string (hex) | #15131C | Fill color painted behind the shapes. Use transparent to skip it. | | density | data-density | number | 9 | Shapes per 10,000 px² of the element's area. The shape count scales with the box, so the texture stays consistent at any size. | | size | data-size | number (px) | 8 | Base footprint of each shape, in pixels. | | overlap | data-overlap | boolean | true | true lets shapes overlap freely. false uses rejection sampling so no two shapes sit closer than one footprint apart. |

Each shape is a randomly generated triangle (constrained so it never collapses into a thin sliver), placed at a random position with a random rotation and a subtle opacity variation for a hand-scattered feel.

Note on overlap: false — when the box is too crowded to fit every shape without collisions, Memphisify places as many as it can and stops, rather than looping forever. Lower the density or size if you need a guaranteed count.


Export

Render a field to a standalone image without touching the DOM:

import { toSVG, toPNG } from 'memphisify';

// SVG string
const svg = toSVG({
  width: 1000,
  height: 1000,
  colors: ['#FF3B6B', '#3BD4FF', '#7B5CFF'],
  background: '#15131C',
  density: 9,
  size: 8,
  transparent: false,   // omit the background rect
});

// PNG Blob (browser only)
const blob = await toPNG({ width: 500, height: 500, transparent: true });

| Option | Type | Default | Description | |---------------|-----------|---------|-------------| | width | number | — | Output width in px (required). | | height | number | — | Output height in px (required). | | transparent | boolean | false | Skip the background rect so the shapes sit on transparency. |

All the standard colors / background / density / size / overlap options apply here too.


Recipes

A confetti-filled button

<button data-memphisify data-size="6" data-density="14" data-background="#15131C">
  <span>Ship it</span>
</button>

Sparse, large shapes on a light canvas

memphisify(card, {
  colors: ['#1B1B1F'],
  background: '#F4F2EC',
  density: 2,
  size: 90,
  overlap: false,
});

Text clipped to a confetti fill — render to SVG, set it as a background-image, and clip it to the glyphs:

.headline {
  background-image: var(--memphis-svg);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

Accessibility

Confetti is decorative — keep it from fighting your content:

  • Maintain enough contrast between any text and the background. WCAG asks for at least 4.5:1 for body text and 3:1 for large text and UI shapes.
  • Where shapes sit behind copy, render text in a contrast-safe color layered above the field, rather than relying on the shapes to stay out of the way.
  • Never use color alone to convey meaning.
  • Generated shapes are inert (aria-hidden by default) so screen readers skip them.

Browser support

Works in all modern browsers. Uses clip-path, CSS custom properties, and the Canvas API (for toPNG). No build step or polyfills required.


License

MIT © Gabriel Ardèvol