Configuration
Configure sources, governance, and output.
primitiv.config.js
// primitiv.config.js
module.exports = {
sources: {
codebase: {
root: "./src",
patterns: ["**/*.css", "**/*.ts", "**/*.tsx"],
ignore: ["node_modules", "dist", ".next"]
},
// figma: {
// token: process.env.FIGMA_ACCESS_TOKEN,
// fileId: "your-figma-file-id"
// // optional: false, // fail the build when this source can't be scanned
// },
// storybook: {
// url: "http://localhost:6006"
// }
},
governance: {
sourceOfTruth: "codebase", // "codebase" | "figma" | "storybook" | "manual"
// "warn": record conflicts as pending; build succeeds (default)
// "error": write the contract, then fail the build (exit 2) while conflicts are pending
// "auto-resolve": conflicts the sourceOfTruth decides are marked resolved; standoffs stay pending
onConflict: "warn"
},
output: {
path: "./primitiv.contract.json"
}
}Sources
Configure which design sources Primitiv scans. Each source uses an adapter:
- codebase — scans CSS variables, TypeScript tokens, and React components from your filesystem
- figma — connects to Figma via the Variables API (requires access token and file ID)
- storybook — scans components and variants via the Storybook manifest
optional
Remote sources (figma, storybook) are optional by default: if one can't be scanned, the build warns, records the failure, and continues. Set optional: false on a source to make its failure hard-fail the build (exit 1, no contract written). Your governance.sourceOfTruth is always treated as required regardless of this flag — see Failed sources.
Governance
Controls how Primitiv handles conflicts between sources:
sourceOfTruth— which source wins when sources disagree ("codebase","figma","storybook", or"manual")onConflict— what to do when a conflict is detected:"warn"(default) — record conflicts aspending; the build still succeeds"error"— write the contract, then fail the build (exit2) while conflicts remain pending"auto-resolve"— conflicts thesourceOfTruthdecides are marked resolved; genuine standoffs (no source-of-truth winner) staypending
Same-source conflicts are never auto-resolved. When one source defines a token twice with two different values, a source can't arbitrate itself, so the conflict stays pending under every onConflict value until a human removes one definition. See Redefinition conflicts.
Failed sources
Every build records a sourceStatuses field on the contract — ok (with token/component counts), failed (with a sanitized error), or skipped (not configured) per source — so consumers can distinguish "not configured" from "configured but failed."
When a remote source (Figma, Storybook) is unreachable, the build warns, records the failure, and continues; verify skips drift reporting for that source's entries instead of reporting them all as removed. The one exception: if the failed source is your governance.sourceOfTruth (or is marked optional: false), the build hard-fails and writes nothing — running conflict resolution without its authority would be worse than no contract.
Output
path— where to write the resolved contract file (default:./primitiv.contract.json)