Skip to content

Per-Tenant Visual Branding (White-Label) #65

@mgoldsborough

Description

@mgoldsborough

Problem

The web app hardcodes NimbleBrain branding — logo, app name, colors, fonts, favicon. Tenants can customize agentName and theme (light/dark), but not the visual identity. A tenant should be able to have their own logo, colors, and app name without a fork.

Current State

Already parameterized (backend/infra):

  • tenant.agentName → agent display name in system prompt
  • tenant.theme → light/dark/system preference
  • ingress.customDomain / customDomainCertArn → custom domain support (defined in Helm, unused)

Hardcoded in web app:

  • Logo.tsx — imports nimblebrain-icon-color-square.png, renders "NimbleBrain" text
  • index.html — page title "NimbleBrain", favicon, font imports
  • bridge/theme.ts — fixed color tokens (primary blue #0055FF, surface colors)
  • Login.tsx — API key placeholder "nb_..."

Proposed Solution

1. Add tenant.brand to Helm values:

tenant:
  brand:
    name: "Acme"
    logoUrl: "/assets/acme-logo.png"    # or external URL
    faviconUrl: "/assets/acme-favicon.png"
    apiKeyPrefix: "acme_"
    colors:
      primary: "#6C3AED"
      accent: "#A78BFA"
      surfaceLight: "#FAF9F7"
      surfaceDark: "#0A0A09"
    fonts:
      body: "Inter"
      heading: "Cal Sans"
      code: "JetBrains Mono"

2. Expose brand config via /v1/config API response (already serves tenant config to the web app).

3. Web app consumes brand config:

  • Logo.tsx reads brand.name and brand.logoUrl from config context
  • index.html title/favicon set dynamically on app init
  • Theme tokens overridden with brand.colors via CSS custom properties
  • Login.tsx uses brand.apiKeyPrefix for placeholder
  • Font imports loaded dynamically or pre-built per tenant

4. Defaults: When tenant.brand is omitted, fall back to current NimbleBrain branding (zero breaking change for existing tenants).

Scope

  • Add brand schema to tenant values template
  • Surface brand in /v1/config API response
  • Refactor Logo.tsx to read from config context
  • Dynamic page title + favicon on app init
  • CSS variable override layer from brand.colors
  • Dynamic font loading from brand.fonts
  • Update Login.tsx placeholder from config
  • Document brand config in tenant onboarding docs
  • Validate with a test tenant

Out of Scope (future)

  • Custom CSS injection (full stylesheet override)
  • Per-tenant email templates
  • Custom agent persona/voice beyond agentName

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions