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

@forumone/throughline-design-contract

v0.2.0

Published

The contract every AI-ready design system satisfies to be consumable by Throughline.

Readme

@forumone/throughline-design-contract

The contract every AI-ready design system satisfies to be consumable by Throughline.

What this package provides

  • ComponentContractSchema — the Zod schema for per-component metadata (intent, composition rules, content fields, tokens, accessibility, examples).
  • ManifestSchema — the aggregated JSON format a design system publishes, versioned via contractVersion.
  • loadManifest / loadManifestFromUrl — runtime loaders with strict validation and a readable error format.
  • lintManifest (via the /lint subpath) — CI-runnable consistency checks for design system repos.

Zero runtime dependencies beyond Zod. Safe to import into client apps, design systems, and server packages alike.

Installation

pnpm add @forumone/throughline-design-contract

Authoring contracts in a design system

Each component has a co-located contract file:

src/components/Hero/
├── Hero.tsx
├── Hero.stories.tsx
├── Hero.contract.ts
└── index.ts

Hero.contract.ts exports a single object that satisfies ComponentContract:

import type { ComponentContract } from '@forumone/throughline-design-contract'

export const contract: ComponentContract = {
  name: 'Hero',
  category: 'hero',
  description: 'A page opener with a headline and optional call-to-action.',
  intent:
    'Used to establish what a page is about within the first viewport. Appropriate for top-level pages that need editorial framing.',
  composition: {
    placement: ['page'],
    maxPerPage: 1,
    requiredSiblings: [],
    forbiddenAdjacent: ['Hero'],
  },
  content: {
    fields: [{ name: 'headline', type: 'text', required: true, maxLength: 80 }],
  },
  tokens: { consumes: ['color.brand.primary'] },
  accessibility: {
    keyboardSupport: [],
    screenReaderBehavior: 'Headline is announced as h1 by default.',
    contentWarnings: [],
  },
  examples: [{ label: 'Default', intent: 'Standard page opener', storyId: 'hero--default' }],
  antiExamples: [
    { label: 'Stacked heroes', why: 'Breaks the visual rhythm.', useInstead: 'Section' },
  ],
}

Your design system's build tooling aggregates these into a Manifest. See the reference design system for a canonical example.

Loading a manifest at runtime

import { loadManifest } from '@forumone/throughline-design-contract'
import manifest from '@my-company/design-system/manifest.json'

const loaded = loadManifest(manifest)

const hero = loaded.requireComponent('Hero')
console.log(hero.intent)

for (const name of loaded.listByCategory('card')) {
  console.log(name)
}

Invalid manifests throw immediately with a path-qualified error message. The loader never partially loads invalid data.

Loading over HTTP

import { loadManifestFromUrl } from '@forumone/throughline-design-contract'

const loaded = await loadManifestFromUrl('https://ds.example.com/manifest.json')

Linting in CI

Every design system should lint its own manifest before publishing. Import the lint helpers from the /lint subpath:

import { lintManifest, formatLintIssues } from '@forumone/throughline-design-contract/lint'
import manifest from './dist/manifest.json'

const issues = lintManifest(manifest, {
  availableStoryIds: new Set(/* collected from storybook-static */),
})

if (issues.some((i) => i.severity === 'error')) {
  console.error(formatLintIssues(issues))
  process.exit(1)
}

lintManifest checks:

  • Every requiredSiblings and forbiddenAdjacent entry references a real component in the manifest.
  • Every token in tokens.consumes exists in the manifest's token table (or in availableTokens if you pass one).
  • Every example's storyId exists in availableStoryIds (skipped when the option is omitted).
  • Warnings: components with no anti-examples; intent statements shorter than 50 characters.

assertManifestClean(manifest, options) is the CI-friendly form: throws on any error, silent on warnings-only.

Versioning

The current contract version is 1.0.0, exported as CONTRACT_VERSION. Manifests declare it via the contractVersion field; the loader rejects mismatches so Claude never recommends a component from a schema it does not understand.

When the contract evolves, this package ships a new major version with migration guidance in the changelog.

Relationship to Storybook AI manifests

Storybook ships its own AI manifest format (/manifests/components.json). It is a static-analysis artifact that describes what exists in a Storybook — component ids, paths, props with types and JSDoc, story ids, import statements. Storybook marks it as preview / unstable.

This package's contract describes what's appropriate — intent, composition rules, accessibility expectations, anti-examples, token consumption. Hand-authored, stable, versioned.

They complement rather than overlap. Typical integration: during a design system's CI, parse Storybook's components.json, collect every stories[].id, and pass the set to lintManifest as availableStoryIds. That gives you the "does this storyId resolve to a real story?" check for free:

import storybookManifest from './storybook-static/manifests/components.json'
import contractManifest from './dist/manifest.json'
import { lintManifest } from '@forumone/throughline-design-contract/lint'

const availableStoryIds = new Set(
  Object.values(storybookManifest.components).flatMap((c: { stories: Array<{ id: string }> }) =>
    c.stories.map((s) => s.id),
  ),
)

const issues = lintManifest(contractManifest, { availableStoryIds })

Related packages

  • @forumone/throughline-reference-ds — a reference design system that satisfies this contract (C3).
  • @forumone/throughline-components — the Component Server MCP that consumes manifests (C5).
  • @forumone/throughline-plugin-contract — the plugin contract for packages that extend Payload.