Extract visual branding (colors, typography, layout patterns) from a client's website and generate a style preset compatible with the HTML slides skill and a brand config JSON for the content asset creator. Uses WebFetch to read pages and analyzes CSS/HTML to identify the color palette, font pairings, and aesthetic patterns.
npx gooseworks install --all # then, in Claude Code, Cursor, or Codex: /gooseworks use the visual-brand-extractor skill
Extract a client's visual identity from their website and generate reusable style presets for slides and content assets. This is an agent-executed skill — the AI reads pages via WebFetch and performs the analysis directly.
Extract visual branding from https://vapi.ai for the Vapi client.| Input | Required | Description |
|---|---|---|
| Website URL | Yes | Client's homepage or landing page URL |
| Client name | Yes | For naming the output files |
| Additional pages | No | Product page, docs page, etc. for richer extraction |
Two files saved to clients/<client-name>/brand/visual-identity.md:
skills/create-html-slides/STYLE_PRESETS.mdskills/content-asset-creator formatFetch 2-3 pages to get a representative sample of the brand:
Use WebFetch on each URL with a prompt like:
"Extract the full content of this page. I need: all color values (hex, rgb, hsl), font family names, CSS class names (especially Tailwind utility classes), any CSS custom properties/variables, meta tags, and the general structure of the page layout. Preserve exact color codes and font names."
Analyze the fetched content to identify the color palette. Look for these sources in priority order:
Look for :root, html, or body blocks containing color variables:
--color-primary, --primary, --brand, --accent
--bg-*, --background-*
--text-*, --foreground-*Check for:
<meta name="theme-color" content="#..."> — often the primary brand color<meta name="msapplication-TileColor" content="#...">Search for color values in these properties:
background-color, background (including gradients)color (text colors)border-color, borderbox-shadow (accent/glow colors)fill, stroke (SVG logo colors)If the site uses Tailwind CSS, map utility classes to hex values using the reference table below.
| Role | How to Identify |
|---|---|
| bg-primary | background-color on body, html, or outermost container. The most common background. |
| bg-secondary | Background on cards, sections, or secondary containers. Slightly different from primary. |
| text-primary | color on body or the most common text color. |
| text-secondary | Muted text variant — used on subtitles, descriptions, .text-gray-* elements. |
| accent | Most prominent non-bg, non-text color. Found on buttons, links, CTAs, highlights. Also check <meta name="theme-color">. |
| accent-secondary | Second accent color, or gradient partner. Found on secondary buttons, hover states. |
| card-bg | Background of cards, modals, or elevated surfaces (if different from bg-primary). |
Check the luminance of bg-primary:
Look for font loading in this order:
Google Fonts <link> tags — Font name is in the URL:
fonts.googleapis.com/css2?family=Inter:wght@400;700→ Font: Inter, weights: 400, 700
Fontshare <link> tags — Similar URL pattern:
api.fontshare.com/v2/css?f[]=clash-display@400,700→ Font: Clash Display
@font-face declarations — Extract the font-family value
font-family CSS properties — Direct declarations on elements
| Role | How to Identify |
|---|---|
| Display font | Font on h1, h2, .title, .heading, .hero-title, or the largest/boldest text. |
| Body font | Font on body, p, or general content elements. |
If both use the same font family, it's a single-family pairing (like "Manrope + Manrope"). Note the different weights used for display (700-900) vs body (400-500).
If the site uses a font NOT available on Google Fonts or Fontshare, map it to the closest available equivalent using the Font Fallback Table below.
Examine the CSS and page structure for these aesthetic signals:
| Signal | What to Look For | Aesthetic Implication |
|---|---|---|
| Border radius | border-radius values — large (12px+, 9999px) vs small (2-4px) vs none | Rounded = friendly/modern. Sharp = corporate/bold. |
| Gradients | linear-gradient, radial-gradient in backgrounds | Gradient-forward = modern SaaS aesthetic |
| Shadows | box-shadow frequency and intensity | Heavy shadows = depth/elevation. None = flat/minimal. |
| Spacing | Padding/margin sizes — generous (4rem+) vs tight (1rem) | Airy = premium/minimal. Dense = information-rich. |
| Animations | @keyframes, transition, transform presence | Motion-forward = energetic. Minimal = calm/professional. |
| Grid patterns | Background grid/dot patterns, decorative overlays | Technical/developer aesthetic |
| Gradient orbs | radial-gradient on positioned pseudo-elements | Modern, atmospheric aesthetic |
| Borders as accents | Colored border-left or border-top on sections | Editorial, organized aesthetic |
Based on the signals above, compose:
Create the file clients/<client-name>/brand/visual-identity.md with both output formats.
# Visual Brand Identity: [Company Name]
**Extracted from:** [URL(s)]
**Date:** [YYYY-MM-DD]
---
## Slide Preset
**Vibe:** [2-4 adjectives]
**Layout:** [1 sentence describing dominant layout pattern]
**Typography:**
- Display: `[Font Name]` ([weight, e.g., 700/800])
- Body: `[Font Name]` ([weight, e.g., 400/500])
**Colors:**
```css
:root {
--bg-primary: [hex];
--bg-secondary: [hex];
--text-primary: [hex];
--text-secondary: [hex];
--accent: [hex];
--accent-secondary: [hex];
}
```
**Signature Elements:**
- [Element 1, e.g., "Subtle gradient orbs as background decoration"]
- [Element 2, e.g., "Rounded cards with 12px border-radius and light shadow"]
- [Element 3, e.g., "Accent-colored left border on feature blocks"]
- [Element 4, e.g., "Grid dot pattern overlay on hero sections"]
**Font Loading:**
```html
<link href="https://fonts.googleapis.com/css2?family=[Font1]:wght@[weights]&family=[Font2]:wght@[weights]&display=swap" rel="stylesheet">
```
---
## Brand Config (JSON)
For use with `content-asset-creator` and other skills:
```json
{
"name": "[Company]",
"primary_color": "[accent hex]",
"secondary_color": "[accent-secondary hex]",
"accent_color": "[accent hex]",
"background": "[bg-primary hex]",
"text_color": "[text-primary hex]",
"font_heading": "[Display Font]",
"font_body": "[Body Font]",
"logo_url": "[if discovered, otherwise omit]"
}
```
---
## Extraction Notes
[Any notes about the extraction — proprietary fonts that were mapped, multiple themes detected, sparse CSS from JS-rendered sites, etc.]When a site uses a proprietary font not available on Google Fonts or Fontshare, use this mapping to find the closest available alternative:
| Font Category | Proprietary Examples | Google Fonts Alternative | Fontshare Alternative |
|---|---|---|---|
| Geometric sans | Circular, Roobert, Graphik, Product Sans | Plus Jakarta Sans, Outfit, Manrope | General Sans, Satoshi |
| Humanist sans | Proxima Nova, Calibri, Gill Sans | Source Sans 3, DM Sans, Work Sans | — |
| Neo-grotesque | Akkurat, Aktiv Grotesk, Suisse Int'l | Space Grotesk, Archivo, Albert Sans | Switzer |
| Modern serif | Tiempos, Canela, GT Sectra | Fraunces, Cormorant, Playfair Display | Zodiak, Sentient |
| Slab serif | Sentinel, Clarendon, Rockwell | Zilla Slab, Roboto Slab | — |
| Classic serif | Mercury, Chronicle, Minion | Source Serif 4, Lora, Libre Baskerville | Bespoke Serif |
| Monospace | SF Mono, Berkeley Mono, Dank Mono | JetBrains Mono, Fira Code, Space Mono | Jet Brains Mono |
| Display / decorative | GT Walsheim, Recoleta, Campton | Syne, Archivo Black, Bricolage Grotesque | Clash Display, Cabinet Grotesk |
Decision heuristic: If unsure which category a font falls into, look at its characteristics:
If the site uses Tailwind utility classes, map them to hex values:
| Class | Hex | Class | Hex |
|---|---|---|---|
gray-50 | #F9FAFB | gray-500 | #6B7280 |
gray-100 | #F3F4F6 | gray-600 | #4B5563 |
gray-200 | #E5E7EB | gray-700 | #374151 |
gray-300 | #D1D5DB | gray-800 | #1F2937 |
gray-400 | #9CA3AF | gray-900 | #111827 |
gray-950 | #030712 |
| Class | Hex | Class | Hex |
|---|---|---|---|
slate-50 | #F8FAFC | slate-500 | #64748B |
slate-100 | #F1F5F9 | slate-600 | #475569 |
slate-200 | #E2E8F0 | slate-700 | #334155 |
slate-300 | #CBD5E1 | slate-800 | #1E293B |
slate-400 | #94A3B8 | slate-900 | #0F172A |
slate-950 | #020617 |
| Class | Hex | Class | Hex |
|---|---|---|---|
blue-400 | #60A5FA | blue-700 | #1D4ED8 |
blue-500 | #3B82F6 | blue-800 | #1E40AF |
blue-600 | #2563EB | blue-900 | #1E3A8A |
| Class | Hex | Class | Hex |
|---|---|---|---|
green-400 | #4ADE80 | green-600 | #16A34A |
green-500 | #22C55E | green-700 | #15803D |
| Class | Hex | Class | Hex |
|---|---|---|---|
indigo-500 | #6366F1 | purple-500 | #A855F7 |
indigo-600 | #4F46E5 | violet-500 | #8B5CF6 |
emerald-500 | #10B981 | amber-500 | #F59E0B |
teal-500 | #14B8A6 | rose-500 | #F43F5E |
cyan-500 | #06B6D4 | orange-500 | #F97316 |
Note: Tailwind classes appear as bg-blue-600, text-gray-900, border-indigo-500, etc. Strip the property prefix (bg-, text-, border-) to get the color token, then look up the hex value above.
For custom Tailwind themes (e.g., bg-brand, text-brand-light), check the page's <script> tags for a tailwind.config object that defines custom colors.
Many modern sites (Next.js, React) inject styles via JavaScript. WebFetch may return minimal inline CSS. In this case:
class attributes<script> tags for embedded config objects<style> tags that contain CSS-in-JS outputSome sites define both light and dark themes via prefers-color-scheme. Extract the default (non-media-query) theme. If a dark mode variant is detected, note it in the Extraction Notes section.
Enterprise sites may use dozens of colors. Focus on:
If font detection fails completely:
Running this skill on https://vapi.ai might produce:
# Visual Brand Identity: Vapi
**Extracted from:** https://vapi.ai, https://docs.vapi.ai
**Date:** 2026-02-26
---
## Slide Preset
**Vibe:** Technical, developer-focused, clean, modern
**Layout:** Dark full-width sections with centered content, card-based feature grids, generous spacing
**Typography:**
- Display: `Inter` (700/800)
- Body: `Inter` (400/500)
**Colors:**
\```css
:root {
--bg-primary: #0F172A;
--bg-secondary: #1E293B;
--text-primary: #F8FAFC;
--text-secondary: #94A3B8;
--accent: #22C55E;
--accent-secondary: #3B82F6;
}
\```
**Signature Elements:**
- Subtle gradient orbs in background (green-to-blue radial gradients)
- Rounded cards with slate-800 background and subtle border
- Code-style monospace accents for technical terms
- Green accent on CTAs and interactive elements
**Font Loading:**
\```html
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;800&display=swap" rel="stylesheet">
\```(This is an illustrative example — actual extraction results will vary based on the live site.)
fill values.<meta name="theme-color" content="#..."> — often the primary brand color<meta name="msapplication-TileColor" content="#...">background-color, background (including gradients)color (text colors)border-color, borderAssemble an expert/educator motion-graphic LISTICLE video ad from a config — a spoken authoritative voiceover carries a numbered listicle while N web-animated hyperframe beats (HTML plus the Web Animations API, one branded design system of alternating tiles, big hero numerals, and glass-pill callouts) are rendered frame-by-frame via Playwright and anchored to the VO's word-level timestamps, periodic color-graded B-roll windows give visual breath, and captions burn ONLY inside those B-roll windows (2-word chunks, ASS Format header carrying a Name field so none drop) with the VO mixed under a low music bed. This is the FREE deterministic assembly stage (Playwright beat render plus ffmpeg concat plus window-masked caption burn plus VO-and-music mix plus final composite) — the VO, the music bed, and the stock B-roll come from create-vo-elevenlabs, create-music-elevenlabs, and media-proxy. Use for the vo-anchored-motion-listicle format.
Assemble a stop-motion hand-swatch-cycle product-demo ad from a config — a sequence of still PLATES (one hand swiping a single-barrel cosmetic across a cream skin-patch, the barrel + swatch changing per plate while the hand, background, crop, and lighting stay locked) is PNG→mp4 loop-encoded at each plate's own stop-motion hold (fast motion frames 150–250ms, per-shade ~380ms, hero beats 1100–1800ms), concat-demuxed with HARD cuts into a silent master, closed on a Playwright HTML-rendered branded end card (serif tagline + sans subtitle + real logo SVG over a hero BG, never AI-rendered text), and muxed with a pre-sourced music track playing under the end card with a fade tail (no VO). This is the FREE deterministic assembly stage (loop-encode + concat-demux + end-card render + music mux); the master-anchor plate, shade plates, and end-card BG come from create-image-gpt-image-fal and the track from create-music-elevenlabs. Use for the stopmotion-hand-swatch-cycle format.
Assemble a split-screen creator ad from a config — a two-zone vertical composite where a supplied AI-creator lip-sync take fills the BOTTOM ~48% while real 16:9 product/demo clips run uncropped in the TOP ~52%, each top clip contain-fit with a darkened blurred cover-scale fill of the same clip (never black bars), a 3px brand-color divider between the zones, the creator slice cover-fit per the per-scene VO timing, scenes hard-concatenated with the body audio being the concatenated creator VO slices, an end card held on the last sharp frame ~3s, then the ASSEMBLED cut transcribed with local Whisper (not the raw VO — concat drops inter-scene silence) and word-level captions burned in the chosen style. This is the FREE deterministic assembly + caption stage (two-zone composite + blurred fill + divider + hard-concat + end card + captions); the VO comes from create-vo-elevenlabs, the anchor from create-image-gpt-image-fal, and the whole-VO lip-sync from a paid VEED Fabric 1.0 take (a no-atom upstream input). Use for the split-screen-creator format.