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

@base-org/eslint-plugin-bds

v0.2.0

Published

ESLint rules and a CI check (bds-lint) that check Base products use BDS fonts and colours from @base-org/bds-tokens.

Readme

@base-org/eslint-plugin-bds

ESLint rules that check Base products use BDS tokens: colours, spacing, fonts and the type scale from @base-org/bds-tokens. The rules read Tailwind classes in className, in class helpers such as cn() and cva(), and literal values in style={{ … }}.

yarn add -D @base-org/eslint-plugin-bds

Works with ESLint 8 (.eslintrc) and ESLint 9 (flat config). Every rule is a warning in the recommended and strict presets, so adding the plugin never blocks a build. To block a pull request on fonts and colours, run bds-lint in CI.

The CI check: bds-lint

bds-lint is one check for BDS fonts and colours. It runs these rules as errors: no-raw-color, valid-color-token, no-tailwind-palette, text-gray-contrast, font-family, type-scale and font-weight. It uses the repo's ESLint (8.57 or later) but ignores the repo's ESLint config and its disable comments, so the result depends only on the code and the plugin version.

yarn add -D @base-org/eslint-plugin-bds eslint @typescript-eslint/parser
npx bds-lint src app

Exit codes: 0 clean, 1 font or colour problems, 2 could not run (a file that doesn't parse, a path with no files, no ESLint). 2 is never a pass. --format json prints ESLint's JSON report.

In GitHub Actions, as its own step so it can block on its own:

- name: BDS fonts and colours
  run: npx bds-lint src app

To adopt it in a repo with existing problems, list the folders to skip for now in bds.config.json, in the working directory, and remove them as they're cleaned up. settings takes the same keys as settings.bds below.

{
  "ignores": ["app/(legacy)/**"],
  "settings": { "allowClasses": ["text-sm"] }
}

In an ESLint config, the same rules as errors are the check and flat/check presets.

Setup

ESLint 9, eslint.config.mjs:

import bds from '@base-org/eslint-plugin-bds';

export default [
  bds.configs['flat/recommended'],
];

ESLint 8, .eslintrc.js:

module.exports = {
  extends: ['plugin:@base-org/bds/recommended'],
};

Presets

| Preset | Rules | | --- | --- | | recommended / flat/recommended | no-raw-color, valid-color-token, no-tailwind-palette, text-gray-contrast, font-family, type-scale, font-weight | | strict / flat/strict | All of recommended, plus prefer-semantic-color and spacing-scale | | check / flat/check | The recommended rules as errors. bds-lint runs these |

The recommended rules only suggest spectrum classes (bg-bds-gray-0), which every BDS install has. strict adds the rules that only fit some repos: semantic roles need the BDS token stylesheet, and the spacing grid waits on layout steps in the token scale before it moves to recommended.

Rules

Most fixes are offered as editor suggestions, not --fix, because a person should check the colour is right for its place.

no-raw-color

No raw hex, rgb() or hsl() colour in arbitrary classes (bg-[#0000ff]) or style values. When the colour is exactly a BDS token, the rule names it and suggests the spectrum class or variable: bg-[#ffffff] → bg-bds-gray-0. Base Blue suggests its brand roles instead of base-blue: text-[#0000ff] → text-bds-brand, bg-[#0000ff] → bg-bds-bg-brand.

valid-color-token

*-bds-* classes and var(--bds-…) variables must name a token that exists, so a typo such as text-bds-fg-mutted doesn't silently render with no colour. Suggests the closest name when only one is close. Only colour names are checked, so text-bds-body, shadow-bds-sm and a component's own --bds-* variables pass.

no-tailwind-palette

No Tailwind default colours (bg-white, text-gray-900, border-blue-500). Use a BDS colour class instead. Repos that map their own palette onto BDS colours can allow it with allowClasses.

text-gray-contrast

No text in gray-40 or lighter on a light background. fg-muted (gray-50) is the lightest text colour. Classes under dark:, disabled states (disabled:, data-disabled:) and white text (gray-0, for dark or brand fills) are left alone.

font-family

Type is set in Base Sans or Base Sans Mono: font-sans, font-mono, or var(--font-sans). Flags font-serif, other families in font-[…], and fontFamily in style.

type-scale

Type comes from a BDS type scale class (text-bds-body, text-bds-title-1, text-brand-headline), which sets size, line height and weight together. Flags Tailwind's default sizes (text-sm, text-2xl, text-lg/7), arbitrary sizes (text-[18px], text-[larger]), leading-[…] and tracking-[…], and fontSize, lineHeight and letterSpacing in style. In style, only a BDS type token passes, as the whole value: var(--text-bds-body) or var(--text-bds-body--line-height). Colours in text-[…] and named steps such as leading-6 are left alone. A repo with its own type classes can allow them with allowClasses.

font-weight

Base Sans in BDS is set in one weight: 400 (font-normal). Flags every other weight class (font-light, font-medium, font-bold, font-thin), font-[300], font-[600] and font-[number:600], and other fontWeight values in style. A type token's weight, var(--text-bds-body--font-weight), passes.

prefer-semantic-color (strict)

Prefer a semantic role over the spectrum step it matches in light mode: bg-bds-gray-0 → bg-bds-bg-primary. A spectrum step stays the same in dark mode; the role switches. Skipped when the class list already sets a dark: value. Needs the BDS token stylesheet, which defines the role classes.

spacing-scale (strict)

Padding, margin and gap stay on the 4px grid: step 1 of the BDS spacing scale, and one Tailwind step on web. The BDS steps 0.5 (2px) and 1.5 (6px) also pass. There is no upper cap, because the token scale stops at 40px and has no layout steps yet, so py-16 (64px) is fine. Flags px-3.5 (14px), m-[13px] and style={{ marginTop: 7 }}. Suggests the class for an arbitrary value on the grid: pt-[12px] → pt-3, py-[4rem] → py-16.

Settings

Set per repo under settings.bds:

settings: {
  bds: {
    // Functions whose string arguments are class lists.
    // Default: cn, clsx, classnames, classNames, cx, twMerge, twJoin, cva, tv
    callees: ['cn', 'classNames'],
    // Classes every rule accepts: exact names, or /regex/ strings. Variants are ignored.
    allowClasses: ['/^(bg|text|border)-blue-\\d+$/'],
    // Raw colours no-raw-color accepts.
    allowColors: ['#0000ff'],
    // Font families font-family accepts besides Base Sans and Base Sans Mono.
    allowFonts: ['Coinbase Display'],
  },
},

Token data

The rules read src/generated/tokens.json, built from packages/tokens. The plugin ships this copy because ESLint 8 loads plugins with require() and @base-org/bds-tokens is ESM-only. Both packages release together at the same version.

After changing tokens, regenerate it:

yarn workspace @base-org/eslint-plugin-bds generate:tokens

A test fails when the copy and packages/tokens differ.