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

@tribulnation/ui

v0.5.0

Published

Tribulnation Labs shared design system: tokens, hash-driven light/dark/system + brand axes, logo marks, and font loading.

Readme

@tribulnation/ui

Shared design system for Tribulnation Labs sites: CSS tokens for the light/dark/system + brand (logo/palette/font) axes, the hash-driven state engine behind them, the mode switch, logo marks, and font loading.

First integrated into tribulnation/landing. Try it live via the interactive showcase at tribulnation.github.io/design/showcase, or grab static logo/lockup files from the brandkit.

The mark SVGs (src/lib/marks/*.svg) aren't hand-edited here — they're synced from /assets/marks (this repo's root, one level up) by scripts/sync-assets.mjs, which runs automatically as part of npm run package. If you're working on this package directly, run npm run sync-assets once after cloning (or after /assets/marks changes) so svelte-check/local dev have the files to import.

Install

npm install @tribulnation/ui

Usage

/* app.css or similar, imported once */
@import '@tribulnation/ui/tokens.css';
@import '@tribulnation/ui/marks.css';
<script lang="ts">
  import { onMount } from 'svelte'
  import {
    watchAxes,
    setAxis,
    setPersistedAxis,
    prefersColorSchemeResolver,
    ModeSwitch,
    FontLinks,
    Logo,
    type Axes
  } from '@tribulnation/ui'

  const config = {
    defaults: { logo: 'brush', palette: 'coral', mode: 'system', font: 'marker', 'logo-outline': 'none' },
    validValues: {
      logo: ['geo', 'brush', 'signal'],
      palette: ['coral', 'lime'],
      mode: ['dark', 'light', 'system'],
      font: ['system', 'inter', 'orbitron', 'audiowide', 'marker', 'sriracha'],
      'logo-outline': ['none', 'circle', 'square']
    },
    // mode remembers the user's last click in localStorage instead of the
    // hash — everyday toggling shouldn't rewrite the address bar. The hash
    // still overrides whenever present, e.g. for a QA/share link.
    persist: ['mode']
  }

  let axes: Axes = $state({ ...config.defaults })

  onMount(() => {
    const system = prefersColorSchemeResolver()
    return watchAxes({ ...config, system }, (resolved) => (axes = resolved))
  })
</script>

<FontLinks />

<Logo class="brand-logo" />

<ModeSwitch value={axes.mode as any} onchange={(v) => setPersistedAxis('mode', v)} />

Every axis is overridable via the URL hash for QA (e.g. #logo=geo&palette=lime&font=orbitron) — that always takes priority. Axes not listed in persist are written back to the hash by setAxis when changed (so the showcase's "Copy link" stays shareable); axes listed in persist (typically just mode) are written to localStorage by setPersistedAxis instead, so routine toggling doesn't touch the URL.

Brandkit

The full brandkit — mark, maskable icon, both lockups, and social cover images, each as SVG + PNG@512/2048, plus a "download everything" zip — ships under dist/brandkit/, generated at package-build time from the same /assets source as the GitHub Pages brandkit (scripts/build-brandkit.mjs invokes the repo-root scripts/build-brand.mjs with a redirected output dir). Every file is importable via the ./brandkit/* export, e.g.:

import markBg from '@tribulnation/ui/brandkit/mark/background.svg'
import zipUrl from '@tribulnation/ui/brandkit/tribulnation-brandkit.zip?url'

Consumers get Vite's normal asset pipeline for free — bump the package version, npm install, rebuild, done. No sync script, no committed copies.

What's in here, and what isn't

Included: design tokens, the axis-sync engine, the mode switch, logo marks, font loading, and the brandkit — the parts that are genuinely the same shape across sites.

Deliberately left out: page layout, nav/footer chrome, buttons, cards — those vary per site and would just bake one site's copy/structure into a "shared" package prematurely. Extract further only once a second real consumer shows what's actually reusable there.

Publishing

Bump version in packages/ui/package.json and push to main. .github/workflows/publish-ui.yml builds the package and publishes to npm whenever that version isn't already on the registry — no tagging step needed.

Publishing uses npm's Trusted Publishing (OIDC): the workflow requests a short-lived identity token from GitHub (id-token: write), and npm verifies it against the Trusted Publisher configured on the package (GitHub Actions, repo tribulnation/design, workflow publish-ui.yml, no environment) — no NPM_TOKEN secret to store or rotate.