White-Label Branding

White-Label Branding

With the right license, a self-hosted Huitzo deployment can be fully white-labeled: the product name, accent colors, fonts, logos, favicon, and transactional emails change across the Hub, hosted dashboards, login screen, and emails — driven entirely by a branding manifest you mount at the deployment root. No code, no rebuild: every brand is a data directory.

The design and security model are fixed by ADR-015 (the manifest) and ADR-016 (the license gate). This guide is the operator how-to.

Two requirements

White-label takes effect only when both are true:

  1. A branding directory is mounted read-only at /etc/huitzo/branding (configurable via HUITZO_BRANDING_PATH).
  2. The deployment's license grants white_label (the features array of the signed license file — see ADR-016). Ask for white-label in the license request; Core Preview (Demo/POC) licenses cannot carry it (Request a license).

If either is missing — no directory, an invalid manifest, or a license without white_label — the deployment serves the baked-in Huitzo defaults and logs a warning. Branding never takes a deployment down (fail-to-default, the inverse of the license hard gate). The mismatch ("manifest present but unlicensed") is surfaced in GET /api/v1/license/status so you can see why a brand did not take.

The branding directory

branding/
├── branding.yaml          # the manifest (schema_version: 1)
└── assets/
    ├── logo.png            # primary wordmark (light surfaces)
    ├── logo-dark.png       # optional dark-surface variant
    ├── favicon.svg         # optional browser-tab / theme icon
    ├── email-logo.png      # optional logo embedded in emails
    └── *.woff2             # optional bundled fonts

A complete, working example ships at examples/branding/harborview-mutual/ (a fictional brand with original assets).

Manifest reference (branding.yaml)

Section Field Notes
schema_version — Required; must equal 1.
product name Required brand string — replaces "Huitzo Hub" everywhere.
product tagline Optional; the login-screen subtitle.
product support_url Optional http(s) URL — replaces the huitzo.com support link.
colors.dark / colors.light --color-* (without the --) Any subset of the 24 brand-color tokens, per theme. Values are hex (#RRGGBB / #RRGGBBAA).
fonts.sans / fonts.mono family, files Optional font-family override (prepended to the IBM Plex stack) + optional bundled .woff2 under assets/.
assets logo, logo_dark, favicon, email_logo Optional bare filenames resolved inside assets/.

The token vocabulary is the entire contract. Only the 24 --color-* tokens and the two font-family tokens are overridable (26 total). Layout, spacing, radius, type scale, and z-index are not brand-tunable — anything outside the allowlist is rejected at validation time. There is no custom-CSS escape hatch.

Asset rules (enforced)

  • Logos and the email logo are raster only (.png / .webp); the favicon may be .svg / .png / .ico. An SVG favicon is sanitized (active content stripped) and served under a restrictive Content-Security-Policy.
  • Filenames are bare (no paths / ..); content-type is pinned from the key; size caps apply (logo ≤ 512 KB, email logo ≤ 256 KB, favicon ≤ 64 KB, each woff2 ≤ 256 KB).
  • An invalid manifest is rejected whole — a deployment never renders a half-applied brand.

Validate before you deploy

Run the CLI validator (offline; CI-friendly exit codes) before bringing the deployment up:

huitzo branding validate ./branding
# exit 0 = valid, 1 = errors (use --json for a machine-readable report)

It checks the same schema and asset rules the backend enforces at load time, so you catch a typo before the deployment silently falls back to defaults. See the CLI reference.

Mount it

Place the branding/ directory next to your compose file and mount it read-only at /etc/huitzo/branding on the backend service — the same shape as the license file. The compose baseline already includes the optional mount:

# docker-compose.yml (backend service) — already present
volumes:
  - ./branding:/etc/huitzo/branding:ro

Drop in (or remove) the branding/ directory and restart the backend to apply. An absent or empty directory is the normal default and serves Huitzo branding.

What changes

Surface Effect
Login screen Product name, tagline, logo, support link, favicon, accent.
Hub chrome Header wordmark, page title, theme color, accent across the UI.
Hosted dashboards (/d/{slug}) Inherit the Hub's brand tokens automatically (the SDK aliases the Hub token names).
Transactional emails Welcome / password-reset wordmark, accent, optional logo, footer.

Notes

  • Full mark removal, no forced attribution. White-label means the Huitzo marks are removed; any "powered by" requirement is a contract term, not a runtime flag.
  • Per-tenant branding is deferred. v1 is deployment-level (one brand per deployment). The same schema becomes a per-tenant overlay later.
  • Demos of a prospect's brand keep the prospect's assets outside this repository — see the branded-demo runbook.

Support and contacts

Need Contact
License requests and renewals partners.huitzo.ai (partner administrators)
Install questions, licensing questions, anything not covered here Your Huitzo partner contact, or [email protected]
Legal notices [email protected]
Security vulnerabilities [email protected]