This repo (VerdigrisTech/design) is the canonical design system for all Verdigris surfaces. It contains machine-readable tokens (JSON), human-readable foundation docs (markdown), and visual rules (YAML).
Package: @verdigristech/design-tokens on GitHub Packages
Consumers: Patina (app UI), www (marketing site), evaluator pipeline, AI agents, Figma
- OKLch is the canonical color space — all other formats (HSL, hex, RGB) are generated
- Patina is the reference implementation — www converges toward Patina, not the other way around
- W3C DTCG format for all token JSON (
$value,$type,$description) - Build pipeline:
tokens/*.json→build/config.ts→build/dist/(oklch.css, hsl.css, hex/colors.json, tailwind/preset.js)
npm run validate # Check token JSON for broken references and missing $type
npm run validate:rules # Check visual-rules.yml (YAML syntax, test blocks, emdashes, convention, sidebar)
npm run validate:all # Run both validators
npm run build # Generate build/dist/ outputs from token source
npm run test:browser # Cross-browser smoke tests (Playwright, chromium/webkit/firefox)
npm run test:browser:install # Install Playwright browser binaries (one-time setup)Smoke tests live in tests/browser/ and run against a locally-built Jekyll site.
Local workflow (one-time):
bundle install # Jekyll + GitHub Pages deps
npm run test:browser:install # Playwright chromium, webkit, firefoxThen for each test run:
bundle exec jekyll build # Build _site/
npm run test:browser # Runs on all 3 browsers; python3 -m http.server serves _siteCI runs these automatically on every PR. See .github/workflows/build.yml cross-browser-smoke job and link-check job.
Before every commit that changes tokens:
npm run validate-- must pass with 0 errorsnpm run build-- regenerate outputs- Commit build outputs alongside token changes
Before every commit that changes rules (visual-rules.yml):
npm run validate:rules-- must pass with 0 errors- Every
type: "constraint"rule must have atestblock - Every
minmust have amax(floors need ceilings) - Every
llm_evalprompt must use YES = violation convention - No emdashes anywhere in the file
Before every commit that changes content (foundations, specimens, examples):
npm run lint:external-- no internal content in public filesnpm run validate:rules-- checks sidebar coverage for new pages- Check for AI writing artifacts (emdashes, jargon, overexplaining)
- Verify cross-file consistency (values in rules must match foundations and specimens)
Releases are automatic. When a PR merges to main, the auto-release.yml workflow:
- Determines the version bump (from PR labels or commit prefixes)
- Bumps package.json, rebuilds, commits, tags, creates a GitHub Release
- Publishes to GitHub Packages
You just merge the PR. Everything else is automated.
| Bump | Trigger | When to use |
|---|---|---|
| Major | PR label major or BREAKING CHANGE in commit body |
Breaking changes: renamed tokens, removed tokens, changed YAML rule ID paths, schema changes that break evaluator pipelines |
| Minor | PR label minor or any feat() commit prefix |
New tokens, new rules, new composition cells, new foundation sections, new assets |
| Patch | Default (no label, no feat prefix) | Fixes to values, docs updates, YAML corrections, adversarial review fixes |
To control the bump, either:
- Add a
major,minor, orpatchlabel to the PR before merging - Or rely on commit message prefixes:
feat()triggers minor, everything else triggers patch
- Branch + PR -- never push directly to main
npm run validate:allon the branch- Adversarial review before merge (at least 1 round for rules/composition changes)
type(scope): description
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Types: feat, fix, docs, refactor, chore
Scopes: tokens, foundations, categories, rules, build, ci
Examples:
feat(tokens): add elevation shadow tokens from Patina audit
docs(categories): add photography guidelines
fix(rules): correct heading weight constraint from 600 to 700
- Team: Z2O (ID:
9e2ce699-7e73-49fe-a33a-d35c81cdb868) - Project: Design System: VerdigrisTech/design
- Include issue ID in commit messages:
[Z2O-XXX]
- All values in W3C DTCG format:
{ "$value": "...", "$type": "...", "$description": "..." } - References use
{path.to.token}syntax — resolved by the build pipeline - Group by concern:
color/,typography/,spacing/,motion/,elevation/
- Include rationale ("why"), not just specification ("what")
- Keep token values in sync with JSON — if a value changes, update both
- If deviating from Patina, add a "Deviation from Patina" section explaining why
- Use
_guide-template.mdas the starting point - Include at least 2 good and 2 bad examples with screenshots
- Reference tokens by name — never hardcode color/size values
- Assets go in
assets/subfolder: SVG for icons, PNG for screenshots, WebP/JPG for photos
- YAML format, machine-parseable for evaluator pipeline consumption
- Schema (v2.1.0): every rule must have
id,severity,type,description - Optional
maturityfield:experimental(warning, collecting signal),convention(warning, deviation requires justification),rule(default, blocks merge),invariant(axiomatic, cannot override) type: "reference"entries omit severity (informational, not enforced)- Every guidance rule needs both a floor AND a ceiling — AI agents optimize toward maximums without upper bounds
- Cross-file consistency: if a value appears in rules, foundations, and specimens, all three must match
- Prototypes, portfolios, working-through-something essays. Not authoritative.
- Nothing here is a rule. Other repos should not treat exploration content as canonical.
- Ideas start here. Graduation happens when evidence accumulates (see below).
The directory structure IS the maturity model. Promoting an artifact = moving it between directories and updating metadata.
- Exploration → Pattern: move from
explorations/tocategories/once used on 2+ real surfaces with positive review - Pattern → Convention: promote to
foundations/when rationale is stable and one adversarial review has passed - Convention → Rule: add to
rules/visual-rules.ymlwithmaturity: experimental. Graduate tomaturity: ruleafter 30 days with no surfaced violations or stakeholder objections - Demotion: anything can move back down if evidence shifts. This is not failure; it is honest response to learning
Guiding principle: if an artifact has no identified ideal brand-aligned use, do NOT build a system around it. Keep it as an exploration until a real use emerges. Bias toward applying existing work to real surfaces over building elaborate exploration scaffolding.
- Don't hardcode design values in docs — reference token names (e.g., "use
color.brand.verdigris" not "use#0fc8c3") - Asset naming: lowercase, hyphens, prefix with
good-orbad-for examples - Screenshots: 2x resolution, max 2400px wide, PNG format
- No AI writing artifacts — strip emdashes, "This means", "In other words", "grounded in", "leverage", "comprehensive". Write short, plain sentences. If it sounds like an AI explaining, rewrite it.
- Alt text — short factual labels ("Verdigris logo — teal"), not internal documentation ("Recovered canonical SVG lockup for light surfaces")
index.md— summarizes with compact visual specimens, links to detailsfoundations/*.md— defines rules with rationale and research citationsspecimen.html— shows applied examples (rendered page scrolls, live demos). Never lecture — show.rules/visual-rules.yml— machine-consumable rules for evaluator/agentsexamples/good|bad/— isolated pattern examples with live HTML demos
- Always branch + PR — never push directly to main, even for docs-only changes
- QA before merge — run content, rules-consistency, and HTML validation review before any PR merge
Any design decision that differs from Patina must be:
- Explicitly documented with a "Deviation from Patina" section
- Justified (marketing-specific need, medium constraint, etc.)
- Rare — Patina has 60+ battle-tested components
Justified: display font (Lato), marketing hero patterns, ad templates, physical goods Unjustified: changing brand teal, different component library, different dark mode strategy
- Build & Validate — runs on push to main and PRs
- Publish — publishes to GitHub Packages on release tags (e.g.,
v0.2.0) - Pages — deploys docs site on push to main
VerdigrisTech/verdigris— www site + evaluator pipeline (consumes this package)- Patina source at
/tmp/patina/— reference implementation for all design decisions