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

kairos-design

v0.12.1

Published

The shared Kairos design system: tokens, component vocabulary, and formatters.

Downloads

3,184

Readme

Kairos Design

The shared implementation of the Kairos design system: one set of tokens, one component vocabulary, one money and date formatter, consumed by every Kairos surface instead of hand-rolled per app.

The kairos-branding skill describes intent. This repo is what is callable today, and where the two disagree, this repo wins.

What is here

| Artifact | Specifier | Contents | | --- | --- | --- | | Tokens | kairos-design/tokens.css | The --kairos-* custom properties, light and dark. The only file with raw hex in it. | | Vocabulary | kairos-design/kairos.css | The kairos-* class vocabulary, 220 classes. Consumes tokens only, no framework. | | Base | kairos-design/base.css | Element-level defaults. Opt-in, because a library that restyles a host app's bare table and input is invasive. | | Formatters | kairos-design/format/money, /format/dates | TTD 8,500.00 and 24 Aug 2026. One formatter, not five. | | React | kairos-design/react | Components emitting the classes above. Optional peer dependencies: radix-ui for anything that opens over the page, @tanstack/react-table for DataTable. | | Manifest | docs/kairos-ui.md | The canonical component list. Read it before building UI. | | Workshop | npm run storybook | Every component and every screen, both themes, four viewports. |

CSS first, React second, on purpose. Of the five Kairos surfaces, two run React (Paykit, Mailkit) and three do not: Uptime ships hand-written CSS with no bundler, Card is a single static HTML file, Mailclient is a Roundcube skin. A React-only package would reach two of five. The CSS reaches all five.

Seeing it

npm install
npm run storybook

Foundations first: colour, space, type, and the stamp, all read out of tokens.css itself so a specimen page cannot drift from the file it documents. Then every component. Then Screens, which is the part that matters — the same record list rendered as Mailkit, as Uptime, and as Paykit, side by side. Two apps can pass every component story and still look nothing alike, because looking alike is a property of the composition.

Everything below was found by rendering this package for the first time, and none of it was findable any other way:

  • kairos-table-panel painted no border, no ground, no radius, and no shadow, so every table the registry rendered had no container.
  • Five heading classes rendered in Bebas on any surface outside the app shell.
  • A panel heading rendered at 13px inside the shell, because the default it was overriding outranked it.
  • An app marking its current nav item with aria-current="page" got no active state.
  • A disabled input looked exactly like one you can type in.

The workshop is why those are past tense. See docs/decisions.md.

Consuming it

npm install kairos-design

Then import what you need. A bundler inlines the CSS into the app's own stylesheet at build time, so the tokens are in the first paint with no network request:

@import "kairos-design/tokens.css";
@import "kairos-design/kairos.css";
import { Button, DataTable } from 'kairos-design/react';
import { formatMoney } from 'kairos-design/format/money';

The React components and the formatters ship as TypeScript source, because the package has no build step. Next apps need the package in transpilePackages:

// next.config.js
export default { transpilePackages: ['kairos-design'] };

See docs/adoption.md for what each surface needs.

Surfaces with no bundler

Uptime, Card, and Mailclient cannot import anything, so they run kairos-design emit from a build script and gitignore what it writes:

kairos-design emit

The output is a build artifact. It is not committed, which is why there is nothing to check for drift.

Why a package rather than copies

Until 0.2.0 the artifacts were vendored: an app copied them in, committed the copies, and ran a check command in CI to catch a copy that had been edited or had fallen behind. That existed because the repo was private, and a private dependency cannot resolve in a Docker build that runs npm ci with no credentials — Paykit and Mailkit both build with build: . and COPY . ..

Making the repo public removes the constraint that produced all of it. A public package resolves in those builds with no secret, no BuildKit SSH forwarding, and no deploy key in CI. Nothing about the design system was confidential: it is a colour palette, 220 class names, and a Button.

What that bought, beyond deleting a CLI, a config file, a lockfile, and a drift checker:

An upgrade is a decision again. A version in package.json moves when someone bumps it. The old check compared each app against whatever commit the registry checkout happened to be on, so merging anything to the registry's main branch turned every app's CI red at once, and the prescribed fix — re-run sync — pulled in whatever else had landed alongside it.

Drift stops being possible rather than being detected. A file produced by a build, from a version fixed in package.json, cannot quietly disagree with its source. check was solving a problem that only existed because the copies were committed.

Copying was the wrong half of the shadcn model. Copying components into an app works because you own and edit the copies. This repo copied them and then failed the build if you edited one, which took on the duplication without the ownership.

The one thing genuinely lost is that tokens no longer reach a surface with no build step at all without running something. That is what emit is for, and it is three surfaces rather than five.

Working on this repo

Planned work is managed by OpenSpec. Four changes, 155 tasks:

openspec list                          # the changes and their task counts
openspec show <change>                 # proposal, specs and deltas
openspec validate --changes --strict   # before committing

Start at openspec/changes/README.md in the registered kairos-plans store. It says what each change is and which order they go in. Run openspec context from this repo to see the store's local path. The reasoning behind the changes is eight ADRs in docs/adr/; each change names the ones it implements.

Neither directory ships, nor does .claude/. files is an allowlist of dist, bin and docs/kairos-ui.md, and a test fails if that stops being true.

Contributing a component

  1. Read docs/kairos-ui.md. If the role is already there, extend it with a variant rather than adding a second component.
  2. Values come from tokens. A hex, a shadow offset, or a row height written into a component is a token in the wrong place.
  3. Add the manifest row in the same change. A component that is not in the manifest does not exist for the next agent.
  4. Export it from dist/react/index.ts. A component that is not reachable through the package entry point does not exist for a consuming app, and a test says so.
  5. If the change renames or retires a class, record it in docs/decisions.md with the reasoning.

npm test before every commit.