Admin branding: colour tokens, five logo variants, runtime favicon

↗ view on GitHub · Claude · 2026-05-16 · 8276afb9

Adds an admin-managed branding surface so the firm's brand colours
and logos can be set from the UI without touching code.

Schema (migration 0021):
- org_settings.brand_primary_hex   default #A93226 (brand red)
- org_settings.brand_secondary_hex default #36475C (dark navy)
- org_settings.brand_neutral_hex   default #6E6E6E (nav text grey)
- org_settings.logo_*_path columns for five variants:
  full_colour, full_white, mark, dark_mono, favicon

Logos live as plain files under ${DATA_ROOT}/branding (mounted to
/data/branding in the backend container). Filenames are
content-hashed so cache busting is automatic. PNG, SVG, WebP, JPEG
accepted for normal variants; .ico, PNG, or SVG for the favicon.
2 MB cap.

Backend:
- New lib/branding.ts (load, write, read, delete, mime/hex
  validation).
- New /branding (public) endpoint pair: GET /branding returns the
  colour tokens + logo URLs; GET /branding/logo/:filename streams
  bytes. No auth required since logos are non-sensitive and the
  login splash needs them.
- New /admin/branding endpoints: GET, PATCH (colours),
  POST /admin/branding/logo/:variant (multipart upload),
  DELETE /admin/branding/logo/:variant.
- singleFileUpload helper now takes a maxBytes argument so the
  branding route can cap at 2 MB without affecting document upload
  limits.

Frontend:
- New BrandingProvider context loads /branding once on app boot,
  injects CSS variables (--pip-primary, --pip-secondary,
  --pip-neutral), and swaps <link rel="icon"> when a favicon
  variant is uploaded.
- SiteLogo prefers the uploaded full_colour variant, falls back to
  the built-in PipIcon + wordmark.
- AppSidebar header shows the mark variant when uploaded; otherwise
  the wordmark renders in the brand-red colour.
- New /admin/branding page: hex colour pickers, drag/upload zones
  per logo variant with preview and remove buttons.

Infra:
- docker-compose mounts ${DATA_ROOT}/branding to /data/branding,
  sets BRANDING_LOCAL_PATH.
- install.sh provisions the branding dir at uid 10001.
- Caddy template adds /branding /branding/* to @backend_api.
Repository cpatpa/PIP
Author Claude <noreply@anthropic.com>
Authored
Parents bb9f778e
Stats 17 files changed , +1107 , -46
Part of PIP branding and Mike→Pip identifier rename

Capture this commit into my fork

Download a Markdown prompt that tells Claude how to port this exact commit into your working tree. Run it via claude -p < capture-commit-8276afb9.md from inside the repo you want the change in.

⬇ Download capture-commit-8276afb9.md