One color is not an identity
Most B2B sites adopt a single brand color and apply it everywhere: the CTA button, the logo, the section dividers, the social-share previews. This works when the audience is one persona and the message is one promise. It stops working the moment the audience is plural.
YPAI publishes for at least five distinct audiences: AI/ML practitioners, compliance officers, security engineers, product leaders evaluating buy-vs- build, and operations teams running the deployed systems. They each read different content, use different vocabulary, and care about different risks. Painting every page the same violet treats them as one audience when they are five.
The temptation is to fix this with layout: different page templates per audience. But layout is expensive — every new template doubles the cross-cutting concerns (SEO, accessibility, motion, dark-mode). Layout is also slow to recognize: a reader needs three seconds of scanning to detect a different template. Color is recognized in milliseconds.
The hub as the unit of identity
A content hub is a coherent body of work with a shared audience: the AI Compliance hub, the LLMOps hub, the Security hub. Each hub publishes dozens of articles, a landing page, a few tools, and case studies. The hub is the smallest grouping a reader cares about and the largest grouping a single author can hold in their head.
Identity at the hub level means: each hub gets one accent color, and that color is used consistently across every surface the hub owns — article body, case-study card, navigation chip, social-share OG image, and the rest. The reader learns the mapping after two visits. Once learned, a glance is enough: cyan means compliance, amber means ops, violet means research.
The trick is making this cheap to implement. The expensive way is to write
a dedicated stylesheet per hub. The cheap way is what
src/lib/hub-tokens.ts does: every hub-aware component reads
two CSS custom properties — --hub-accent and
--hub-accent-rgb — and the page-level container sets those
properties from a single taxonomy entry.
How the propagation works
The single source of truth is src/lib/taxonomy.ts, which
registers every hub with title, tagline, icon, and hex color. From there:
hubAccentVars(slug)returns the CSS variables that get spread onto a wrapping element.hubColor(slug)returns the hex for build-time scripts (OG image generation, llms.txt, structured data).hubRgb(slug)returns the "r, g, b" triplet so components can composergba(var(--hub-accent-rgb), 0.12)for tinted backgrounds.
Every hub-aware component — HubCard, ArticleHero,
TableOfContents, FootnoteList, and twenty-three
others — references those custom properties. None of them know which hub
they belong to. The hub identity is set by the page-level wrapper and
inherited through the cascade. Components stay portable.
The result: adding a new hub is one PR. One line in
taxonomy.ts (the hub registration), one route, and the entire
site picks up the tint. No new CSS, no new components, no per-hub
overrides. The Week-3 audit found 23 hub-aware components; not one of
them needed a change when we added the LLMOps hub last sprint.
The accent is not the brand
Crucial distinction: the hub accent is not the YPAI brand color. The brand color is reserved for the global chrome — the masthead logo, the cross-hub navigation, the footer. The hub accent operates one layer down, inside the content surface. The two never compete because they never occupy the same region: the brand owns the page frame; the hub owns the content body.
Most one-color brands fail at exactly this boundary: when a content area wants to express something different from the chrome, the only available knob is the brand color, which has to remain stable. So content stays monochrome, and the reader never gets a visual cue about which kind of article they are reading. By reserving accent space at the hub level, we keep the brand stable and let content earn its own visual territory.
What this commits us to
The implication is structural: every new content surface has to declare its hub up front. There is no "unaffiliated" content. If an article does not fit any existing hub, the right move is to argue for a new hub, not to publish in default-brand-violet.
Operationally:
- No component sets a hex color directly. Hub-aware components read
var(--hub-accent); non-hub components readvar(--ds-color-accent), which falls back to the brand. - OG image generation reads from the taxonomy, so every share preview matches the page.
- The structured-data
articleSectionfield is the hub title — search engines see the same hierarchy a reader does.
The payoff is recognition. A reader who has visited the site twice already knows what amber means. A reader who shares an article on LinkedIn ships a preview tinted the right color, so their followers see the topic before they read the headline. The system spends pixels in the place where pixels do the most work — and pays zero per-page implementation cost.