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

@hub-kit/core

v0.4.76

Published

Shared pages, components and theme system for all Hub projects.

Readme

Hub Kit

One package that powers every Hub project. Pages, components and the theme system live here; each project supplies its data adapters, its dictionary, and one theme file.

Rules for working in this repo: see CLAUDE.md. The full plan: see docs/plan.md.

Install in a project

npm install @hub-kit/core

In the project's styles.css:

@import "@hub-kit/core/themes/default.css";
@source "../node_modules/@hub-kit/core/dist";

Use a component

import { QueueKpiRow } from "@hub-kit/core/invoice-queue";
import { NotificationBell, AlertList } from "@hub-kit/core/notifications";
import { Button, Table } from "@hub-kit/core/ui";

Use a page

Some screens still ship whole. A page needs one adapter the project implements, and takes optional labels for translation. English works out of the box.

New screens should not be built this way — see Build a list screen below. The route owns its layout and imports the parts; a whole page shared across four projects ends up carrying a prop for every difference between them.

import { ProcessingLogPage } from "@hub-kit/core/pages";
import { processingLogAdapter } from "../adapters/processing-log";

export function ActivityLog() {
  return <ProcessingLogPage adapter={processingLogAdapter} />;
}

The adapter interfaces are in hub-kit/adapters. Query hooks return a plain QueryResult shape, so the project implements them with React Query and Supabase; mutations are plain functions returning promises, so the project wraps its own writes and cache invalidation.

Build a list screen

Search, one Filter button holding every filter, chips for what is on, a period picker, sortable headers, two-line cells and a tooltip — all from one place, so a fix lands in every project at once.

import {
  SearchInput, FilterPopover, FilterPills, SortableColumnHeader, StackedCell, HintTooltip,
} from "@hub-kit/core/data-table";

Filters are declared once as a FilterField[], and the Filter button, its active count and the chips all read that one list, so they cannot disagree about what is filtering the screen.

The layout belongs to the project, the parts belong to the kit. The route writes its own header, tabs, toolbar and empty states, and imports the pieces — a rule table, a filter popover, a range calendar — from here.

Full instructions, including the filter kinds and the project wiring: docs/data-table.md.

Set up a new project

npx hub-kit init

This creates hub.config.mjs, src/hub/registry.tsx and a starter adapter, then prints the two CSS lines to add. Nothing is overwritten if the files already exist.

Add a guided tour

Tours are plain data the project owns. One object per page, keyed by the project's own route path:

import { TourProvider, TourButton, type TourDefinition } from "@hub-kit/core/tour";

const overviewTour: TourDefinition = {
  id: "overview",
  steps: [
    {
      target: "overview-money-cards",
      title: "Your figures at a glance",
      content: [{ kind: "paragraph", text: "Incoming and outgoing invoices for the period." }],
      showPlaceholderData: true,
    },
  ],
};

<TourProvider tours={{ "/overview": overviewTour }}>
  <Shell headerActions={<TourButton />} ...rest />
</TourProvider>

A tour opens by itself the first time a user lands on the page. Once it is skipped or finished it never opens by itself again; the Tour button always reopens it. Pages with no tour show no button. Target names are listed in docs/tour-guide.md.

Steps carry typed content blocks: paragraph, list, image, video, link, keyValueList and callout. The array order is the order on the card. Styling comes from the theme, so a project supplies content only.

A step with showPlaceholderData fills an empty page with sample values while the tour is open. Sample values come from a separate read-only adapter, so real data is never read through or written to.

Full instructions, including the target names each kit page offers: docs/tour-guide.md.

Generate route files

hub.config.mjs in the project root names the enabled pages:

export default {
  registryImport: "@/hub/registry",
  pages: [
    { component: "TeamPage", path: "/team" },
    { component: "NotificationsPage", path: "/benachrichtigungen" },
    { component: "ActivityLogPage", path: "/protokoll" },
  ],
};

Then:

npx hub-kit sync

This writes one thin route file per page. The project's src/hub/registry.tsx binds each kit page to its adapters and dictionary once.

Build this package

npm run build   # compiles src/ to dist/ with type declarations
npm run check   # type check only