@bezel-labs/bezel-kit
v0.4.0
Published
Convert a W3C Design Tokens (DTCG) file into a scoped variables.css, with one CSS scope per context.
Maintainers
Readme
@bezel-labs/bezel-kit
Convert a W3C Design Tokens (DTCG) file into a scoped
variables.css — one CSS scope per context (e.g. :root, .dark, .light). Token
references are resolved to literal values, and every non-base context is emitted as an
override-only block.
The core is isomorphic (browser / edge / Node) and imports no node:*. An optional Node
entry and a bezel CLI add file-system conveniences for build-time generation.
Install
npm install @bezel-labs/bezel-kitUsage
Core — tokensToCss (isomorphic, no file system)
import { tokensToCss, type DtcgNode } from "@bezel-labs/bezel-kit"
const css: string = tokensToCss(tokens)
const hexCss = tokensToCss(tokens, { colorFormat: "hex" })Node — generateVariablesCss (reads/writes files)
The tokens file is always read from design-tokens.json at the project root — its name and
location are fixed and not configurable.
import { generateVariablesCss } from "@bezel-labs/bezel-kit/node"
// reads ./design-tokens.json, writes ./src/bezel/variables.css
await generateVariablesCss()CLI
bezel init [options] # create a bezel.json for this project
bezel build [options] # generate the outputs (default command)init writes the config so you don't have to author it by hand, picking defaults from
the project: outputs go to src/bezel/ (or bezel/ with no src/), and the generated
contexts.ts/fonts.ts modules are only scaffolded for a TypeScript project. Override
any of it with --dir, --variables-output, --contexts-output, --fonts-output,
--no-contexts, --no-fonts, --color, --unit. An existing bezel.json is never
overwritten without --force.
Link the repo to a Bezel project with --project <uuid>, and pin which tokens the Bezel
MCP fetches with --tokens-version <v> (latest or a published semver like 1.4.0;
default latest). These two flags update only their own key in an existing bezel.json,
so no --force is needed:
bezel init --project 0f7a4c2e-1b3d-4e5f-8a9b-0c1d2e3f4a5b --tokens-version 1.4.0build auto-loads bezel.json from the working directory when present. Run
bezel --help for all options.
Config — bezel.json
Any BezelOptions key can be set in bezel.json (variablesOutput, contextsOutput,
fontsOutput, colorFormat, dimensionUnit, nameExtension, ...). Two keys describe
the project link rather than the build:
projectId(optional) — the Bezel project this repo is linked to (a UUID).version(recommended, defaultlatest) — the tokens the Bezel MCP fetches:latestfor the project's latest snapshot, or a published semver like1.4.0.
Both are read only by the Bezel MCP and ignored by build.
{
"projectId": "0f7a4c2e-1b3d-4e5f-8a9b-0c1d2e3f4a5b",
"version": "latest",
"variablesOutput": "src/bezel/variables.css"
}Generated outputs live in their own directory because build overwrites them without
asking and adds them to .gitignore — keeping them out of a hand-written src/styles
means a generic name like variables.css can never clobber a file you wrote.
Upgrading to 0.3.0
The default $extensions namespace changed from com.tokendesigner.app to
com.bezel.app. Tokens still carrying the old key no longer match the default, so
bezel build falls back to path-derived names (--color-primary-default instead of
the authored --primary).
Either re-export design-tokens.json from Bezel, or pin the old key in bezel.json:
{ "nameExtension": "com.tokendesigner.app" }API
- Core (
.):tokensToCss,emitCss,resolveCssOptions,getContexts,formatContextsModule,getFonts,formatFontsModule, theDEFAULT_CONTEXTS/DEFAULT_NAME_EXTENSIONdefaults, plus the related types. - Node (
./node): everything above, plusgenerateVariablesCss,resolveOptions,initConfig, and theDEFAULT_OUTPUT_DIR/DEFAULT_CONFIG_FILEdefaults.
Development
npm install # install deps
npm run build # bundle ESM + CJS + types (index, node, cli) with tsup
npm test # run the Jest test suite
npm run typecheckLicense
PolyForm Shield 1.0.0 — free to use, modify, and redistribute for any purpose except building or providing a product that competes with Bezel. Open-source, internal, and commercial use are all permitted within that bound.
