Brad Wenner Digital brand definition, templates, skills https://branding.sites.brads.house/bwdigital
  • HTML 80.2%
  • Python 18.3%
  • CSS 1.1%
  • SCSS 0.2%
  • JavaScript 0.2%
Find a file
2026-03-01 00:14:36 +00:00
.forgejo/workflows feat: add charts skill for brand-consistent data visualization 2026-02-28 14:39:01 -08:00
assets chore: regenerate brand outputs from brand.yml 2026-03-01 00:13:29 +00:00
references chore: regenerate reference outputs 2026-03-01 00:14:36 +00:00
schema
scripts fix: palette gray ramps fade lighter, fix role color labels 2026-02-28 15:36:05 -08:00
skills feat: remote font downloading, letterhead image embedding, per-bar palette 2026-02-28 16:12:59 -08:00
.gitignore
brand.json fix: palette gray ramps fade lighter, fix role color labels 2026-02-28 15:36:05 -08:00
BRAND.md fix: palette gray ramps fade lighter, fix role color labels 2026-02-28 15:36:05 -08:00
brand.yml fix: palette gray ramps fade lighter, fix role color labels 2026-02-28 15:36:05 -08:00
CLAUDE.md
example.brand.yml
pyproject.toml feat: add charts skill for brand-consistent data visualization 2026-02-28 14:39:01 -08:00
README.md
uv.lock feat: add charts skill for brand-consistent data visualization 2026-02-28 14:39:01 -08:00

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.yml checks brand.yml for errors and warnings
  • On merge to main: build.yml runs 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 colors dict. 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 order array for tools that need a color sequence (charts, dashboards). Entries can be hex values or references. Optional labels array 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 styles entries)
  • 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

  1. Copy example.brand.yml to brand.yml
  2. Fill in your brand name and primary color
  3. Run uv run scripts/build.py
  4. 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.jsonaccessibility.approved_pairs has pre-computed ratios
  • Palette for charts: brand.jsonpalettes.*.order has hex arrays ready to use
  • Style patterns: brand.jsonstyles.* has resolved CSS properties for dividers, cards, links, etc.
  • Style classes: Use .style-{name} classes from brand.css or 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}.scss for Sass projects (includes $style-* maps)