Skip to content

Canonical Rebrand — Brand-Surface Map

Authored S406 (2026-06-23) from a 4-angle codebase sweep (app + docs-site + mcp-apps, 65 surfaces). Companion to the docs-site wiring tracker CANONICAL-REBRAND-FOLLOWUP.md (repo-slug layer, mostly done) — this doc is the visual / product-identity layer that the brand-direction decision unblocks.

No real users yet (S406, Liam). The MCP server name, plugin download filename, the two mcp-app UI strings, and all cosmetic items can be changed without any risk — there are no saved connectors or live installs to break. The connector-identity caveat noted against the MCP server-name below is therefore moot; treat every string item as a free edit. This means the brand session is gated on one thing only: the visual wordmark/logo decision.

The app brand is config-driven through a single seam: lib/branding/clients/default.json → loaded by loadBranding() → exported as BRANDING (lib/client-config.ts:644) → consumed by every app UI / metadata / export surface.

Name-strings are already ~90% rebranded (productName / productShortName / organisationName = "Canonical"). What remains is only:

  • (a) visual assets still showing the old “KH” / “Knowledge Hub” marks, and
  • (b) hardcoded strings in surfaces that don’t import BRANDING (MCP server/apps, docs-site wordmark SVG) — all now zero-risk per the note above.

Legend: [L] logo-asset (redraw image) · [W] wordmark-render (text mark in UI) · [N] name-string (config/metadata text)

lib/branding/clients/default.json — the central brand constant. [N]

One JSON edit ripples to: <title> + favicons (app/layout.tsx), header logo + alt + sr-only (brand-logo.tsx), mobile drawer (site-header.tsx:168), login h1 + aria (login/page.tsx), OAuth consent (oauth/consent/page.tsx), DOCX/XLSX/PDF exports, RSS generator, provenance labels. Already set to “Canonical” for names — but still binds logoUrl / faviconSvgUrl to the placeholder /favicon.svg and supportEmail to the old @knowledgehub.dev domain. After editing, run bun run generate:branding to repopulate lib/branding/client-branding-map.generated.ts.

Runner-up: public/favicon.svg serves triple duty (browser favicon + header logo + drawer logo via logoUrl=/favicon.svg) and still shows the dark rounded-square “KH” lockup. Replacing this one asset fixes the most-seen app mark.

SurfaceKindLocationStatus
BrandLogo component (only logo-drawing component)[L]components/shell/brand-logo.tsx:26Config-driven, no code change — inherits asset swap
Site header (ONLY render site of BrandLogo)[W]components/shell/site-header.tsx:99Config-driven
Mobile drawer title (productShortName)[W]components/shell/site-header.tsx:168Config-driven
Home page heading[W]app/page.tsx:323Config-driven (already reads “Canonical”)

Note: if the new brand is a wide wordmark rather than a square icon, also update logoAspectRatio / logoMaxWidthPx (currently 1:1 / 32px) and add a separate logoUrlDark in default.json (none set today — dark mode falls back to light).

SurfaceKindLocationStatus
Login h1 + aria-label[W]app/login/page.tsx:608,614Config-driven
Login subtitle “Sign in to your knowledge base”[W]app/login/page.tsx:619HARDCODED — KH-flavoured copy, fix by hand
localStorage key kh-stay-signed-in[N]app/login/page.tsx:57,444Non-visible legacy prefix (free cleanup)
Login error page[W]app/login/error.tsx:26Config-driven
OAuth consent screen (3rd-party identity)[W]app/oauth/consent/page.tsx:86,180Config-driven
SurfaceKindLocationStatus
Root metadata: title / description / icons[N]app/layout.tsx:26-40Config-driven (cache-busted by commit SHA)
CLIENT_CONFIG.client_name = 'Knowledge Hub'[N]lib/client-config.ts:107HARDCODED legacy feature-config (NOT BRANDING) — reconcile to Canonical
Generated branding map[N]lib/branding/client-branding-map.generated.tsBuild artefact — regenerate, no manual edit
RSS <generator> tag[N]lib/intelligence/rss-generator.ts:67Config-driven

PWA gap (add, not replace): no app/icon.tsx, app/apple-icon.*, app/opengraph-image.*, apple-touch-icon, or site.webmanifest exist — i.e. there is currently no apple-touch-icon and no OG/social-share image for the app. The rebrand can opt to add these.

SurfaceKindLocationStatus
public/favicon.svg (favicon + header logo + drawer)[L]public/favicon.svgPLACEHOLDER — dark square, white “KH”. Triple-duty. Top app asset to redraw
public/favicon.png (raster fallback, required field)[L]public/favicon.pngPLACEHOLDER “KH” raster — re-export from new mark
Asset→slot bindings[N]lib/branding/clients/default.json:9,13,14Repoint logoUrl / logoUrlDark here if splitting wordmark vs icon
SurfaceKindLocationStatus
supportEmail = support@knowledgehub.dev[N]lib/branding/clients/default.json:7OLD DOMAIN — surfaces in OAuth consent / settings / error pages. Change to a canonical.* domain

MCP-app UIs (none import BRANDING — all literal edits, all zero-risk)

Section titled “MCP-app UIs (none import BRANDING — all literal edits, all zero-risk)”
SurfaceKindLocationStatus
MCP server handshake name: 'knowledge-hub'[N]app/api/mcp/[transport]/route.ts:101Machine name shown to Claude.ai/Desktop. Rename to canonical freely — no users → no connector breakage
MCP system-prompt persona (“AI assistant for the Knowledge Hub…”)[N]lib/mcp/resources.ts:810,939HARDCODED AI-facing copy
Settings → Connections config snippet (server key + plugin path)[N]components/settings/connections-section.tsx:396,403,494HARDCODED — must match the MCP server-name decision
Plugin download filename knowledge-hub-plugin.zip[N]app/api/plugin/download/route.ts:30,9HARDCODED user-visible download name
form-dashboard “View in Knowledge Hub →” + aria[W]mcp-apps/form-dashboard/src/app.ts:436,441,444HARDCODED — edit source AND rebuild bundle
reorient-me welcome copy[W]mcp-apps/reorient-me/src/app.ts:205HARDCODED — edit source AND rebuild bundle
Prebuilt bundle (bakes the two strings above)[N]lib/mcp/app-bundles.ts:340Must be rebuilt after editing mcp-apps sources

Note: per-app HTML <title> tags (“Bid Dashboard”, “Coverage Matrix”…) are feature names, not brand surfaces — no change needed.

Sales / PDF exports (all config-driven — inherit “Canonical”)

Section titled “Sales / PDF exports (all config-driven — inherit “Canonical”)”
SurfaceKindLocationStatus
DOCX bid cover page company name[W]lib/procurement/procurement-export-docx.ts:829,335-348Config-driven
DOCX export-types doc-comment (default: "Knowledge Hub")[N]lib/procurement/procurement-export-types.ts:58-59Stale comment only — cosmetic
XLSX workbook.creator metadata[N]lib/procurement/procurement-export-xlsx.ts:441Config-driven
Provenance / verification-history PDF (header + footer)[W]components/provenance/report-document.tsx:262,278Config-driven (closest thing to a branded PDF)
AI provenance label[N]lib/provenance/item-provenance.ts:83Config-driven
SurfaceKindLocationStatus
Header wordmark SVG (most visible un-rebranded surface)[W]src/assets/kh-wordmark.svgPLACEHOLDER — literally <text>Knowledge Hub</text>. replacesTitle:true makes it THE header. Redraw as “Canonical”; rename off kh- prefix
Starlight title:'Canonical' + logo.src + description[N]astro.config.mjs:34,37-40Title/description already rebranded; logo points at placeholder above
Docs favicon[L]astro.config.mjs (no favicon: key)GAP — uses Starlight default; add a Canonical favicon
editLink GitHub repo slug[N]astro.config.mjs:110Repoint if docs repo renamed
Site URL placeholder vercel-default-subdomain…[N]astro.config.mjs:~30Set real URL
Package identity (canonical-docs / canonical-internal)[N]package.json:2Already rebranded — internal only
Asset-gap already loggedCANONICAL-REBRAND-FOLLOWUP.md:90Confirms kh-wordmark.svg replacement is a known item

The wordmark/logo decision is the only gating dependency. Ordered by what it unblocks:

  1. Decide the core identity: wordmark-vs-icon lockup, primary mark, light + dark variants, brand-primary colour. (This is the single decision; everything below is execution.)
  2. Decide the mark shape → determines whether you also update logoAspectRatio / logoMaxWidthPx and add a separate logoUrlDark in default.json (square icon = swap-only; wide wordmark = config change too).
  3. Produce the app asset set: public/favicon.svg (redraw), public/favicon.png (re-export). Optionally add the missing apple-icon + opengraph-image + webmanifest.
  4. Produce the docs-site wordmark: replace src/assets/kh-wordmark.svg and add a docs favicon → wire into astro.config.mjs.
  5. Edit the central config (default.json): repoint logoUrl / logoUrlDark / favicon paths to the new assets, fix supportEmail to a canonical.* domain, refresh tagline → then bun run generate:branding.
  6. String sweep — all zero-risk, do anytime (no users): MCP server name, system-prompt persona, settings snippet, plugin ZIP filename, the two mcp-app UI strings → rebuild the bundle (lib/mcp/app-bundles.ts); plus client_name constant, stale doc-comments, login subtitle, kh- localStorage/filename prefixes.

Bottom line: the visual decision (step 1) unblocks steps 2–5; step 6 is independent string work that can land in parallel — and, with no users to break, carries no risk.

  • CANONICAL-REBRAND-FOLLOWUP.md (repo root) — the docs-site wiring layer (repo-slug repoint), mostly complete.
  • Design system: design/warm-meridian-implementation-spec.md, design/warm-meridian-philosophy.md, design/token-system.md (brand-primary colour lives in the token system).
  • Claude Design canvas: the .design-sync/ lane (Warm Meridian primitives synced to the Canonical claude.ai/design project) — where the wordmark/typography exploration happens; brief the design agent via .design-sync/conventions.md.