Utilities
BDS-side tooling — the Style Dictionary build pipeline, the bds-find component-discovery CLI, and the Adopt / Extend / Graduate cascade.
This page covers tooling that sits inside BDS — what BDS builds, ships, and exposes to consumers as command-line helpers and build outputs.
Looking for the consumer-side helpers (@/lib/tokens, @/lib/styles, the Prose markdown renderer, the pre-commit token-compliance hook)? Those live on every consumer repo and are documented in React Composition Layer.
Style Dictionary build pipeline
BDS owns the source-of-truth pipeline. Consumers never run these — they consume the compiled outputs via @brikdesigns/bds. Knowing the pipeline matters when a token is missing, a rename is in flight, or a Library is being refreshed.
Two-Library composition
BDS sources tokens from two logical Libraries — the Foundations Library (universal, agnostic) and the Brik Brand Kit Library (brand-specific values). Both are Figma files managed via Tokens Studio. The pipeline pulls each via the WebSocket relay (port 3055), then Style Dictionary composes them into the shipped bundle:
┌──────────────────────────┐ ┌────────────────────────────┐
│ Foundations Library │ │ Brik Brand Kit Library │
│ (Figma — Tokens Studio) │ │ (Figma — Tokens Studio) │
└────────────┬─────────────┘ └────────────────┬───────────┘
│ bun pull-variables.js <channel> │ bun pull-variables.js <channel>
▼ ▼
design-tokens/foundations.json design-tokens/brand-kits/brik.json
│ │
└────────────────┬───────────────────────┘
│ Style Dictionary
▼
tokens/figma-tokens.css (Foundations primitives + base semantics — @layer bds-tokens)
tokens/figma-tokens-dark.css (Foundations dark — scoped to [data-theme="dark"])
tokens/theme-brand-brik.css (Brik Brand Kit — scoped to .theme-brand-brik)
build/figma/js/tokens.mjs (JS object form)
build/figma/swift/*.swift (iOS sync)
│ scripts/build-dist-tokens.js
▼
dist/tokens.css (shipped to consumers via @brikdesigns/bds/tokens.css)Current state vs target. Today design-tokens/tokens-studio.json is a single pre-separation merged snapshot containing both Foundations and Brand Kit content. The per-Library JSON split (foundations.json + brand-kits/{slug}.json) is the target architecture. Until the multi-Library pull lands, manual care is required when refreshing the snapshot. Tracked in brik-bds#712.
Commands
| Command | Input | Output |
|---|---|---|
./scripts/start-figma-relay.sh | (none) | Starts the WebSocket relay on port 3055 (idempotent — no-op if running) |
bun scripts/pull-variables.js <channel-id> | Live Figma file via relay | JSON dump of all variables (stdout — pipe to a file under design-tokens/) |
./scripts/figma-pull-tokens.sh [channel-id] | (relay channel) | One-shot wrapper: pull + sync + build |
npm run build:sd-figma | design-tokens/tokens-studio.json | tokens/figma-tokens.css, JS, Swift |
npm run build:sd-dark | same JSON, color=dark mode | tokens/figma-tokens-dark.css |
npm run build:modes | same JSON | tokens/modes-{collection}.css per wired mode |
npm run build:all-tokens | all the above SD steps | Full rebuild (light + dark + modes) |
npm run build:dist-tokens | all tokens/*.css | dist/tokens.css (concatenation + bundle) |
npm run build:lib | full repo | Publishable dist/ |
Never hand-edit tokens/figma-tokens.css or tokens/figma-tokens-dark.css. They're regenerated on every build and your edit will silently disappear. Add the token to the appropriate Library in Figma → re-pull → rerun build:sd-figma. The only manual token files are tokens/gap-fills.css (tokens not yet in Figma — destined to migrate) and tokens/theme-brand-brik.css (Brik's own Brand Kit — pending automated emission from a Brand Kit pull).
Never call the Figma Variables REST API. It's Enterprise-tier and not on Brik's plan. The relay + Tokens Studio dev plugin is the only sanctioned path from Figma → JSON.
See Token Anatomy for the four-tier abstraction this pipeline emits, Library Architecture for the per-Library detail, and The Cascade for how the CSS output composes at runtime.
bds-find — component discoverability CLI
A CLI that queries the BDS component manifest (dist/bds-manifest.json) to answer the question every product agent should ask before building UI: does BDS already have a component for this?
# Fuzzy search — the most common usage
bds-find "tag input with autocomplete"
# Filter by tag
bds-find --tag form
# Exact lookup
bds-find --exact AddableTagList
# Dump everything (JSON)
bds-find --listAdopt / Extend / Graduate
bds-find's exit codes map to the cascade product agents follow when they hit a UI gap:
| Exit code | Match confidence | Decision |
|---|---|---|
0 | ≥ 0.85 (high) | Adopt — use the BDS component as-is. |
1 | 0.5 – 0.85 (partial) | Extend — upstream a PR to BDS rather than rebuild. |
2 | under 0.5 (no match) | Graduate — build in the consumer, log to .bds-gaps.log for later upstream. |
3 | internal error (manifest missing) | run npm run build:inspector-manifest first. |
The cascade prevents two failure modes:
- Reinventing existing components (silent duplication of
AddableTagListbecause the agent didn't know it existed). - Forking BDS in the consumer (one-off card variants that drift from canonical). Extending upstream keeps the system narrow and shared.
Output formats
bds-find auto-detects: human-readable Markdown when output is a TTY, JSON when piped. Force one with --format=md or --format=json. JSON is what agent tooling parses; markdown is what humans skim.
# Human-readable (default in a terminal)
bds-find form
# Structured (default when piped — what agents consume)
bds-find form | jq '.matches[0]'Adding a utility
The bar for shipping a new utility from BDS itself is high. Most "utility" needs belong in the consumer's lib layer (see React Composition Layer) — that keeps the BDS surface narrow.
A utility belongs in BDS only when:
- It depends on the BDS source of truth (component manifest, token registry, content-system enums) and would drift if forked.
- It's used by ≥ 2 consumers (or has an obvious second consumer in a product app).
- It's stateless and side-effect-free — no global runtime state, no DOM mutation. CLI scripts and pure functions only. Stateful behavior belongs in a hook paired with a component.
Utilities that don't clear all three bars stay in the consumer.
Related
- React Composition Layer — consumer-side
@/lib/tokens+@/lib/styles+Prosepattern - Primitives → Color — canonical token registry the build pipeline emits
- Theming → Atmospheres — the dark / atmosphere overlay system
- Components — what
bds-findsearches against - Hooks — the stateful counterpart to these stateless utilities