Brand customization
A Cobuntu integration has two chrome surfaces and Cobuntu makes both wear the customer's brand:
The customer's landing is the visual source of truth. Cobuntu
pages + Cobuntu widgets pull from that same source, so a visitor
who clicks from yourdomain.com/about (landing) to
yourdomain.com/events (Cobuntu page) experiences one continuous
brand.
Step 1 — The leader connects their landing
In cobuntu-admin at /[communityTag]/customize, there's a
"Sync from landing" section. The leader pastes their landing URL
(or it's auto-detected from landingPageUrl on their community
record) and hits Sync now.
The scraper opens the landing in a real headless browser, not just
regex on HTML — that lets it pick up CSS variables computed at
runtime, web-font URLs from @font-face declarations, and
button-radius / card-radius defaults from the rendered DOM.
The diff step is intentional. A community might already have a
manually-set brandColor and the new scrape produced a slightly
different shade — the leader sees both and chooses.
Step 2 — The themeConfig contract
What ends up in communities.themeConfig (a JSONB column) is a
flat set of brand tokens:
{
"brandColor": "#D4AF37",
"accentColor": "#F2D47E",
"bgColor": "#0A0A0A",
"textColor": "#E0E0E0",
"headingFont": "Playfair Display",
"bodyFont": "Montserrat",
"headingFontUrl": "https://fonts.gstatic.com/...",
"bodyFontUrl": "https://fonts.gstatic.com/...",
"buttonRadius": "0px",
"cardRadius": "22px",
"inputRadius": "12px",
"primaryBtnBg": "linear-gradient(135deg, #D4AF37 0%, #F2D47E 100%)",
"primaryBtnText": "#000000",
"secondaryBtnBg": "rgba(255,255,255,0.05)",
"secondaryBtnText":"#E0E0E0",
"linkColor": "#D4AF37"
}Everything is optional — missing tokens fall back to a Cobuntu default. Each token has a documented purpose; see community-config for the full table.
Step 3 — How Cobuntu pages pick them up
The community-app's root layout reads themeConfig server-side
and emits inline CSS variables on <html>:
<html style="
--brand-color: #D4AF37;
--accent-color: #F2D47E;
--bg-color: #0A0A0A;
--text-color: #E0E0E0;
--heading-font: Playfair Display;
--body-font: Montserrat;
--button-radius: 0px;
--card-radius: 22px;
--primary-btn-bg: linear-gradient(135deg, #D4AF37 0%, #F2D47E 100%);
/* ... */
">Every component on every Cobuntu page references these variables:
.btn-primary {
background: var(--primary-btn-bg);
color: var(--primary-btn-text);
border-radius: var(--button-radius);
font-family: var(--body-font);
}So /feed, /events, /marketplace, /profile, etc. all paint
in the customer's brand automatically. There's no per-page
override — every Cobuntu surface is derived from the same JSON
column.
Step 4 — Widgets inherit the same tokens
When you embed a Cobuntu widget on your landing — <div data-cobuntu-cart> or <CobuntuAuth /> — it picks up CSS
variables from its own :root. If you've also configured
themeConfig in cobuntu-admin, those tokens are exposed as
--cobuntu-* variables and the widget will use them.
:root {
/* Set these once at the top of your landing's CSS — or just
let cobuntu-admin's /customize sync set them automatically. */
--cobuntu-bg: var(--brand-color, transparent);
--cobuntu-color: var(--text-color, inherit);
--cobuntu-radius: var(--button-radius, 8px);
--cobuntu-font: var(--body-font, inherit);
--cobuntu-hover-bg: var(--accent-color, rgba(0,0,0,0.05));
}Three customization levels exist for each widget:
See widgets for the per-widget reference (cart, auth, messages, notifications, search). The same tokens drive every one — set them once, every widget on your page paints consistently.
What about cobuntu-admin itself?
cobuntu-admin (the surface community leaders use) is not
themed by themeConfig. It's Cobuntu's own dashboard — same
brand, same chrome, regardless of which community the leader is
managing. The /customize page edits a community's tokens; the
admin itself stays in Cobuntu's house style.
Trade-offs of automatic sync
Pros.
- Zero manual work for leaders. Paste a URL → press button → Cobuntu pages look like the landing.
- One source of truth. The landing's CSS is the canonical brand; Cobuntu just reads it.
- Re-syncs at any time. Update the landing, hit Sync, Cobuntu pages update on next request.
Cons.
- The scrape is an opinion, not a contract. If your landing uses CSS-in-JS with runtime-computed colours, the scraper might pick the wrong shade. Hence the diff step — the leader confirms before writing.
- Web fonts loaded via JavaScript (Google Fonts variable fonts,
some Adobe Fonts loaders) sometimes aren't visible to the
scraper. The headless browser waits for
loadevent but not for late-loaded fonts. Manual override is the workaround.
Going deeper
- Widgets reference — per-widget data-attribute and CSS variable contracts
- community-config — the full themeConfig schema with every supported token
- REST API: branding — PATCH endpoint if you're scripting this from your own tooling instead of using cobuntu-admin