# White Label & System Branding

**Task 023** — single-instance white-label foundation. All customer-facing branding is configurable from **Settings → Branding**. This is not multi-tenant.

## Brand settings

Stored on `system_settings.branding` (synced with legacy `appName` / `companyName`).

| Field | Purpose |
|-------|---------|
| `platformName` | Product name in sidebar, login, metadata |
| `companyName` | Legal / sender identity |
| `logoLight` / `logoDark` | UI and email logos |
| `favicon` | Browser tab icon |
| `primaryColor` / `secondaryColor` | Email template defaults |
| `website` | CTA and email footer (hidden when empty) |
| `supportEmail` / `supportPhone` / `address` | Email footer and sender defaults |

## Services & provider

| Layer | Location |
|-------|----------|
| Types & helpers | `src/lib/brand-settings.ts` |
| Server service | `src/server/services/brand-settings.service.ts` |
| Upload storage | `uploads/branding/` → served at `/api/branding/assets/[filename]` |
| React context | `src/components/providers/brand-provider.tsx` — `useBrand()` |
| Email footer | `src/lib/email-footer.ts` — `buildEmailFooterHtml()` |

## API

| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET | `/api/settings/branding` | Public read | Resolved brand settings |
| PATCH | `/api/settings/branding` | Admin | Update text/colors |
| POST | `/api/settings/branding/upload` | Admin | Upload logo/favicon (`assetType`, `file`) |
| GET | `/api/branding/assets/[filename]` | Public | Serve uploaded asset |

## UI integration

- **Sidebar / topbar / login / dashboard / marketing home** — `useBrand()` + `BrandLogo`
- **Settings → Branding** — form, uploads, live preview (sidebar, login, email header/footer)
- **Email templates** — new-template defaults from brand; starters use `{{company_name}}`, `{{sender_name}}`, `{{sender_email}}`
- **AI generation** — brand voice `companyName` sourced from branding settings
- **Campaigns / sequences** — sender fallbacks from `getDefaultSenderFromBrand()`

## Fallbacks

- No logo → show `platformName` text
- No `website` → omit website line in footer and default CTAs
- Missing fields → `FALLBACK_BRAND_SETTINGS` in `brand-settings.ts`

## Related docs

- [18-settings-administration.md](./18-settings-administration.md)
- [05-email-system.md](./05-email-system.md)
- [26-ai-content-generation.md](./26-ai-content-generation.md)
