How the Brand Onboarding Process Extracts Colors from a Website for Diagram Design

The brand onboarding process fetches a website's HTML, parses its CSS to extract all color values, ranks them by frequency and visual prominence, then maps the top five colors to semantic design tokens.

This automated pipeline—implemented in the cathrynlavery/diagram-design repository—eliminates manual color entry by transforming any public website into a reusable brand palette. The entire workflow completes in approximately 60 seconds and writes directly to the skill's style guide.

The 10-Step Color Extraction Pipeline

The brand onboarding process follows a deterministic, self-contained workflow defined in skills/diagram-design/references/onboarding.md:

1. User URL Input

The skill prompts for a publicly accessible website address. Example: https://mybrand.com.

2. HTML Retrieval

The system issues an HTTP GET request using Python's httpx or urllib.request to download the page markup.

3. Stylesheet Discovery

BeautifulSoup parses the HTML to locate:

  • <link rel="stylesheet"> tags for external CSS
  • Inline <style> blocks embedded in the document

4. CSS Aggregation

External stylesheets are fetched and concatenated with inline styles. The combined CSS is normalized—comments, whitespace, and media-query wrappers are stripped.

5. Color Parsing

A regular expression scan extracts every CSS color literal:

  • Hex codes: #rrggbb, #rgb
  • Functions: rgb(), hsl()
  • Named colors: aliceblue, antiquewhite, aqua, etc.

The parser prioritizes properties associated with brand visibility: background-color, color, border-color, and fill.

6. Frequency Scoring

Each color occurrence is tallied. Heuristics boost weights for colors applied to high-visibility selectors like a, button, and h1.

7. Top-N Selection

By default, the pipeline selects the five most common colors and assigns them to semantic roles:

  • paper — background/base color
  • ink — primary text color
  • accent — highlight/CTA color
  • muted — secondary/subdued color
  • link — hyperlink color

8. Font Family Extraction

A parallel scan extracts font-family declarations from body and heading selectors to identify the primary typeface.

9. Style Guide Generation

The extracted tokens replace defaults in skills/diagram-design/references/style-guide.md. A fidelity receipt records the source URL and extracted values.

10. Profile Persistence (Optional)

Users may save results as a named profile to ~/.diagram-design/profiles/<slug>.md for automatic application to future diagrams.

Implementation: Core Code Components

The following Python snippets mirror the internal logic used by the diagram-design skill.

Fetch and Parse HTML

import httpx
from bs4 import BeautifulSoup

def fetch_html(url: str) -> str:
    """Download the page HTML."""
    resp = httpx.get(url, timeout=10.0)
    resp.raise_for_status()
    return resp.text

Collect CSS from All Sources

def collect_css(html: str, base_url: str) -> str:
    """Gather inline <style> blocks and external CSS files."""
    soup = BeautifulSoup(html, "html.parser")
    css_parts = []

    # Inline styles

    for style_tag in soup.find_all("style"):
        css_parts.append(style_tag.string or "")

    # External stylesheets

    for link in soup.select('link[rel="stylesheet"]'):
        href = link.get("href")
        if not href:
            continue
        css_url = httpx.URL(href, base_url=base_url)
        css_parts.append(httpx.get(str(css_url)).text)

    return "\n".join(css_parts)

Extract and Rank Colors

import re
from collections import Counter

COLOR_RE = re.compile(
    r"""(?i)
    \#([0-9a-f]{3}|[0-9a-f]{6})|
    rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)|
    hsl\(\s*\d+\s*,\s*\d+%?,\s*\d+%?\)|
    (aliceblue|antiquewhite|aqua|...|yellow)  # abbreviated list

    """, re.VERBOSE)

def extract_colors(css: str) -> list[str]:
    """Return a list of all colour literals found in the CSS."""
    return COLOR_RE.findall(css)

def rank_colors(colors: list[str]) -> list[tuple[str, int]]:
    """Count occurrences and return colours sorted by frequency."""
    return Counter(colors).most_common()

def map_to_tokens(top_colors: list[tuple[str, int]]) -> dict:
    """Map the five most common colours to semantic tokens."""
    tokens = ["paper", "ink", "accent", "muted", "link"]
    return {token: color for token, color in zip(tokens, [c for c, _ in top_colors])}

Command-Line Usage

Execute the full pipeline via the skill's built-in command:

diagram-design onboard https://example.com

This prints a summary report and updates style-guide.md with extracted tokens.

To preserve results for reuse:

diagram-design onboard https://example.com --save my-brand

The saved profile enables automatic brand application without re-running extraction.

Key Source Files

File Purpose
skills/diagram-design/references/onboarding.md Complete specification of URL-to-tokens flow, color-extraction heuristics, and ranking algorithm
skills/diagram-design/references/style-guide.md Semantic token definitions (paper, ink, accent, muted, link) populated by onboarding
skills/diagram-design/SKILL.md High-level capability description linking to onboarding functionality

Summary

  • The brand onboarding process extracts colors from websites through automated CSS parsing and frequency analysis
  • Five semantic tokens (paper, ink, accent, muted, link) receive the most prominent colors
  • The pipeline completes in ~60 seconds and writes directly to style-guide.md
  • Profiles enable persistent brand reuse via ~/.diagram-design/profiles/
  • Implementation relies on BeautifulSoup, httpx, and regex-based color parsing

Frequently Asked Questions

What color formats does the brand onboarding process support?

The parser recognizes hex shorthand (#rgb), hex standard (#rrggbb), rgb() functions, hsl() functions, and CSS named colors. All values are extracted as strings and ranked by occurrence count before token assignment.

How does the system decide which colors are "brand" colors?

Frequency is the primary signal—colors appearing most often in the CSS are assumed primary. Heuristic weights boost scores for colors applied to navigation elements (a), buttons (button), and headings (h1), under the assumption that these receive deliberate brand treatment.

Can I modify the number of extracted colors?

The default selects five colors mapped to fixed semantic tokens. To customize, edit the tokens list in map_to_tokens() and adjust the slice operation on top_colors before the zip() call.

Where are extracted brand profiles stored?

Named profiles persist to ~/.diagram-design/profiles/<slug>.md when using the --save flag. These Markdown files contain the full token set and fidelity receipt, enabling version-controlled brand management and team sharing.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →