A close-up portrait of a man with a salt-and-pepper beard wearing a white collared shirt against a textured beige background.
A close-up portrait of a man with a salt-and-pepper beard wearing a white collared shirt against a textured beige background.

One branding object read by every surface

Jesse James Richard
|
Mar 26, 2026
|
7 min read
#Architecture
#AI & Agents

A marketing agency running forty client accounts has a job nobody outside the industry sees. Keeping each client looking like themselves across everything at once.

The website, the email campaigns, the social cards and the landing pages all carry the same blue, the same font and the same voice, for forty different companies, and they keep carrying it as those companies grow and change. Brand consistency at that scale is an ongoing, expensive job, and one Giant Context tries to make disappear.

Why brand consistency slips

Brand consistency is the difference between a company that looks like a real business and one that looks assembled from parts. An audience notices, without being able to say why, when the email that arrives does not match the website it links to. Agencies charge for consistency because holding it is work, and across dozens of clients and dozens of surfaces it is a lot of work.

In most tools the brand lives in many places at once. The website has the brand colour pasted into its theme. The email template has the same colour typed in again. The social card generator has it a third time. Each of those is a copy, and copies drift. Someone tweaks the website's blue and forgets the email. A client rebrands and the change lands on the homepage this week, the newsletter next month, the old landing pages never.

Nobody decides a brand should fragment. It fragments because it exists in twenty copies and no two get updated together. Across forty clients that becomes a vigilance job nobody finishes, which is what makes it worth real money to solve.

The object

So a brand exists in exactly one place. One row holds the whole visual and creative identity, and there is no per-surface settings page anywhere in the platform.

The branding row

// core.project_brandings{  // media  logoUrl, logoDarkUrl, faviconUrl,
  // colour  colorPrimary, colorSecondary,  colorSuccess, colorError, colorWarning, colorInfo,  backgroundLight, backgroundDark, paperLight, paperDark,
  // type  fontHeading, fontBody, fontScale,  headingWeight, bodyWeight, lineHeight, letterSpacing,
  // shape and spacing  borderRadius, shadowIntensity, spacingScale,
  // component styles  buttonStyle,   // squared | rounded | pill  inputStyle,    // outlined | filled | standard  cardStyle,     // flat | elevated | outlined
  // AI design briefs  contentDesignBrief,   // how this brand writes  imageDesignBrief,     // how this brand looks in pictures  voiceDesignBrief      // how this brand sounds}

The enumerated styles and the numeric scales are pinned by check constraints in the database rather than validated in the application, so a fontScale outside 0.5 to 3.0 or a buttonStyle of anything but those three values cannot be written at all.

The interesting half is what a page stores when someone picks the brand's blue.

A block does not store #6366f1. It stores the token primary. At render, a resolver takes that token, reads the brand's palette, and returns the actual colour, falling back to the theme when a token has no brand value.

Which is why changing a brand's primary recolours every block that referenced primary, without any block being touched. There is no migration, no sweep across pages, no job that rewrites stored styles. The pages never held the colour, so there is nothing in them to update.

The colour picker in the editor puts the brand's semantic colours first, so an author picking a colour is usually picking a token rather than a hex. Raw colours are still available, and a raw colour is the thing that will not move when the brand does.

Two surfaces side by side, an email and a web page, carrying the same logo, colours and typography.
Two surfaces, one brand object. Neither holds a copy of the other's colours.

What reads it

The website server resolves the brand at render. It reads the app's branding id, selects the brand row, and passes it into the page as props, so there is no client fetch on the hot path. The page wraps its content in a scoped theme built from those values, and the colours, typography and shape become the theme for that subtree.

The editor uses the same primitive. Preview and production share one code path, which removes the class of bug where a page looks right in the builder and wrong when published.

Fonts are self-hosted per tenant. The brand's chosen body and heading fonts are served from the platform's own origin, metric-matched so the fallback occupies the same space, which means no cross-origin stylesheet request and no reflow when the real font arrives. Any font a tenant picks gets this, not only the defaults.

The knowledge base and the developer portal render through the same path as the website, so they inherit the theme and the fonts without a branding stack of their own. Email resolves the brand at send and composites its colours and logo into the message.

The share-image route is brand-aware too. A link shared from a tenant's site produces a card in the tenant's fonts, with the tenant's logo, tinted with the tenant's accent, rather than a generic platform card.

The AI reads it too

Three of the columns are written for the model rather than the theme.

The content brief says how the brand writes, the voice brief says how it sounds, and the image brief says how it looks in pictures. Every generation stage reads them, so the copy and the tone come out of the brand rather than out of the model's defaults, and every generated image is produced against the brand's visual direction rather than to a generic prompt.

A brand here is a design system and a creative brief in one row. The theme half decides what a page looks like. The brief half decides what the platform writes and draws when nobody is watching.

One brand or many

The schema allows a project to hold many named brands, and any app can point at whichever one it wants. An agency could run a client's main site on one brand and a sub-brand campaign on another, in the same project.

That is switched off. Today a project has one brand and every app in it reads that brand, and the difference between the two is a settings page nobody can reach. The plumbing underneath is unchanged, and turning it on is a decision about whether the flexibility is worth the extra thing a customer has to understand. Early on it is not.

What it does not cover yet

The object is a working design system and stops short of a full brand standard. It covers colour, typography, logo, component styling and the creative direction for content and imagery.

A brand book covers more. Letter kerning, the finer spacing rules, print specifications, the usage policy saying where the logo may and may not go. None of that is in the object today, and it is where the object grows. Every rule that moves into it is a rule the platform can hold on a customer's behalf without the customer being a designer.

What the agency stops doing

An agency puts a client's brand into one row and stops policing consistency. Forty clients become forty rows, each read by that client's every surface, each changeable in one place. The never-finished job of keeping brands from drifting becomes setting the object once and keeping it current.

Building fine-grained permissions

#Access Control
#Growth

Most software does not need this. Three roles and one boundary is cheaper and enough for teams working on shared material. The business case here name...

Jesse James Richard

|

Mar 20, 2026
Read previous

Building something like this

I'm Jesse. I build platforms end to end, and I'm open to work. If this is the kind of engineering you need, get in touch.

Contact Jesse
Home
About
Contact
Sitemap
Privacy Policy
Terms of Service
Cookie Policy
Building one brand object | Jesse James Richard