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

@canonical/terrazzo-lsp

v0.5.2

Published

Language server providing CSS custom property intelligence for design token workflows. Includes completions, hover, diagnostics, go-to-definition, rename, document colours, and workspace symbols.

Readme

@canonical/terrazzo-lsp

Language server providing CSS custom property intelligence for design token workflows. Reads tokens.json build artifacts and provides editor features for CSS and SCSS files.

Features

| Feature | Description | |---------|-------------| | Completions | Context-aware suggestions for var(--...) references, prioritised by type assignability, semantic tier, and provenance. | | Hover | Token metadata including resolved value, colour swatch, alias chain, tier badge, selector context, and source location. | | Diagnostics | Type mismatch detection, missing/stale fallback warnings, unreachable token analysis, primitive usage warnings, and more. | | Go to Definition | Jump from a var() reference to the token declaration. | | Rename | Rename a CSS custom property across all files in the import graph. | | Document Colours | Inline colour swatches and colour picker for token-backed colour values. | | Semantic Tokens | Syntax highlighting distinguishing artifact tokens, local properties, and external references. | | Workspace Symbols | Search tokens across the workspace by name or type. |

Editor Setup

VS Code (recommended):

npm install -D @canonical/design-tokens
npx @canonical/terrazzo-lsp-extension

The extension auto-detects bun first and falls back to node >= 22.

CLI

npx terrazzo-lsp --stdio                # Start LSP server on stdio
npx terrazzo-lsp --stdio --allow-degraded  # Start with reduced capabilities when config is missing
npx terrazzo-lsp check [globs]          # Run diagnostics on CSS files
npx terrazzo-lsp status                 # Show config and artifact status
npx terrazzo-lsp inspect <var>          # Inspect a CSS custom property
npx terrazzo-lsp resolve <spec>         # Resolve an import specifier
npx terrazzo-lsp graph <file>           # Show import graph from a file

Diagnostics Reference

The LSP emits 14 diagnostic codes. CSS diagnostics run on every CSS/SCSS file in the workspace. DTCG diagnostics run once when loading tokens.json artifacts and validate conformance to the DTCG 2025.10 specification. Every diagnostic can be configured to "error", "warning", "info", or "off" in terrazzo-lsp.config.json.

| Code | Config Key | Default | Description | |------|------------|---------|-------------| | css/unknown-var | unknownProperties | off | A var() reference does not match any known custom property. | | css/missing-fallback | missingFallback | warning | A var() reference to a non-artifact property has no fallback value and no @property registration. Skipped for artifact tokens since they are guaranteed to be defined. | | css/stale-fallback | staleFallback | warning | The fallback literal in a var() does not match the token's current resolved value. | | css/type-mismatch | typeMismatch | error | A token's DTCG type is incompatible with the CSS property (e.g. colour token in padding). | | css/type-uncertain | typeUncertain | info | A typed token appears in a shorthand or context where multiple value types are acceptable. | | css/unreachable-token | unreachableToken | warning | The token's artifact output file is not reachable through the @import graph or global stylesheets. | | css/primitive-token | primitiveToken | warning | Direct usage of a primitive-tier token where a semantic alias should be preferred. | | css/scoped-usage | scopedDeclaration | warning | A token declared under a specific selector scope is used in a broader scope. | | css/no-color-scheme | lightDarkNoScheme | info | A light-dark() value is used without a color-scheme declaration on the selector or an ancestor. | | dtcg/broken-alias | brokenAlias | error | An alias reference in the artifact points to a token ID that does not exist. | | dtcg/schema-violation | schemaViolation | error | A token's value is invalid for its declared $type (e.g. $type: color with a non-colour value). | | dtcg/circular-alias | circularAlias | error | The alias chain forms a cycle — a token ID appears more than once in the resolution path. | | dtcg/missing-type | inferredType | info | A token has no explicit $type and its type is ambiguous. | | dtcg/draft-syntax | draftFormat | info | A token uses pre-standardisation draft field syntax (value/type without $ prefix). |

CSS diagnostics example

The example below triggers every CSS diagnostic in one file:

/* Assume the following tokens exist in the artifact:
 *   --color-fg           : oklch(17.2% 0 0)        tier: semantic, type: color
 *   --spacing-sm         : 0.5rem                   tier: semantic, type: dimension
 *   --color-palette-blue : oklch(50% 0.15 250)      tier: primitive, type: color
 *   --button-pad         : 0.75rem                  tier: semantic, scoped to .button
 *   --unreachable-token  : 1rem                     (in a file not imported by this sheet)
 */

/* css/unknown-var — off by default, enable via config */
.unknown   { margin: var(--does-not-exist); }

/* css/missing-fallback — no fallback for a non-artifact property */
.missing   { padding: var(--local-pad); }

/* css/stale-fallback — resolved value is 0.5rem, not 16px */
.stale     { gap: var(--spacing-sm, 16px); }

/* css/type-mismatch — colour token in a length context */
.type-err  { width: var(--color-fg); }

/* css/type-uncertain — dimension in a shorthand accepting many types */
.type-warn { background: var(--spacing-sm); }

/* css/unreachable-token — output file not in @import graph */
.unreach   { margin: var(--unreachable-token); }

/* css/primitive-token — prefer semantic alias */
.primitive { color: var(--color-palette-blue); }

/* css/scoped-usage — --button-pad is scoped to .button */
.card      { padding: var(--button-pad); }

/* css/no-color-scheme — light-dark() without color-scheme */
.no-scheme { color: light-dark(black, white); }

DTCG diagnostics example

DTCG diagnostics surface problems in the token definitions themselves. These appear on the tokens.json artifact entry, not in CSS files:

{
  // dtcg/broken-alias — alias target does not exist
  "color.ghost":   { "aliasChain": ["color.nonexistent"], "type": "color" },

  // dtcg/schema-violation — "not-a-colour" is not a valid CSS colour
  "color.invalid": { "valueLight": "not-a-colour", "type": "color" },

  // dtcg/circular-alias — loop-a → loop-b → loop-a
  "color.loop-a":  { "aliasChain": ["color.loop-b", "color.loop-a"], "type": "color" },

  // dtcg/missing-type — no $type field, type is ambiguous
  "spacing.bare":  { "valueLight": "4px", "type": null },

  // dtcg/draft-syntax — uses pre-standard value/type without $ prefix
  "color.legacy":  { "type": "color", "extensions": { "com.terrazzo.draft-syntax": true } }
}

Suppression syntax

Diagnostics can be suppressed inline with comments:

/* Disable all checks for a region: */
/* terrazzo-lsp-disable */
.suppressed { width: var(--color-fg); }
/* terrazzo-lsp-enable */

/* Disable a specific code for the next line: */
/* terrazzo-lsp-disable css/primitive-token */
.selective { color: var(--color-palette-blue); }
/* terrazzo-lsp-enable css/primitive-token */

Configuration

Create a terrazzo-lsp.config.json in your workspace root:

{
  "artifacts": ["@canonical/design-tokens/dist/tokens.json"],
  "globalStylesheets": [".storybook/styles.css"]
}

If no config file is present, the output panel logs every candidate path it tried, prints a ready-to-copy starter config, and then exits. For temporary degraded startup, pass --allow-degraded.

{ "artifacts": ["@canonical/design-tokens/dist/tokens.json"] }

Full configuration reference

{
  "artifacts": [],
  "distDir": "dist",
  "scanGlobs": ["src/**/*.css", "src/**/*.scss"],
  "globalStylesheets": null,
  "diagnostics": {
    "unknownProperties": "off",
    "missingFallback": "warning",
    "staleFallback": "warning",
    "typeMismatch": "error",
    "typeUncertain": "info",
    "unreachableToken": "warning",
    "primitiveToken": "warning",
    "scopedDeclaration": "warning",
    "lightDarkNoScheme": "info",
    "brokenAlias": "error",
    "schemaViolation": "error",
    "circularAlias": "error",
    "inferredType": "info",
    "draftFormat": "info",
    "ignoreGlobs": []
  },
  "hover": {
    "showColourSwatches": true,
    "showSelectorContext": true,
    "showProvenanceBadge": true,
    "showAliasChain": true,
    "showSourceLocation": true,
    "showNavigationTier": true,
    "showSpecReferences": true
  },
  "inlayHints": {
    "enabled": false,
    "showColourSwatches": true
  },
  "logLevel": "info"
}

| Key | Description | |-----|-------------| | artifacts | Paths to tokens.json build artifacts. Bare specifiers resolve through node_modules/. Relative paths must start with ./ or ../. | | distDir | Directory containing *.css.map files for source-mapping. | | scanGlobs | Glob patterns for CSS/SCSS files to scan for diagnostics. | | globalStylesheets | CSS files implicitly reachable from every document. null means auto-derive from the artifact. | | diagnostics | Per-diagnostic severity overrides. Values: "error", "warning", "info", "off". | | diagnostics.ignoreGlobs | Glob patterns for files excluded from diagnostics. | | hover | Toggle individual sections of the hover popup. | | inlayHints | Inlay hint display (disabled by default). | | logLevel | Server log verbosity: "off", "error", "warn", "info", "debug". |

VS Code extension settings

| Setting | Default | Description | |---------|---------|-------------| | terrazzo-lsp.serverPath | "" | Path to dist/esm/cli.js. If empty, uses the bundled server. | | terrazzo-lsp.runtime | "" | Runtime override. Empty = auto-detect (bun preferred, node >= 22 fallback). | | terrazzo-lsp.trace.server | "off" | "off" shows startup summary only. "verbose" adds per-request traces to the output channel. |

Development

Architecture

The LSP server is organised into four main layers:

| Layer | Path | Responsibility | |-------|------|----------------| | Protocol | protocol/ | JSON-RPC message parsing, config loading, request/response matching | | Runtime | runtime/ | Server lifecycle, document management, import graph building, worker dispatch | | Graph | graph/ | Token graph data structure, artifact loading, reachability cache | | Providers | providers/ | All LSP features: completions, hover, diagnostics, rename, etc. |

Diagnostics pipeline:

CSS diagnostics:  orchestrateDiagnostics → per-rule check modules → makeDiagnostic
DTCG diagnostics: produceArtifactDiagnostics → per-rule check modules → makeDiagnostic

Each diagnostic rule lives in its own file (diagnostics/checkMissingFallback.ts, artifactDiagnostics/checkBrokenAlias.ts, etc.) with a co-located .tests.ts file. The orchestrator loops over usages (CSS) or tokens (DTCG) and delegates to each check function.

bun run build      # Compile LSP server (tsc)
bun run test       # Run tests
bun run check      # Lint + type check