Client Creative Intelligence (CCI)
A 5-stage LangGraph pipeline that automates the brand research step before every creative brief. It extracts CSS typography and color tokens to build a reference document.
40 Minutes in DevTools Before the First Sketch
Every creative brief for a new brand client starts the same way: someone opens Chrome DevTools and starts digging. They are hunting for the official font stack buried inside minified CSS bundles, guessing hex values from compressed logo JPEGs, and manually cross-checking which Instagram handle is the verified one. On a good day this takes 20 minutes. On a brand with a scattered web presence, closer to 45.
The real damage is not just the time lost. It is what happens when someone tries to shortcut it. A generic LLM prompt—“What are Spotify’s brand colors?”—returns #00FF00 as Spotify’s primary green with full confidence, instead of #1DB954. That hallucinated value ends up in a client presentation before anyone checks it. The manual research is painful. The AI shortcut makes it dangerous.
Parsing Facts vs. Interpreting Voice
The core constraint that shaped this design: brand tokens—fonts, hex codes, social handles—are verifiable facts. They live verbatim in CSS files, OpenGraph tags, and HTML attributes. No language model should ever generate them. They should be read.
Brand voice, on the other hand—the adjectives describing a brand’s tone, its audience positioning, its editorial register—is genuinely subjective. A bounded model is exactly the right tool for that.
Split the pipeline at the extraction boundary. Regex handles anything that is a verifiable string in a document. A typed model handles everything that requires judgment. They never share a code path.
One approach I actively rejected: using a vision model to read a rendered screenshot of a stylesheet. It costs money per call, it can hallucinate, and it ignores the fact that the ground truth is already machine-readable text. When your data is structured, use a parser—not a probabilistic approximator.
Automated Brand Reconnaissance
CCI runs five sequential stages: it discovers the client’s verified web presence via a 7-query Tavily matrix, crawls up to 8 pages via Firecrawl, extracts CSS typography and color tokens via compiled regex (zero model cost), scores the extracted palette against WCAG 2.1 contrast math, and assembles the final Designer Intelligence Pack via Python string templating. The model never touches the output file.
A typical run for a mid-size brand completes in under 30 seconds and returns a structured pack that would have taken a junior designer 40 minutes to compile by hand.
{ "brand": "Maison Living", "fonts": ["Inter", "Playfair Display"], "colors": ["#3C2A21", "#FFF8EA", "#8B6954"], "wcag_contrast": 11.4, "wcag_status": "AAA_PASS", "brand_voice": "warm, editorial, considered", "hex_drift_rate": 0.00 }
5-Stage LangGraph Linear Pipeline
Each stage is a typed LangGraph node with a defined input schema, output schema, and a single invariant it is structurally prohibited from violating. Click any stage card to read its implementation, input state, and output state.
Search → Crawl → Extract (regex, $0.00) → Score (WCAG math, $0.00) → Pack (template, $0.00)
Discovery Node (Tavily Query Matrix)
Constructs a deterministic 7-query matrix across official brand websites, Instagram, LinkedIn, news releases, and brand guidelines. Dispatches requests asynchronously and stores raw URLs into IntelligenceState.discovered_urls.
Three Decisions That Define the Architecture
Using Regex for CSS Extraction
A vision model asked to extract the font stack from a CSS file costs API credits, introduces latency, and can hallucinate plausible-sounding values. A compiled regex pattern against raw HTML and linked stylesheets runs in microseconds, is deterministic, and is verifiably correct. For any fact that exists as machine-readable text, a parser will always outperform a probabilistic model.
CCI extracts @font-face declarations, font-family rules, Google Fonts <link> hrefs, and CSS custom property hex values using three compiled regex patterns. Zero model involvement. Zero API cost. Zero drift risk.
# Three compiled patterns cover common CSS token patterns FONT_FACE = re.compile(r'@font-face\s*\{[^}]*font-family\s*:\s*["']?([^"';\}]+)', re.I|re.S) COLOR_PROP = re.compile(r'--[\w-]+\s*:\s*(#[0-9a-fA-F]{3,8}|rgb[a]?\([^)]+\))') GFONTS = re.compile(r'fonts\.googleapis\.com/css[^"']*family=([^&"']+)') def parse_css_tokens(html: str, css_sheets: list[str]) -> BrandTokens: fonts = FONT_FACE.findall('\n'.join(css_sheets)) colors = COLOR_PROP.findall('\n'.join(css_sheets)) gfonts = GFONTS.findall(html) return BrandTokens(fonts=fonts, colors=colors, google_fonts=gfonts)
Static Synthesis Template
In a typical multi-stage LLM pipeline, a downstream synthesis prompt re-reads the entire conversation and regenerates the final report. During this second pass, models frequently drift—subtly altering hex codes, rounding contrast ratios, or inventing font weights that were never extracted.
CCI eliminates this structurally. The synthesis_node is a pure Python function. It formats a static Markdown template using direct string interpolation from the typed IntelligenceState object. No LLM is in the loop. CSS tokens flow from state directly into the output file.
def synthesis_node(state: IntelligenceState) -> Dict[str, Any]: # Pure string template — no LLM call in this node profile = state.brand_profile report = render_pack_template(profile, state.contrast_report) return {"designer_pack_markdown": report, "success": True}
Typed LangGraph State as the Integration Contract
A flat Python dict passed between pipeline stages fails silently. A typo in a key name, a missing field, or a wrong type propagates through three more stages before you see an error—usually in the final output, after API credits have already been spent.
IntelligenceState is a TypedDict that acts as a typed contract between every node. Each node declares exactly which keys it reads and writes. Type checkers flag missing fields during development, preventing silent propagation of bad keys.
class IntelligenceState(TypedDict): brand_name: str # Input website: str discovered_urls: list[str] # Stage 01 → 02 raw_html: str # Stage 02 → 03 css_sheets: list[str] brand_profile: BrandProfile # Stage 03 → 04 (Pydantic) contrast_report: ContrastReport # Stage 04 → 05 designer_pack_markdown: str # Final output success: bool
Run the Full Suite Locally in Under 4 Seconds
The full test suite runs offline against pre-recorded fixture data. Zero API keys, zero network calls, zero spend required to verify the implementation.