Build Brand Board
Overview
This skill generates a brand board — a single-page visual reference sheet capturing a company's visual identity — from their website URL and any additional assets the user provides.
A brand board includes:
- Color palette — primary, secondary, accent, and neutral colors with hex codes
- Typography — font families, weights, and size scale with specimen text
- Logo — extracted from the website, shown on light and dark backgrounds
- Imagery & mood — hero images and photography style
- Design tokens — border radius, shadows, spacing patterns, CSS custom properties
The skill works in two phases: extraction (automated analysis of the website) and composition (building the brand board artifact with Claude's design judgment).
When to Use
Fire this skill when the user asks to:
- Build, create, or generate a brand board from a website URL
- Extract a company's visual identity / brand elements from their site
- Analyze a firm's website for colors, fonts, and design patterns
- Create brand guidelines from a URL
- Produce a "look and feel" reference from a website
Also fire when the user provides a URL and asks for "brand analysis", "visual identity audit", or "design system extraction".
When NOT to fire
- Carta-internal branding requests — use
carta-brand or carta-theme instead
- Full design system documentation — this skill produces a one-page reference, not a comprehensive system
- Logo design or creation — this skill extracts existing logos, it does not create new ones
Prerequisites
The analysis script requires network access to fetch the website. Dependencies are declared inline (PEP 723) and resolved by uv run automatically:
requests, beautifulsoup4, cssutils, Pillow
- For PDF output:
reportlab
- For PPTX output:
python-pptx
Workflow
Phase 0: Check for saved brand board in Carta (MANDATORY — runs before any website extraction)
Before touching the website, check whether Carta already has a saved brand board for this firm. A saved board means a previous session already extracted and approved the brand identity — reusing it is faster, more consistent, and avoids redundant scraping.
0a. Ensure firm context is set
If a firm UUID was passed in from the orchestrating skill (e.g., carta-agm-deck-builder), call:
mcp__claude_ai_carta__set_context(firm_id="<firm_uuid>")
If no firm UUID was passed, call mcp__claude_ai_carta__list_contexts() to list available firms and pick the matching one. Do not skip this step — the brand board lookup depends on the active firm context.
If Carta MCP is not connected (tool not found or auth error), skip Phase 0 entirely and proceed to Phase 1. Record brand_board_source = "none".
0b. Fetch saved brand board
mcp__claude_ai_carta__call_tool({"name": "fa__get__brand_board"})
HTTP 200 / success: A saved brand board exists. Use the brand_board field from the response as brand_data. Set brand_board_source = "saved_mcp". Tell the user:
"Found a saved brand board for this firm — reusing the previously extracted brand identity. Let me know if you'd like to re-extract from the website instead."
Skip Phase 2 (website extraction) entirely. Jump directly to Phase 3 (Classify and curate) using the saved data.
404 / "Brand board not found": No saved board exists. Set brand_board_source = "to_be_created". Proceed to Phase 1 (gather inputs) and Phase 2 (website extraction). The result will be saved in Phase 5.
Any other error: Treat as "not found" and proceed to Phase 1. Do not block on errors.
Phase 1: Gather inputs
Ask for the website URL if not already provided. Accept bare domains (acme.com) — the script prepends https:// automatically.
Ask about additional assets (optional). The user may provide:
- Logo files (PNG, SVG) they want used instead of / in addition to extracted logos
- Brand color specifications (hex codes, color names)
- Existing brand guidelines or style guides
- Reference brand boards from other companies they admire
- Font names or specimen images
If the user says "no" or provides nothing extra, proceed with website-only extraction.
Ask about the output format (optional). Default to HTML artifact. Other options:
- PDF (landscape A4)
- PPTX (16:9 slide deck)
- React artifact
If the user doesn't specify, produce an HTML artifact.
Phase 2: Extract brand signals
Run the analysis script:
uv run ${CLAUDE_PLUGIN_ROOT}/skills/carta-brand-extraction/scripts/analyze_website.py <url>
This returns a JSON report with raw extraction data. Save the output — you will reference it throughout composition.
If the script fails (e.g., the site blocks automated access, CAPTCHA, JS-heavy SPA with no server-rendered content):
- Try
WebFetch on the URL as a fallback to get the HTML
- If the page requires JavaScript rendering, inform the user and ask them to provide a screenshot or manually list their brand colors/fonts
- Never silently skip extraction — always tell the user what happened
Phase 3: Classify and curate
This is where Claude's design judgment matters. The raw extraction data has frequency-ranked colors and multiple font families. You must classify them:
Colors
Group the extracted colors into four categories:
- Primary — the 1-2 most prominent brand colors (often used in headers, CTAs, navigation). These define the brand. Look for colors that appear in the logo, primary buttons, or hero sections.
- Secondary — supporting colors used for backgrounds, section differentiation, or secondary UI elements. Usually 1-3 colors.
- Accent — highlight colors for CTAs, links, hover states, or emphasis. Often the most saturated/vibrant colors on the site.
- Neutral — grays, off-whites, and dark tones used for text, borders, and backgrounds. Include the primary text color and the page background.
Classification heuristics:
- Colors in CSS custom properties named
--primary, --brand, --accent are strong signals
- Colors used in
<header>, <nav>, or .hero contexts are likely primary
- Very light colors (luminance > 220) are likely background neutrals
- Very dark colors (luminance < 40) are likely text neutrals
- If the user provided explicit brand colors, those override extraction
Typography
- Identify the heading font (used in
h1-h3, .hero, display text)
- Identify the body font (used in
p, body, general content)
- Note any accent fonts (used sparingly for special elements)
- Google Fonts detected by the script are high-confidence signals
- Include weight and size ranges observed
- The script also extracts
@font-face source URLs (typography.font_faces) for custom/self-hosted fonts. These are the actual font file URLs needed to load the fonts at render time — without them, the browser only has the family name and falls back to system fonts
Logos
- Prefer logos extracted from
<header> or <nav> over favicon
- Prefer SVG over raster when available
- If the user provided a logo file, use that as the primary logo
- Show the logo on both light and dark backgrounds in the brand board
Imagery
- Select 3-6 hero/banner images that best represent the brand's visual style
- Skip icons, tiny decorative elements, and tracking pixels
- Note the overall mood: professional, playful, minimal, bold, etc.
Design Tokens
- Extract observed border-radius values, shadow styles, and spacing patterns from CSS custom properties
- These are supplementary — include them if present, skip if the site doesn't use CSS custom properties
Phase 4: Compose the brand board
Read the appropriate snippet template:
| Format |
Snippet to read |
| HTML artifact |
snippets/brand_board_html.html |
| React artifact |
snippets/brand_board_react.jsx |
| PDF |
snippets/brand_board_pdf.py |
| PPTX |
snippets/brand_board_pptx.py |
For HTML artifacts (default):
- Read
snippets/brand_board_html.html
- Replace all
{{PLACEHOLDER}} values with the classified data
- Duplicate the repeating elements (
.bb-swatch, .bb-type-specimen, etc.) for each data item
- If the brand identity is dark, add class
dark-mode to <body>
- For logos, use the extracted URL directly (or base64-encode if producing a self-contained artifact)
- Output the complete HTML as a Claude artifact
For React artifacts:
- Read
snippets/brand_board_react.jsx
- Construct the props object from classified data
- Render
<BrandBoard> with the populated props
- For logos, use base64 data URIs for self-contained artifacts
For PDF:
- Read
snippets/brand_board_pdf.py
- Construct the
data dict with classified colors, fonts, logos, tokens
- Call
generate_brand_board_pdf(data, "brand_board.pdf", firm_name="...")
For PPTX:
- Read
snippets/brand_board_pptx.py
- Construct the
data dict
- Call
generate_brand_board_pptx(data, "brand_board.pptx", firm_name="...")
Phase 5: Save brand board to Carta (MANDATORY if newly extracted)
If brand data was freshly extracted in this session (i.e., brand_board_source = "to_be_created" — Phase 0 returned a 404), save it to Carta automatically after the user has seen the brand board output and not objected to the colors.
You do not need a separate explicit consent question for this write. The user's approval of the brand board in Phase 4 (or the absence of any correction) is sufficient consent. If the user explicitly said "don't save" or "skip Carta", honor that.
Call:
mcp__claude_ai_carta__call_tool({"name": "fa__create__brand_board", "arguments": {"brand_board": <brand_data_json>}})
The brand_board parameter is the full brand identity JSON object — colors, typography, logo candidates, and source metadata.
On success, tell the user (one line only):
"Brand board saved to Carta — future runs will reuse it automatically."
Skip this step if:
brand_board_source is "saved_mcp" (came from Carta, no need to re-save)
- Carta MCP was unavailable in Phase 0 (
brand_board_source = "none")
- The firm UUID / context was never set
Phase 6: Incorporate user-provided assets
If the user provided additional assets in Phase 1:
- Logo files — replace extracted logos with user-provided ones
- Color specs — override extracted colors with user-specified hex codes; keep extracted colors as secondary/neutral fill if they complement the user's choices
- Brand guidelines — use as the authoritative source; extracted data fills gaps only
- Reference boards — match the layout/style/mood of the reference when composing
User-provided input always takes precedence over automated extraction.
User-facing output
Keep responses concise. The brand board artifact is the deliverable — not the conversation.
- Start: one sentence — "Analyzing acme.com to build your brand board."
- After extraction: brief summary of what was found — "Found 12 colors, 2 font families (Inter, Playfair Display), 3 logo candidates, and 5 hero images."
- After composition: "Brand board ready." + the artifact
- Do NOT dump the raw JSON analysis, list every extracted color, or narrate each classification decision
- Do NOT explain the template structure or which snippet was used
If the extraction is thin (few colors, no clear fonts, no logos), say so and ask the user if they can provide additional brand assets to fill the gaps.
Verification checklist
Before delivering the brand board:
Troubleshooting
- Script returns empty colors: The site may use CSS-in-JS or a framework that inlines styles at runtime. Try
WebFetch to get the rendered HTML, or ask the user for a screenshot.
- No fonts detected: The site may use system fonts only, or load fonts via JavaScript. Check for
@font-face in the raw CSS or Google Fonts links.
- Logo not found: Many sites use inline SVGs or CSS background images for logos. Check the SVG extraction results. If nothing works, ask the user to provide their logo file.
- Site blocks requests (403/429): Some sites block automated requests. Ask the user to provide a screenshot of their homepage, or paste the key colors/fonts manually.
- JS-heavy SPA: The script fetches server-rendered HTML only. SPAs that render entirely client-side will return minimal data. Ask for a screenshot or manual input.
Related skills (bundled in this plugin)
powered-by — embeds the "Powered by Carta" lockup on artifacts. Complementary — carta-brand-extraction produces the board, powered-by adds the Carta badge if the data came from Carta.
carta-agm-deck-builder — the main orchestrator skill that chains brand extraction + deck generation + Carta badge.
1---2name: carta-brand-extraction3description: Generates a brand board from a firm's website URL and optional user-provided assets. Analyzes the website to extract theme colors, typography, logos, and imagery, then produces a polished brand board as an HTML artifact, PDF, slide deck, or React component. Trigger phrases: "build a brand board", "create a brand board", "generate a brand board", "extract brand identity", "brand board from website", "visual identity from URL", "brand guidelines from site", "analyze brand from website", "brand audit".4---56<!-- carta:instrumentation-fallback -->7<IMPORTANT>8`_instrumentation_v2` is anonymous Carta skill-usage telemetry. ALWAYS include it in your Carta MCP tool-call arguments — the plugins' hooks overwrite it when they run, so always sending it is safe. Shape:9`_instrumentation_v2: {"skills": ["<plugin>:<skill>", ...], "model": "<model-id>", "surface": "<value>"}`10`skills` is cumulative for the session: list every Carta skill loaded so far, not only the one driving this call. Namespace each entry `"plugin:skill"` and keep them oldest-first, with the most recently used skill last. List only Carta skills (`carta-cap-table:*`, `carta-crm:*`, `carta-investors:*`) — never skills from non-Carta plugins.11`surface` is the Claude surface you are running in: `"chat"` (claude.ai or the Claude app, i.e. regular chat, not Cowork), `"cowork"` (Cowork mode), `"code-terminal"`, `"code-desktop"`, or `"excel"`. Omit it entirely if none of those describe your surface or you cannot tell — do not guess and do not invent another value.12</IMPORTANT>1314# Build Brand Board1516## Overview1718This skill generates a **brand board** — a single-page visual reference sheet capturing a company's visual identity — from their website URL and any additional assets the user provides.1920A brand board includes:211. **Color palette** — primary, secondary, accent, and neutral colors with hex codes222. **Typography** — font families, weights, and size scale with specimen text233. **Logo** — extracted from the website, shown on light and dark backgrounds244. **Imagery & mood** — hero images and photography style255. **Design tokens** — border radius, shadows, spacing patterns, CSS custom properties2627The skill works in two phases: **extraction** (automated analysis of the website) and **composition** (building the brand board artifact with Claude's design judgment).2829## When to Use3031Fire this skill when the user asks to:3233- Build, create, or generate a brand board from a website URL34- Extract a company's visual identity / brand elements from their site35- Analyze a firm's website for colors, fonts, and design patterns36- Create brand guidelines from a URL37- Produce a "look and feel" reference from a website3839Also fire when the user provides a URL and asks for "brand analysis", "visual identity audit", or "design system extraction".4041### When NOT to fire4243- Carta-internal branding requests — use `carta-brand` or `carta-theme` instead44- Full design system documentation — this skill produces a one-page reference, not a comprehensive system45- Logo design or creation — this skill extracts existing logos, it does not create new ones4647## Prerequisites4849The analysis script requires network access to fetch the website. Dependencies are declared inline (PEP 723) and resolved by `uv run` automatically:50- `requests`, `beautifulsoup4`, `cssutils`, `Pillow`51- For PDF output: `reportlab`52- For PPTX output: `python-pptx`5354## Workflow5556### Phase 0: Check for saved brand board in Carta (MANDATORY — runs before any website extraction)5758Before touching the website, check whether Carta already has a saved brand board for this firm. A saved board means a previous session already extracted and approved the brand identity — reusing it is faster, more consistent, and avoids redundant scraping.5960#### 0a. Ensure firm context is set6162If a firm UUID was passed in from the orchestrating skill (e.g., `carta-agm-deck-builder`), call:6364```65mcp__claude_ai_carta__set_context(firm_id="<firm_uuid>")66```6768If no firm UUID was passed, call `mcp__claude_ai_carta__list_contexts()` to list available firms and pick the matching one. Do not skip this step — the brand board lookup depends on the active firm context.6970If Carta MCP is not connected (tool not found or auth error), skip Phase 0 entirely and proceed to Phase 1. Record `brand_board_source = "none"`.7172#### 0b. Fetch saved brand board7374```75mcp__claude_ai_carta__call_tool({"name": "fa__get__brand_board"})76```7778- **HTTP 200 / success**: A saved brand board exists. Use the `brand_board` field from the response as `brand_data`. Set `brand_board_source = "saved_mcp"`. Tell the user:7980 > *"Found a saved brand board for this firm — reusing the previously extracted brand identity. Let me know if you'd like to re-extract from the website instead."*8182 **Skip Phase 2 (website extraction) entirely.** Jump directly to Phase 3 (Classify and curate) using the saved data.8384- **404 / "Brand board not found"**: No saved board exists. Set `brand_board_source = "to_be_created"`. Proceed to Phase 1 (gather inputs) and Phase 2 (website extraction). The result will be saved in Phase 5.8586- **Any other error**: Treat as "not found" and proceed to Phase 1. Do not block on errors.8788---8990### Phase 1: Gather inputs91921. **Ask for the website URL** if not already provided. Accept bare domains (`acme.com`) — the script prepends `https://` automatically.93942. **Ask about additional assets** (optional). The user may provide:95 - Logo files (PNG, SVG) they want used instead of / in addition to extracted logos96 - Brand color specifications (hex codes, color names)97 - Existing brand guidelines or style guides98 - Reference brand boards from other companies they admire99 - Font names or specimen images100101 If the user says "no" or provides nothing extra, proceed with website-only extraction.1021033. **Ask about the output format** (optional). Default to **HTML artifact**. Other options:104 - PDF (landscape A4)105 - PPTX (16:9 slide deck)106 - React artifact107108 If the user doesn't specify, produce an HTML artifact.109110### Phase 2: Extract brand signals111112Run the analysis script:113114```bash115uv run ${CLAUDE_PLUGIN_ROOT}/skills/carta-brand-extraction/scripts/analyze_website.py <url>116```117118This returns a JSON report with raw extraction data. **Save the output** — you will reference it throughout composition.119120If the script fails (e.g., the site blocks automated access, CAPTCHA, JS-heavy SPA with no server-rendered content):121- Try `WebFetch` on the URL as a fallback to get the HTML122- If the page requires JavaScript rendering, inform the user and ask them to provide a screenshot or manually list their brand colors/fonts123- Never silently skip extraction — always tell the user what happened124125### Phase 3: Classify and curate126127This is where Claude's design judgment matters. The raw extraction data has frequency-ranked colors and multiple font families. You must **classify** them:128129#### Colors130131Group the extracted colors into four categories:132133- **Primary** — the 1-2 most prominent brand colors (often used in headers, CTAs, navigation). These define the brand. Look for colors that appear in the logo, primary buttons, or hero sections.134- **Secondary** — supporting colors used for backgrounds, section differentiation, or secondary UI elements. Usually 1-3 colors.135- **Accent** — highlight colors for CTAs, links, hover states, or emphasis. Often the most saturated/vibrant colors on the site.136- **Neutral** — grays, off-whites, and dark tones used for text, borders, and backgrounds. Include the primary text color and the page background.137138**Classification heuristics:**139- Colors in CSS custom properties named `--primary`, `--brand`, `--accent` are strong signals140- Colors used in `<header>`, `<nav>`, or `.hero` contexts are likely primary141- Very light colors (luminance > 220) are likely background neutrals142- Very dark colors (luminance < 40) are likely text neutrals143- If the user provided explicit brand colors, those override extraction144145#### Typography146147- Identify the **heading font** (used in `h1`-`h3`, `.hero`, display text)148- Identify the **body font** (used in `p`, `body`, general content)149- Note any **accent fonts** (used sparingly for special elements)150- Google Fonts detected by the script are high-confidence signals151- Include weight and size ranges observed152- The script also extracts `@font-face` source URLs (`typography.font_faces`) for custom/self-hosted fonts. These are the actual font file URLs needed to load the fonts at render time — without them, the browser only has the family name and falls back to system fonts153154#### Logos155156- Prefer logos extracted from `<header>` or `<nav>` over favicon157- Prefer SVG over raster when available158- If the user provided a logo file, use that as the primary logo159- Show the logo on both light and dark backgrounds in the brand board160161#### Imagery162163- Select 3-6 hero/banner images that best represent the brand's visual style164- Skip icons, tiny decorative elements, and tracking pixels165- Note the overall mood: professional, playful, minimal, bold, etc.166167#### Design Tokens168169- Extract observed border-radius values, shadow styles, and spacing patterns from CSS custom properties170- These are supplementary — include them if present, skip if the site doesn't use CSS custom properties171172### Phase 4: Compose the brand board173174Read the appropriate snippet template:175176| Format | Snippet to read |177|--------|----------------|178| HTML artifact | `snippets/brand_board_html.html` |179| React artifact | `snippets/brand_board_react.jsx` |180| PDF | `snippets/brand_board_pdf.py` |181| PPTX | `snippets/brand_board_pptx.py` |182183**For HTML artifacts** (default):1841. Read `snippets/brand_board_html.html`1852. Replace all `{{PLACEHOLDER}}` values with the classified data1863. Duplicate the repeating elements (`.bb-swatch`, `.bb-type-specimen`, etc.) for each data item1874. If the brand identity is dark, add class `dark-mode` to `<body>`1885. For logos, use the extracted URL directly (or base64-encode if producing a self-contained artifact)1896. Output the complete HTML as a Claude artifact190191**For React artifacts:**1921. Read `snippets/brand_board_react.jsx`1932. Construct the props object from classified data1943. Render `<BrandBoard>` with the populated props1954. For logos, use base64 data URIs for self-contained artifacts196197**For PDF:**1981. Read `snippets/brand_board_pdf.py`1992. Construct the `data` dict with classified colors, fonts, logos, tokens2003. Call `generate_brand_board_pdf(data, "brand_board.pdf", firm_name="...")`201202**For PPTX:**2031. Read `snippets/brand_board_pptx.py`2042. Construct the `data` dict2053. Call `generate_brand_board_pptx(data, "brand_board.pptx", firm_name="...")`206207### Phase 5: Save brand board to Carta (MANDATORY if newly extracted)208209If brand data was freshly extracted in this session (i.e., `brand_board_source = "to_be_created"` — Phase 0 returned a 404), save it to Carta **automatically** after the user has seen the brand board output and not objected to the colors.210211You do **not** need a separate explicit consent question for this write. The user's approval of the brand board in Phase 4 (or the absence of any correction) is sufficient consent. If the user explicitly said "don't save" or "skip Carta", honor that.212213Call:214215```216mcp__claude_ai_carta__call_tool({"name": "fa__create__brand_board", "arguments": {"brand_board": <brand_data_json>}})217```218219The `brand_board` parameter is the full brand identity JSON object — colors, typography, logo candidates, and source metadata.220221On success, tell the user (one line only):222> *"Brand board saved to Carta — future runs will reuse it automatically."*223224Skip this step if:225- `brand_board_source` is `"saved_mcp"` (came from Carta, no need to re-save)226- Carta MCP was unavailable in Phase 0 (`brand_board_source = "none"`)227- The firm UUID / context was never set228229---230231### Phase 6: Incorporate user-provided assets232233If the user provided additional assets in Phase 1:234235- **Logo files** — replace extracted logos with user-provided ones236- **Color specs** — override extracted colors with user-specified hex codes; keep extracted colors as secondary/neutral fill if they complement the user's choices237- **Brand guidelines** — use as the authoritative source; extracted data fills gaps only238- **Reference boards** — match the layout/style/mood of the reference when composing239240User-provided input always takes precedence over automated extraction.241242## User-facing output243244Keep responses concise. The brand board artifact is the deliverable — not the conversation.245246- **Start**: one sentence — *"Analyzing acme.com to build your brand board."*247- **After extraction**: brief summary of what was found — *"Found 12 colors, 2 font families (Inter, Playfair Display), 3 logo candidates, and 5 hero images."*248- **After composition**: *"Brand board ready."* + the artifact249- **Do NOT** dump the raw JSON analysis, list every extracted color, or narrate each classification decision250- **Do NOT** explain the template structure or which snippet was used251252If the extraction is thin (few colors, no clear fonts, no logos), say so and ask the user if they can provide additional brand assets to fill the gaps.253254## Verification checklist255256Before delivering the brand board:257258- [ ] Color palette has at least primary + one other group populated259- [ ] Colors are shown as actual swatches (not just hex codes in text)260- [ ] Typography section shows real specimen text in the detected fonts (or names the fonts clearly if embedding isn't possible)261- [ ] Logo is displayed (or noted as "not found" with a suggestion to provide one)262- [ ] Imagery section has at least 2-3 images (or is omitted if none were found)263- [ ] The board looks visually cohesive — uses the extracted brand colors in its own styling where appropriate264- [ ] User-provided assets override extracted values where they conflict265- [ ] The firm name and URL appear in the header266- [ ] Output format matches what the user requested (or defaults to HTML)267268## Troubleshooting269270- **Script returns empty colors**: The site may use CSS-in-JS or a framework that inlines styles at runtime. Try `WebFetch` to get the rendered HTML, or ask the user for a screenshot.271- **No fonts detected**: The site may use system fonts only, or load fonts via JavaScript. Check for `@font-face` in the raw CSS or Google Fonts links.272- **Logo not found**: Many sites use inline SVGs or CSS background images for logos. Check the SVG extraction results. If nothing works, ask the user to provide their logo file.273- **Site blocks requests (403/429)**: Some sites block automated requests. Ask the user to provide a screenshot of their homepage, or paste the key colors/fonts manually.274- **JS-heavy SPA**: The script fetches server-rendered HTML only. SPAs that render entirely client-side will return minimal data. Ask for a screenshot or manual input.275276## Related skills (bundled in this plugin)277278- `powered-by` — embeds the "Powered by Carta" lockup on artifacts. Complementary — `carta-brand-extraction` produces the board, `powered-by` adds the Carta badge if the data came from Carta.279- `carta-agm-deck-builder` — the main orchestrator skill that chains brand extraction + deck generation + Carta badge.