Brand Guide MCP — Slack Response Design Proposal
Date: 2026-04-21 Author: Eric + Claude (design pass, pre-implementation) Principle being honored: "premium brand agent, not chat log" (PRD)
The bar
Every /brand response is a product surface. Not a formatted dump of brand-guide JSON — a considered editorial layout that feels like something Linear, Stripe, or Arc would ship inside Slack.
Pass-fail criterion per response: 1. 2-second scan test: Can I find the section I want in 2 seconds? 2. Hierarchy test: Is it obvious what's a label, what's body, and what's metadata? 3. Rhythm test: Does the layout have tight groupings + generous gaps, or is it a flat wall of text? 4. Slop test: Would I mistake this for a generic ChatGPT-style bullet-list output? If yes, fail.
Design language (applied to all 4 responses)
Slack's Block Kit gives us roughly five usable "size levels." We anchor a shared language across every category:
| Role | Primitive | Visual weight |
|---|---|---|
| Category name (top anchor) | header block |
Biggest bold |
| Subsection label ("Mission", "Tagline", "Values") | header block |
Same as category — visual hierarchy comes from position + divider above it |
| Body paragraph | section with mrkdwn |
Medium body |
| List with bold labels | rich_text_list with rtBold() first-child |
Medium body |
| Copyable text (tagline, pitch, boilerplate) | rich_text_preformatted |
Monospace + native copy button |
| Metadata / caption (typeface source, weight list, "last updated") | context block |
Smallest muted |
| Traits as pills | rich_text with inline rtCode() per trait |
Monospace chip style |
| Color swatches | rich_text with {type: "color"} element |
Native swatch (best-in-class) |
Rhythm: dividers between major subsections ONLY, not between every block. Tight groups of (header → content), generous breaks between groups. This matches the /arrange principle of "tight grouping for related, generous between groups."
No attachments (legacy), no images (not SVG-friendly), no custom emoji. Pure Block Kit. This keeps rendering consistent across iOS / web / desktop Slack.
Shared footer on every response (new):
context: Full brand guide → california-forever-brand-guide.vercel.app · Updated <date>
Ties the Slack surface back to the canonical source. Tiny. Always there. Premium touch.
Per-category specs
1. /brand messaging
Content: tagline · elevator pitch · 5 key-message pillars · boilerplate · naming conventions
The hero is the tagline — the one line clients will copy most. Give it the strongest copy-button treatment. The boilerplate is the second copy-hero (press/partner materials). Everything else is reference.
header: Messaging
divider
header: Tagline
rich_text_preformatted: "Building the next great American city." ← copy button
divider
header: Elevator Pitch
section (mrkdwn paragraph): California Forever is a plan to build… ← reads as prose
divider
header: Key Messages
rich_text_list: ← bold pillar + detail
• Good Jobs — 30,000 new jobs across construction…
• Affordable Housing — 170,000 new homes…
• Clean Energy & Sustainability — …
• Open Space & Walkability — …
• California's Legacy — …
divider
header: Boilerplate
rich_text_preformatted: [full paragraph] ← copy button
divider
header: Naming Conventions
rich_text_list:
• Default: California Forever — All public-facing materials
• Internal: `CF` — Internal docs, Slack only
• Legal: California Forever, LLC — Contracts only
• ✗ Never: `Cal Forever`, `CalForever`, `CA Forever` ← emoji-anchored don't
context: Full brand guide → … · Updated <date>
Rationale:
- Elevator pitch in section (not preformatted) — it's a paragraph people read, not a snippet to paste. Preformatted + paragraph = boxy and awkward.
- Tagline + boilerplate in preformatted — both are designed to be copied verbatim. Copy button earns its keep.
- Key Messages as rich_text_list, not 5 preformatted blocks — these are reference, not paste-targets.
- "Never" line gets an emoji anchor to signal "stop" without needing a different block type.
2. /brand typography
Content: 2 typefaces (name, category, source, weights, usage map) · 8-level type scale
The problem: We can't render the typefaces. So the "hero" has to be structure + metadata, not a sample. Each typeface becomes a tight specimen card — name + one-line metadata caption + usage list + weights list.
header: Typography
divider
header: Milo Serif OT
context: Serif · Self-hosted (licensed) ← muted metadata line
rich_text_list:
• Headings — Medium (500) for h1–h4
• Display — Bold (700) or ExtraBold (800) for hero headlines
• Body — Regular (400) for pull quotes and editorial text
context: Weights · Regular · Medium · Bold · ExtraBold ← muted weight line
divider
header: Outfit
context: Sans-Serif · Google Fonts
rich_text_list:
• Headings — Medium (500) for h5–h6
• Body — Regular (400) for paragraphs and long-form
• UI — Medium (500) for buttons, labels, navigation
• Captions — Regular (400) at smaller sizes
context: Weights · Light · Regular · Medium · Semibold · Bold
divider
header: Type Scale
rich_text_list:
• H1 — `85px · 500 · Milo Serif OT` ← inline-code spec (copy button per row)
• H2 — `56px · 500 · Milo Serif OT`
• H3 — `40px · 500 · Milo Serif OT`
• H4 — `28px · 400 · Milo Serif OT`
• H5 — `20px · 500 · Outfit`
• H6 — `12px · 600 · Outfit`
• Body — `19px · 400 · Outfit`
• Caption — `15px · 400 · Outfit`
context: Full brand guide → … · Updated <date>
Rationale:
- Each typeface's metadata becomes a context line (not inline italic in the heading). Gives real visual weight separation between name (big) and meta (small/muted).
- Weights get their own context line at the bottom of each specimen — visually stacks underneath the usage list without stealing focus.
- Type scale rows use inline-code for the spec (85px · 500 · Milo Serif OT) — copy button per row means a designer can grab the exact spec string for a PR or comment.
- Hierarchy: category header → typeface header → context meta → usage list → context weights. Four levels of visual weight without any custom styling.
3. /brand voice
Content: overview · 3 traits · tone by context (5) · 4 writing rules · 4 good/bad example pairs
The hero is the examples. Traits, tones, and rules are reference — the "This / Not This" pairs are where voice actually lives. De-emphasize the DON'Ts so the DOs lead the eye.
header: Voice & Tone
section: [overview paragraph] ← opening prose
divider
header: Traits
rich_text_list:
• Authentic — We say what we mean. No corporate jargon…
• Hopeful — We believe in California's future…
• Direct — We respect people's time…
divider
header: Tone by Context
rich_text_list:
• Website — Confident, clear, benefit-focused
• Email — Warm, direct, action-oriented
• Social — Casual, engaging, personality-forward
• Support — Patient, clear, solution-focused
• Press — Professional, factual, concise
divider
header: Writing Rules
rich_text_list:
• Capitalization — Sentence case for headlines and buttons…
• Punctuation — Oxford comma. Period after full sentences…
• Numbers — Spell out one through nine. Numerals for 10+
• Contractions — Use them. We're, it's, don't — they sound human.
divider
header: This / Not This
For each of the 4 example pairs:
rich_text: ✅ "A new community for California." ← bold + visible
context: "We are pioneering a paradigm-shifting community…" ← muted, smaller
(blank line between pairs via separate rich_text blocks)
context: Full brand guide → … · Updated <date>
Rationale:
- Overview is a section (mrkdwn paragraph) — sets the stage, doesn't need list treatment.
- Each example pair visually pairs a primary ✅ (full weight, rich_text) with a muted ❌ (context block, smaller+gray). This is the single most impactful design decision in the whole doc — it mirrors the brand principle ("don't sound like this") by literally making the bad example visually recede.
- No heavy divider between do/don't — they're a pair, not two groups.
4. /brand foundation
Content: mission · vision · story · 4 values · 5 personality traits · audience
The hero is either Mission or Values depending on who's asking. Give them equal visual weight. Personality as code-pills creates a distinctive, branded look that's pure Block Kit.
header: Brand Foundation
divider
header: Mission
section: To create a new community where Californians can thrive…
divider
header: Vision
section: A walkable, sustainable community that proves…
divider
header: Our Story
section: [story paragraph]
divider
header: Values
rich_text_list:
• Community — We're building more than houses…
• Sustainability — Clean energy, open space…
• Innovation — We're rethinking how communities get built…
• Transparency — We show our work…
divider
header: Personality
rich_text: `Authentic` `Hopeful` `Bold` `Grounded` `Visionary` ← inline-code pills
divider
header: Audience
section: Californians looking for a better way to live…
context: Full brand guide → … · Updated <date>
Rationale:
- Three paragraph sections (Mission / Vision / Our Story / Audience) all use section with mrkdwn body — consistent reading rhythm.
- Personality becomes inline-code pills — this is the distinctive design moment. Each trait is copyable (code = copy button), each has a monospace chip appearance, and together they read like a tag cloud but controlled.
- Values use rich_text_list so bold names scan while descriptions flow naturally.
Small polish moves (post-approval)
Additions that push beyond the baseline once the structure's right:
- Emoji category anchors. One emoji prefixing each top
header.📣 Messaging,🔤 Typography,🗣 Voice & Tone,🌱 Brand Foundation,🎨 Brand Colors. Slack'sheaderblock supports emoji. Gives each response a distinct visual signature. - Shared context footer.
contextblock at the bottom of every response:Full brand guide · california-forever-brand-guide.vercel.app · Updated {lastModified}. Ties every response back to the source of truth. - "Key" example per trait. In
/brand voice, after the traits list, pick the strongest ✅ example from each trait and pin it as a callout. Makes traits feel alive instead of abstract. - Preset comparison in
/brand typography. Add a single-row example pair showing heading vs body in mrkdwn:*H1 weight*next to regular body — visual weight demo using Slack's own rendering.
Polish 1 + 2 are cheap wins. Polish 3 + 4 are nice-to-haves.
What happens next
- Eric reviews this doc and pushes back on anything that isn't right.
- We iterate on the design spec until it passes the 4 tests up top.
- ONLY THEN do we edit
lib/slack/format.ts— applying the approved spec, not freestyling. - Deploy + verify in Slack.
- Commit as a clean atomic change that reverts the reactive WIP.