- HTML 80.2%
- Python 18.3%
- CSS 1.1%
- SCSS 0.2%
- JavaScript 0.2%
| .forgejo/workflows | ||
| assets | ||
| references | ||
| schema | ||
| scripts | ||
| skills | ||
| .gitignore | ||
| brand.json | ||
| BRAND.md | ||
| brand.yml | ||
| CLAUDE.md | ||
| example.brand.yml | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
Brand System
A structured, build-driven brand definition system. You define your brand once in a YAML file, and scripts generate all the outputs: machine-readable JSON (with computed color math), CSS custom properties, a human-readable brand guide, palette swatch PNGs, and export files for creative tools (ASE, GPL, SCSS, W3C Design Tokens).
The scripts and schema are the reusable engine. brand.yml and your references/*.md files are the only project-specific content.
How It Works
graph TD
A["brand.yml + references/*.md"] --> B["scripts/build.py"]
B --> C["brand.json<br/><i>computed colors, resolved references, contrast ratios</i>"]
B --> D["BRAND.md<br/><i>human-readable brand guide with embedded prose</i>"]
B --> E["assets/exports/<br/><i>brand.css · ASE · GPL · SCSS · W3C Design Tokens · showcase</i>"]
style A fill:#4b9cd3,stroke:#000,color:#fff
style B fill:#505050,stroke:#000,color:#fff
style C fill:#2b2b2b,stroke:#000,color:#fff
style D fill:#2b2b2b,stroke:#000,color:#fff
style E fill:#2b2b2b,stroke:#000,color:#fff
You edit brand.yml. Everything else is generated.
Build
uv run scripts/build.py # full pipeline: validate → json → css → swatches → exports → docs
uv run scripts/build.py validate # validate brand.yml only
uv run scripts/build.py json # assemble brand.json only
uv run scripts/build.py css # regenerate CSS only
uv run scripts/build.py swatches # regenerate palette swatch PNGs only
uv run scripts/build.py exports # regenerate ASE/GPL/SCSS/tokens only
uv run scripts/build.py docs # regenerate BRAND.md only
CI (Forgejo Actions)
- On PR:
validate.ymlchecks brand.yml for errors and warnings - On merge to main:
build.ymlruns the full pipeline and commits generated files
Schema Overview
Only name and colors.primary are required. Everything else is optional — add sections as your brand grows. The schema is organized in three layers:
Primitives
The atomic building blocks. Define these once, reference them everywhere.
colors — Individual colors with roles. You provide hex values; the build script computes RGB, HSL, and CMYK automatically.
colors:
primary:
name: Indigo
hex: "#4b0082"
use: Main brand color, key accents
secondary:
name: White
hex: "#ffffff"
use: Backgrounds
text:
name: Charcoal
hex: "#333333"
use: Body text
fonts — Font families and their files. Each entry maps a role (logo, heading, body, etc.) to a family with weights and styles.
fonts:
heading:
family: "Inter"
weights: [400, 700]
styles: [normal]
system: false
files:
woff2: assets/fonts/inter.woff2
Structures
Groups, scales, and relationships built from primitives. These compose primitives into usable systems.
palettes — Named color groups. Two shapes:
- Full palettes have a
colorsdict. Each entry can be a color definition or a string reference to a defined color (like"primary"or"grayscale.medium"). The build script resolves references and enriches everything with computed values. - Ordered palettes have an
orderarray for tools that need a color sequence (charts, dashboards). Entries can be hex values or references. Optionallabelsarray gives names to each position.
Both shapes can have a title (display heading) and description (what it's for).
palettes:
neutrals:
description: Neutral gray ramp for data visualization
colors:
dark:
name: Dark Gray
hex: "#333333"
use: Text on light backgrounds
light:
name: Light Gray
hex: "#cccccc"
use: Backgrounds, dividers
chart_colors:
title: Chart Palette
description: Primary color sequence for data visualization
order:
- primary # references colors.primary
- neutrals.light # references a palette color
- "#ff6600" # inline hex
labels:
- Key Metric
- Comparison
- Accent
typography — Type scale definitions (size, weight, line height, optional letter spacing).
typography:
scale:
h1: { size: "36px", weight: 700, line_height: 1.2, letter_spacing: "-0.02em" }
body: { size: "16px", weight: 400, line_height: 1.6 }
styles — Named visual patterns beyond typography. Each entry becomes CSS custom properties (--style-*), a utility class (.style-*), an SCSS map, and a showcase specimen. Use this for recurring design elements like dividers, accent rules, link treatments, and card styles.
Property keys use snake_case and map to CSS properties. color, text_color, and background resolve brand color references. All other keys convert via snake_case → kebab-case.
styles:
divider:
description: Dotted section separator
border_style: dotted
border_width: "2px"
color: primary # resolves to border-color
margin: "2rem 0"
opacity: 0.6
link:
description: Highlighted inline link
font_weight: bold
background: primary # resolves to background-color
text_color: text # resolves to color (text color)
padding: ".15em"
text_decoration: none
card:
description: Content card
border_radius: "8px"
padding: "1.5rem"
shadow: "0 2px 8px rgba(0,0,0,0.1)"
background: secondary
logos — Named compositions (mark, lockup, wordmark, etc.), each with treatments (full_color, reversed, monochrome). Treatments reference color roles for backgrounds and color lists. A rules entry defines size minimums, clear space, and misuse rules.
logos:
mark:
description: "Icon/symbol only"
full_color:
svg: assets/logos/mark-color.svg
background: secondary # references colors.secondary
colors: [primary, text] # colors used in the logo
rules: # rules are per-composition
minimum_size: "48px"
clear_space: "12px"
donts:
- Don't stretch or distort
- Don't change brand colors
lockup:
description: "Mark + wordmark combined"
full_color:
svg: assets/logos/lockup-color.svg
background: secondary
colors: [primary, text]
rules:
minimum_size: "200px" # different composition, different min
clear_space: "24px"
accessibility — WCAG level, approved contrast pairs, and never-use rules. The build script computes the actual contrast ratios from the color pairs you define. typography_rules lists type-specific accessibility rules.
accessibility:
wcag_level: AA
approved_pairs:
- foreground: text
background: primary
never_use:
- Light text on bright backgrounds
typography_rules:
- "Minimum body text size: 16px"
Context
Prose, usage guidance, and metadata. These tell people (and agents) how to use the brand.
voice — Personality traits and tone description.
voice:
personality: [professional, friendly, clear]
tone: Expert but approachable
use_cases — Named scenarios that pair a palette with a pattern. Optional title for display.
use_cases:
marketing:
title: Marketing Materials
palette: chart_colors
pattern: Accent color sparingly
description: Business cards, social media, presentations
references — External markdown files for prose content (audience, visual style, writing guidelines). Files with embed: true are inlined into BRAND.md. Files with embed: false appear as links.
references:
audience:
path: references/audience.md
embed: true
style_guide:
path: docs/style-guide.md
embed: false
contact — Brand steward and help channel.
What the Build Script Computes
You only provide hex values. The build script handles:
- RGB, HSL, CMYK conversions for every color
- WCAG contrast ratios for accessibility pairs
- Pass/fail level (AAA, AA, Fail) for each pair
- Color reference resolution (e.g.
"primary"→"#4b0082"in output) - CSS custom properties and utility classes (colors, typography, styles)
- Style pattern resolution (color references in
stylesentries) - Font-face declarations from font file paths
- Palette swatch PNGs (via MCP color server)
- Export files for creative tools (ASE, GPL, SCSS, W3C Design Tokens)
- Embedded reference content in BRAND.md
Getting Started
- Copy
example.brand.ymltobrand.yml - Fill in your brand name and primary color
- Run
uv run scripts/build.py - Add sections as needed — the schema is fully optional beyond name + primary color
See example.brand.yml for a minimal starting point with the full schema commented out.
Repository Structure
your-brand/
├── brand.yml # SOURCE — the only file you edit
├── brand.json # GENERATED — machine-readable with computed values
├── BRAND.md # GENERATED — human-readable brand guide
├── references/ # Prose content (.md files) embedded into BRAND.md
├── assets/
│ ├── logos/ # Logo files (SVG, PNG)
│ ├── fonts/ # Font files (WOFF2, TTF)
│ ├── swatches/ # GENERATED — palette swatch PNGs
│ └── exports/ # GENERATED — portable brand kit
│ ├── index.html # Visual showcase (self-contained)
│ ├── brand.css # CSS custom properties & utilities
│ ├── fonts/ # Copies of referenced font files
│ ├── logos/ # Copies of logo files
│ ├── swatches/ # Copies of swatch PNGs
│ ├── {name}.ase # Adobe Swatch Exchange (Photoshop, Illustrator)
│ ├── {name}.gpl # GIMP Palette (GIMP, Inkscape)
│ ├── _{name}.scss # SCSS variables, maps, type scale
│ └── {name}.tokens.json # W3C Design Tokens (Figma, Style Dictionary)
├── schema/
│ └── brand.schema.json # JSON Schema for brand.json validation
├── scripts/
│ ├── build.py # Build pipeline (validate → json → css → swatches → exports → docs)
│ └── validate.py # Standalone validation (for CI)
└── .forgejo/workflows/
├── validate.yml # On PR: validate brand.yml
└── build.yml # On merge: build & commit outputs
For Agents
- Quick color lookup: Read
brand.json— all values are resolved and computed - Full guidelines: Read
BRAND.md— the complete brand guide in one file - Accessibility check:
brand.json→accessibility.approved_pairshas pre-computed ratios - Palette for charts:
brand.json→palettes.*.orderhas hex arrays ready to use - Style patterns:
brand.json→styles.*has resolved CSS properties for dividers, cards, links, etc. - Style classes: Use
.style-{name}classes frombrand.cssor override via--style-{name}-*custom properties - Design tokens: Read
assets/exports/{name}.tokens.json— W3C format for any design tool integration - SCSS integration: Import
assets/exports/_{name}.scssfor Sass projects (includes$style-*maps)