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

@vertekum/ext-token-ramp

v0.3.15

Published

Vertekum extension: generate colour ramps from a single brand anchor — a fixed lightness ladder with chroma arched through the anchor

Readme

@vertekum/ext-token-ramp

Colour ramps generated from a single brand anchor. A group in the token collection declares a ramp; this extension computes its stops — a fixed lightness ladder with chroma arched through the anchor, in OKLCH.

Get started

// vertekum.config.ts
import { defineConfig } from '@vertekum/core';
import { tokenRampExtension } from '@vertekum/ext-token-ramp';

export default defineConfig({
  collection: './tokens',
  extensions: [tokenRampExtension],
});
// tokens/core.json — the ramp is a group carrying a payload; the stops are computed
{
  "brand": {
    "accent": { "$type": "color", "$value": { "colorSpace": "oklch", "components": [0.6884, 0.1148, 188.2], "alpha": 1, "hex": "#1DB1A8" } }
  },
  "color": {
    "teal": {
      "$extensions": {
        "org.vertekum.generate/ramp": {
          "anchor": "{brand.accent}",
          "scalar": "100-1000/100"
        }
      }
    }
  }
}

color.teal.100color.teal.1000 now exist — aliasable, exportable, validated — without being written anywhere. That is virtual mode. To write them as real tokens instead (committed mode):

# vertekum ramp build [--check] [--dry-run] [--json]
vertekum ramp build          # writes the stops under each ramp group
vertekum ramp build --check  # CI guard: fails when committed stops are stale
vertekum ramp build --dry-run --json   # emits every computed stop as data.ramps —
                                       # a value source that needs no CSS parsing

A ramp group may carry its own $root token (the anchor swatch as the group's value): the root parses as usual and the generated stops appear beside it.

The payload stays the single source either way: virtual stops refuse direct edits ("generated by 'org.vertekum.generate/ramp' — edit the payload"), and committed stops are regenerated by ramp build.

The payload

| Field | Values | Required | Meaning | | --- | --- | --- | --- | | anchor | a colour ("#1DB1A8", a stored colour object) or a reference ("{brand.accent}") | yes | The brand colour the ramp is built from. It is never repainted — its step carries it verbatim. | | scalar | a stepped range, "min-max/step" ("100-1000/100", "050-500/50" — leading zeros pad the names) | yes | The step names. The anchor's position is derived, never declared: it lands on the step whose ladder lightness is nearest its own. | | hueDrift | degrees (number) | no (default 0) | Dark-side hue rotation, reached in full at the last step. Deep yellows drift toward orange instead of going olive. | | profile | a name from profiles | no | Which physics profile this ramp uses. Absent → defaultProfile → the base settings alone. An unknown name is an error, never a fallback. | | ladder, lightness, lightFraction, darkExponent | as in settings | no | Per-ramp overrides of the configured physics. |

Settings

How a shade is calculated — the full walkthrough with a worked example is in docs/ramp.md.

| Setting | Default | Meaning | | --- | --- | --- | | lightness.first | 0.958 | The palest step's lightness (OKLCH L, 0–1). | | lightness.last | 0.27 | The deepest step's lightness. | | lightness.ease | 1 | How the steps travel between them: 1 = evenly spaced, >1 bunches the light end, <1 the dark end. | | ladder | — | An explicit step name → L table. Wins over the curve for the steps it names — use it to reproduce a hand-tuned ladder exactly. | | lightFraction | 0.2 | How washed-out the palest step is: its chroma is this fraction of the anchor's. | | darkExponent | 0.85 | How quickly chroma falls on the dark side (higher = duller deep shades). | | profiles | — | Named partials of the fields above — one per brand, typically. A payload selects one with "profile": "<name>". Resolution is per field: defaults ← top-level settings ← profile ← payload overrides, ladders merging by step key. | | defaultProfile | — | The profile a payload without profile uses. |

// Multi-brand: declare each brand's physics once; each ramp payload says one word.
extensions: [
  tokenRampExtension({
    profiles: {
      brand-a: { ladder: { '100': 0.958, '200': 0.91, /* … */ '1000': 0.27 } },
      brand-b:  { lightness: { first: 0.97, last: 0.24, ease: 1.15 } },
    },
    defaultProfile: 'brand-a',
  }),
],

What check enforces

  • The payload's shape (its own schema, diagnostics under the ramp/* domain).
  • ramp/invalid-scalar — the range does not parse or yields fewer than two steps.
  • ramp/unknown-profile — the payload (or defaultProfile) names a profile the settings do not define; the message lists what is defined.
  • ramp/unresolved-anchor — the anchor reference dangles or is not a colour. A virtual ramp must be loud when it cannot compute, never silently absent.

License

Apache-2.0