Widgets
Theming

Theming

Every Cobuntu widget — auth, cart, messages, notifications, nav, search — reads its colors, radii and fonts from a shared set of --cobuntu-* CSS custom properties. There are three ways to control them, in order of how much work they are:

  1. Do nothing — auto-theme. The widget bundle fetches your community's brand config on mount and writes the right vars to :root for you. This is the default and what most customers want.
  2. Override per page — set the vars yourself in a <style> block on the landing. Useful when the auto-fetched theme isn't what you want, or when you don't have a Cobuntu community at all (rare).
  3. Override per widget mount — set vars inline on each <div data-cobuntu-*> mount node. Useful when one widget on a page needs to look different from the others.

Auto-theme (default)

On every page that mounts at least one widget script, the bundle:

  1. Reads location.hostname (e.g. yourdomain.com).
  2. Hits GET https://api.cobuntu.com/api/communities/by-domain/<host> — a public endpoint that returns the community's themeConfig.
  3. Maps your brand colours to --cobuntu-* vars and injects a <style> tag into <head> — wrapped in a low-priority @layer cobuntu-preset.

Auto-theme applies your colours only — your brand colour to the badges + accent, and your background/text to the drawer panels. It does not set the icon-button shape: the triggers (cart, messages, notifications, account) default to a flat, transparent chrome. Any shape — borders, pills, fills, padding — is entirely your own CSS (--cobuntu-border, --cobuntu-bg, --cobuntu-radius, …). There are no "flat / glass / bordered" modes to pick from; you just write the CSS you want.

The same widget bundle runs on the community's own pages (e.g. yourdomain.com/events) and on your landing — the visual result is identical.

Your own CSS always wins. Because the auto-theme is injected inside @layer cobuntu-preset, it's a default — any --cobuntu-* value you set yourself (in a normal, unlayered <style>/CSS rule, or inline on a mount) overrides it, regardless of source order. So you never have to fight the auto-theme: set only the vars you want to change, and the rest fall back to your brand config. (Unlayered CSS beats any @layer in the cascade — this is a standard CSS guarantee, not a Cobuntu trick.)

Idempotent. The widget checks for two style IDs before injecting:

  • cobuntu-community-theme-vars (its own injection)
  • cobuntu-widget-theme-style (the community-app's <WidgetThemeStyle> React component, which runs before any widget script on community-app pages)

If either is present, the fetch is skipped. So even if you have multiple widgets on the page, only one fetch happens.

Failure mode. If the hostname isn't registered as a Cobuntu custom domain, the endpoint returns 404 and the widget falls back to its built-in defaults (white background + dark text + gold badge). Nothing crashes; no console error in production builds.

Override per page

Auto-theme is fine for 90% of customers, but if you want to hard-pin the values — for QA, for a temporary brand override, or because your landing is on a host that isn't a Cobuntu custom domain — set the vars yourself:

<style>
  :root {
    --cobuntu-bg:                  #0A0A0A;
    --cobuntu-color:               #E0E0E0;
    --cobuntu-badge-bg:            #D4AF37;
    --cobuntu-badge-text:          #000000;
    --cobuntu-radius:              0px;
    --cobuntu-card-radius:         22px;
    --cobuntu-input-radius:        12px;
    --cobuntu-font:                "Montserrat", sans-serif;
    --cobuntu-heading-font:        "Playfair Display", serif;
    --cobuntu-link-color:          #D4AF37;
    --cobuntu-drawer-bg:           #0A0A0A;
    --cobuntu-drawer-color:        #E0E0E0;
    --cobuntu-primary-btn-bg:      linear-gradient(135deg, #D4AF37, #F2D47E);
    --cobuntu-primary-btn-text:    #000000;
  }
</style>

Variables you set this way always win over the auto-fetched ones — the auto-theme ships inside @layer cobuntu-preset, and any unlayered CSS rule (like the <style> above) beats a layer in the cascade no matter where it sits in the document. You only need to declare the vars you want to change; everything else falls back to the auto-theme. Just keep your rule unlayered (a plain :root {…} — don't wrap it in your own @layer).

Override per widget mount

For one-off cases (a "dark mode toggle" on a single button, a brand-color cart drawer on an otherwise neutral page), use inline styles on the mount node. Variables inherit, so anything you set on the parent flows through to the widget's internal markup.

<div
  data-cobuntu-cart
  style="
    --cobuntu-bg: #ffffff;
    --cobuntu-color: #1a1a1a;
    --cobuntu-badge-bg: #ef4444;
  "
></div>

Full variable contract

These vars are part of the v1 stable contract. Names and meaning won't change in v1; new vars may be added in minor versions.

Trigger surface

VariableTypeWhat it controls
--cobuntu-bgcolorButton / icon background
--cobuntu-colorcolorForeground (text + icon stroke)
--cobuntu-hover-bgcolorBackground on hover (falls back to bg)
--cobuntu-hover-colorcolorForeground on hover (falls back to color)
--cobuntu-bordershorthandOptional border on the trigger
--cobuntu-radiuslengthButton corner radius
--cobuntu-paddingshorthandButton padding (button variants only)
--cobuntu-fontfont-familyBody font for trigger labels
--cobuntu-font-sizelengthTrigger label font size
--cobuntu-font-weightweightTrigger label weight
--cobuntu-letter-spacinglengthTrigger label spacing
--cobuntu-text-transformkeywordTrigger label transform

Badge

VariableTypeWhat it controls
--cobuntu-badge-bgcolorUnread-count badge background
--cobuntu-badge-textcolorUnread-count badge foreground

Drawer / panel (auth + cart + notifications)

VariableTypeWhat it controls
--cobuntu-drawer-bgcolorDrawer panel background (falls back to --cobuntu-bg)
--cobuntu-drawer-colorcolorDrawer panel foreground (falls back to --cobuntu-color)
--cobuntu-card-radiuslengthInner card corner radius
--cobuntu-input-radiuslengthInput field corner radius
--cobuntu-primary-btn-bgcolor/gradient"Accept" / "Save" button background
--cobuntu-primary-btn-textcolor"Accept" / "Save" button foreground
--cobuntu-link-colorcolorDrawer link color
--cobuntu-accentcolorOne-token brand colour for the account avatar + sign-in button (the explicit *-bg/*-text tokens still win)
--cobuntu-on-accentcolorForeground on --cobuntu-accent
--cobuntu-drawer-hovercolorRow / item hover background. Defaults to a color-mix off the drawer text colour, so it adapts to any brand automatically
--cobuntu-drawer-bordercolorDividers / borders inside the drawer. Same auto-adapting default
--cobuntu-backdropcolorThe dim scrim behind an open drawer
--cobuntu-dangercolorDestructive actions (e.g. "Remove", account delete)

Brand-agnostic by default. Every drawer surface that isn't an explicit brand colour (hovers, dividers, the close affordance) derives from the drawer's own text colour via color-mix, so the widgets adapt to a light or dark brand with zero config. Set --cobuntu-accent + --cobuntu-drawer-bg/-text and the whole drawer reskins to your brand.

How auto-theme maps your themeConfig

For reference — these are the exact field-to-var mappings the widget applies when it fetches your theme:

themeConfig.bgColor          → --cobuntu-bg          + --cobuntu-drawer-bg
themeConfig.textColor        → --cobuntu-color       + --cobuntu-drawer-color
                                                     + --cobuntu-hover-color
themeConfig.brandColor       → --cobuntu-badge-bg
themeConfig.primaryBtnText   → --cobuntu-badge-text
themeConfig.buttonRadius     → --cobuntu-radius
themeConfig.inputRadius      → --cobuntu-input-radius
themeConfig.cardRadius       → --cobuntu-card-radius
themeConfig.bodyFont         → --cobuntu-font
themeConfig.headingFont      → --cobuntu-heading-font
themeConfig.linkColor        → --cobuntu-link-color
themeConfig.primaryBtnBg     → --cobuntu-primary-btn-bg
themeConfig.primaryBtnText   → --cobuntu-primary-btn-text

The themeConfig itself is what you edit in cobuntu-admin → Customize → Branding. Changes there reflect on your landing within seconds of save (no widget version bump needed — each page-load fetches fresh).

Versioning

The variable names + auto-theme behavior are v1 stable. They won't change while /widgets/v1/*.js is current. New widgets shipped under v1 read the same vars. A future v2 will live at /widgets/v2/*.js and may introduce new vars or rename existing ones; both versions will coexist for the standard deprecation window.