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

papercade

v0.2.0

Published

A pixel × hand-drawn design library. NES.css × Excalidraw, with a character in it.

Readme

papercade

A pixel × hand-drawn design library. Pixel-game UI (quest logs, XP bars, dialogue boxes, coin counters) fused with Excalidraw-style sketchiness (paper grain, ink strokes, hand-written notes) — one coherent system, unmistakably not a generic UI kit. Think NES.css × Excalidraw, with a character in it.

Live demo: https://anandparth.github.io/papercade/ — scroll it. The character walking down the page is the scroll indicator, inking his route behind him and stopping to talk. He is built from three shipped components and nothing else.

License: MIT (code) · CC BY 4.0 (art) · OFL (fonts)

Quick start

Two CDN tags, any HTML page, no framework required. The second one is only needed for the interactive elements:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/papercade.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/papercade.js"></script>

<body class="px-paper">
  <button class="px-btn px-btn--accent">recruit this unit</button>

  <div class="px-xp" role="progressbar" aria-valuenow="72" aria-valuemin="0" aria-valuemax="100">
    <span class="px-xp-fill" style="--px-xp: 72%"></span>
  </div>

  <px-avatar src="my-hero.webp" frames="6" rows="2" width="96" height="96" alt="My hero"></px-avatar>
</body>

Or from npm:

npm install papercade
import "papercade";            // the stylesheet
import "papercade/elements";   // registers <px-avatar> and friends (typed)

To hack on the library itself:

git clone https://github.com/anandparth/papercade
cd papercade
pnpm install
pnpm build        # tokens + css + fonts + art + element bundles -> dist/
pnpm watch        # rebuild on change, in one terminal
pnpm dev          # live demo at localhost:5844, in another

What's inside

| Layer | What | Status | |---|---|---| | Tokens | DTCG tokens/tokens.json → Style Dictionary → --px-* CSS custom properties (paper/ink palette, Excalidraw stroke+fill pairs, pixel motion curves) | ✅ | | Surfaces & type | .px-paper / .px-screen dot-grid surfaces, .px-mono HUD labels, .px-hand notes, .px-hl marker highlight | ✅ | | Static components | .px-frame pixel box · .px-btn sketch button · .px-card sketch card (build-time rough.js border) · .px-dialogue RPG dialogue · .px-note / .px-arrow annotation · .px-quest quest select · .px-chip HUD chip · .px-xp / .px-hp meters | ✅ 8 of 8 | | Custom elements | <px-avatar> bring-your-own-sprite-sheet mascot · <px-coin> collectible + shared wallet · <px-holo-card> foil tilt · <px-flipcard> two-face turn | ✅ 4 of 4 |

v1 ships exactly 12 components and stops. No generic form controls — your <select> is fine as it is. Every element is light-DOM and does as little as possible: the motion lives in CSS custom properties, so the markup still renders when the script does not.

Using & theming

  • Everything is prefixed px-. Components are plain classes; state is plain modifier classes (.is-gone, --screen, --accent).
  • All colors/fonts/motion come from --px-* custom properties — override any of them on :root or a subtree to retheme:
.my-zone { --px-color-accent: #e03131; --px-frame-color: var(--px-color-sketch-blue-stroke); }
  • Sounds (when they land) are opt-in everywhere — nothing plays audio by default.
  • Every animation respects prefers-reduced-motion.
  • Bundled fonts: Press Start 2P + Excalifont (both SIL OFL, license files ship in dist/fonts/). Keep pixel type at 16px+ (Press Start 2P is drawn on an 8px grid).

Your own mascot

<px-avatar> takes any uniform sprite grid — frames columns by rows rows. width/height are the cell size, so set both together to keep your sheet's aspect ratio. row picks the state (walk left, idle, celebrate — whatever your rows mean), fps sets the pace, paused holds the first frame, and alt makes it announced rather than decorative. It also exposes play(), pause(), and playing.

<px-avatar src="hero.webp" frames="6" rows="3" row="2" fps="10" width="96" height="96" pixelated></px-avatar>

Omit src and you get the bundled mascot (my pixel self, CC BY 4.0 — attribution required, see LICENSE-GRAPHICS). Your own sheet stays entirely yours; the component imposes no license on it. Playback is pure CSS, so the markup renders even if the script never loads.

Coins

<px-coin> banks its value (default 1) into one wallet shared by every coin on the site, persisted in localStorage and synced across tabs. Any element with data-px-coins becomes a live readout — pair it with .px-chip for the HUD look. Add sticky to keep a coin collectable forever, sound to opt that coin into a short blip (silence is the default, everywhere), and label to name it for screen readers. Each collect fires a bubbling px-collect event carrying { value, total }.

<px-coin value="5"></px-coin>
<span class="px-chip">coins <b data-px-coins>0</b></span>

Drive the wallet directly when you need to — coins.add(-10) is how you build a shop:

import { coins } from "papercade/elements";
coins.subscribe((total) => console.log(total));  // returns an unsubscribe

Cards

<px-holo-card> tilts toward the pointer and lights a foil sheen made from the library's own sketch palette; it writes --px-holo-x / --px-holo-y (−1 to 1) once per frame and CSS does the rest. The foil is four gradient stops plus a blend mode, so a new one is an override rather than a fork. Seven variants ship: --gold and --silver (multi-tone), --ice, --phosphor and --orchid (single hue), --soft (screen blend, gentler — combines with any of the others), and --matte (no foil or glare at all).

A single-hue foil is one declaration:

.my-foil { --px-holo-foil: #b2f2bb; }

For a spectrum, set the four stops individually — and --px-holo-angle to turn the bands:

.my-spectrum {
  --px-holo-foil-1: #7de2d1; --px-holo-foil-2: #ff8fab;
  --px-holo-foil-3: #c9f299; --px-holo-foil-4: #ffd6a5;
  --px-holo-blend: screen;   /* color-dodge is punchier, screen is gentler */
  --px-holo-angle: 135deg;
}

Pick colors that survive the blend. color-dodge computes base ÷ (1 − source), so over the near-black card only light, low-saturation colors stay metallic — pale fills clip one or two channels to white and glint. Saturated mid-tones and dark strokes lose all but one channel and go muddy: #5b3df5 lands on a dim #3529ff, while #b2f2bb becomes a vivid #71ff61. <px-flipcard> turns over on click or Enter, toggling a flipped attribute you can also set yourself; give it two .px-flipcard-face children (the second marked --back) and an aspect. Both are keyboard-operable and announced.

Extending

To add a component (the pattern the whole library follows):

  1. Create src/css/components/<name>.css — classes prefixed px-, all values from --px-* tokens, include a --screen dark preset and a reduced-motion-safe transition. Add a usage comment block at the top of the file.
  2. Register the file in the parts array in scripts/build.mjs (order matters: tokens → base → components).
  3. Add a demo section to site/index.html — the demo page is the visual test.
  4. pnpm build && pnpm dev and check both light and --screen variants.

New tokens go in tokens/tokens.json (DTCG format), never hardcoded in component CSS.

Contributing

Issues and PRs welcome. Ground rules: uniqueness over completeness (no generic components), accessibility is a feature not a chore (focus-visible, ARIA roles, reduced-motion paths are required, not optional), and no Nintendo assets, character names, or sound-alikes — this library evokes an era, not a company.

For AI agents

If you are an AI coding agent working in this repo: the token file tokens/tokens.json is the single source of truth for all design values; scripts/build.ts defines the CSS layer order; components live one-per-file in src/css/components/ with usage documented in the file's header comment; the demo page site/index.html doubles as the visual regression surface — every component change must be reflected there. All script/element code is strict TypeScript (pnpm typecheck must pass; no .js source files, no any); interactive elements ship bundled via Vite library mode with type declarations. Follow the four rules in the Extending section exactly. Do not add dependencies, do not add generic UI components, and do not remove prefers-reduced-motion or focus-visible handling.