Product engineering
Design libraries
Other token sets for the same components: create, edit, build, check, pull and remove them with node src/cli.mjs library, and import one by name.
A design library is a named set of tokens — colours, dark colours, fonts, the type scale, weights, radii, spacing, shadows, motion — that the shared Wisent components are drawn with. The components are the same in every library; a library changes only the values they read. A product picks a library by the stylesheet and Tailwind theme it imports.
wisent is the package's own library: its tokens are measured from the Wisent Figma files and every existing import (@wisent-ai/components/styles.css, theme.css, tailwind-preset, tokens) is wisent. Other libraries never change it.
Use a library in a product
@import "@wisent-ai/components/libraries/forest/styles.css";
@import "tailwindcss";
@import "@wisent-ai/components/libraries/forest/theme.css";For Tailwind 3, use @wisent-ai/components/libraries/<name>/tailwind-preset.cjs as the preset. styles.css is the whole component stylesheet with the library's tokens and the package's own fonts; React components are imported from @wisent-ai/components as before.
The libraries
Every value is a variable of the Wisent Figma library, set with figma: so the record names the variable it came from.
| Library | What it changes | Import |
|---|---|---|
wisent | nothing: the package's own tokens, Brand green on Shaded Gray | @wisent-ai/components/styles.css |
wisent-character | the brand ramp, light and dark, becomes the library's Character purple ramp | @wisent-ai/components/libraries/wisent-character/styles.css |
wisent-neutral | the canvas, borders and text, light and dark, become the library's neutral Grayscale ramp; the brand stays green | @wisent-ai/components/libraries/wisent-neutral/styles.css |
Choose a library by what people prefer
Preferences shows people two things and asks which they like more. library specimen NAME --out FILE.html draws one self-contained page of the real components with a library; library vote puts those pages to a Preferences vote in an html category, through the Preferences CLI and its own operator bearer.
preferences category create --arena wisent --id design-libraries --name "Design libraries" --kind html
node src/cli.mjs library vote wisent wisent-character wisent-neutral --arena wisent --category design-libraries --out .build/library-vote
node src/cli.mjs library vote --result --submission SUBMISSION--result prints Preferences' ranking and exits 69 until the leader's 95% interval separates; a decided vote is recorded on the winning library. A product moves to a library by changing its import. vote refuses fewer than two libraries, a library named twice, missing --arena, --category or --out (2), and a library whose build is behind its record (1); a Preferences refusal is printed with its own sentence.
Create, edit and build a library
node src/cli.mjs library create forest --from wisent --title "Forest"
node src/cli.mjs library edit forest --set color.brand=#2f6b3a --set radius.lg=10px --approved-by "Łukasz Bartoszcze" --reason "Forest brand green, softer corners"
node src/cli.mjs library build forest
node src/cli.mjs library show forestRun these in the wisent-components checkout. A library made --from another follows that library's changes and keeps its own overrides; each override records who approved it, why and when, and show prints it as from -> to. The build writes dist/libraries/<name>/: styles.css, theme.css, both Tailwind presets and the token modules. node src/cli.mjs build rebuilds every library after the package's own dist/.
| Verb | What it does |
|---|---|
list | every library, its source, overrides and build state (current, not built, stale: <files>) |
show NAME | source, import paths, build state, each override, derived libraries, and the products whose committed source imports it |
create NAME --from LIBRARY | a library made of LIBRARY's tokens plus overrides |
create NAME --figma URL | a library measured from a Figma design file |
edit NAME --set PATH=VALUE --unset PATH --approved-by WHO --reason TEXT | record or drop overrides |
build NAME, build --all | write dist/libraries/NAME |
check [NAME] | refuse a build that is behind its record, naming each file |
pull NAME --export-request FILE | export the Figma file through Weles, measure it, build, commit and push |
remove NAME | delete a library nothing uses |
specimen NAME --out FILE.html | one self-contained page of the real components drawn with NAME |
vote NAME NAME… --arena A --category C --out DIR | put the libraries to a Preferences vote; --result --submission ID reads it |
Values an override takes
color and dark take #rrggbb or #rrggbbaa; radius and space a non-negative px length; shadow x y blur [spread] rgba(r, g, b, a); motion ms; weight a whole number 1–1000; font a CSS font-family list; type.<step>.size px, lineHeight px, em or normal, letterSpacing em or px. Only tokens the components already read can be set, so every component works in every library.
Pull a library from Figma
pull runs on the export host whose Skarbiec holds the Figma token for the Weles export workload. --export-request is that host's Weles request with remote, branch, credential and teamId. pull names the file and the output, libraries/<name>/figma; Weles exports, commits and pushes it (design exports). The file's variables and text styles are then read through the Figma MCP server, the tokens are bound by libraries/<name>/tokens.map.json, and a radius, spacing or shadow the file does not draw is refused. The library is built, committed and pushed.
Refusals
Exit 1 is a refusal and its message names the cause and the command to run; exit 2 is a malformed command.
- a name that is not lower-case words joined by hyphens (2); a name that exists (1); both or neither of
--fromand--figma(2); an unknown parent library (1, listing every library); a URL that is not a Figma design file (2) edit,build,pullorremoveofwisent(1, naming the command that does it forwisent)editwithout--approved-byand--reason(2); a path no component reads (1, listing the group's names); a value of the wrong shape (1, naming the shape);--unsetof a path without an override (1)checkof a stale or unbuilt library (1, naming each file andlibrary build NAME)removeof a library another library is made from, or that a product's committed source imports (1, naming each repository and file)pullof a--fromlibrary; a request withoutteamId; Weles that cannot start or an export that fails; a token whose Figma variable or style is missing from the file (1)
Real test
node tests/library/lifecycle.test.mjs creates, edits, builds, checks and removes a library through the CLI, runs every refusal that needs no Figma file, resolves the packed package's libraries/<name>/ exports from a consumer, finds a real consumer checkout, and checks that wisent's dist/ holds the same bytes before and after. The guide in the repository is docs/design/libraries.md.