Branding and Theming¶
Applies to: All subscriptions
Purpose¶
Describe Theme Framework V1: what an organization can customize (product name, logo, colors, light/dark default), what it cannot (White Label Lite — see Scope — is not a fully custom deployment), how color changes are validated before they save, and how branding resolves on the login screen, which renders before any session exists.
Audience¶
System administrators configuring an organization's identity, and implementation partners onboarding a white-labeled customer.
Prerequisites¶
- Administrator access —
admin.manage_userspermission (Org Administrator or Platform Super Admin) - Theme API if automating configuration rather than using the admin console's Branding & Themes screen
Reference¶
Scope: White Label Lite¶
Theme Framework V1 supports:
- Product name and short name
- Logo, favicon, and an optional login screen hero image
- Primary, secondary, and accent brand colors
- Light / Dark / System default
- Support email and phone
It does not support, and there is no configuration path for:
- A custom deployment (separate infrastructure, domain, or database per organization) — every organization runs on the same Complifly instance
- A custom login flow — SSO providers, password policy, and MFA are configured per the Authentication documentation and are unrelated to theming
- Fully custom pages — an organization cannot replace a screen's layout or add its own pages, only its colors, name, and marks
Organization-scoped, not GSTIN-scoped¶
One theme per organization, not per GSTIN. Every GSTIN under an organization, and every user signed into any of them, renders the same branding. This is the opposite of Feature Flags, which are per-GSTIN — the two intentionally scope differently, for different reasons: a feature flag gates a module with legal or billing consequence per registration; a theme is an identity, and an organization has one.
Colors and accessibility¶
Three colors are configurable — primary, secondary, accent — and each is validated against the text color it is actually rendered with, not a generic check:
| Color | Always paired with | Validated against |
|---|---|---|
| Primary | White text (buttons, the shell bar) | White — needs 4.5:1 (WCAG AA) |
| Secondary | Dark text (light fills, secondary surfaces) | A fixed dark color — needs 4.5:1 |
| Accent | Dark text (tinted highlights) | The same fixed dark color — needs 4.5:1 |
A color that does not meet this bar is refused at save time, with a message naming the exact ratio and what is needed — not merely flagged after the fact. This closes the accessibility gap the platform's own default warning/status colors had before Theme Framework V1 shipped: those were fixed (never customer-configurable) and have since been corrected independently of this feature, but the lesson from that gap — a color that looks fine to the person choosing it can still be unreadable — is exactly what this validation exists to prevent for every future organization theme.
Semantic status colors (success, warning, error, info) are never customer-configurable, in any organization's theme, for the same reason: recoloring what "error" looks like is a correctness risk, not a branding choice.
The login screen and pre-session branding¶
The login screen, password reset, and any other page that renders before a
session exists cannot look up "the caller's organization" the normal way —
there is no token yet to read an org ID from. In V1, these pages render the
platform's own default branding (GET /api/theme/public — see
Theme API).
An organization's own branding takes over immediately once its users sign
in.
Consequence for white-labeled organizations: the sign-in screen a white-labeled organization's users see today is Complifly's own default look, not theirs, until they authenticate. A per-organization login wall — reached by a distinct URL or subdomain that resolves to that organization's branding before sign-in — is a known V1 limitation, not built. It would need a way to resolve organization identity from the request itself (a subdomain or a query parameter carried through the link a user is sent), which does not exist in the current routing.
Assets¶
Logo, favicon, and login hero image are uploaded through the admin console
or POST /api/theme/assets and served back through a public (unauthenticated)
URL this API itself returns — see
Theme API §Asset upload.
Files are stored on the application server's local filesystem under
gst-backend/uploads/theme/<org_id>/, the same convention the platform's
existing upload storage already uses (FILE_UPLOAD_DIR) — nothing new was
introduced for this feature specifically.
What is never themed¶
- Generated documents — invoices, e-Way Bills, and other PDFs use their own fixed template and are unaffected by an organization's theme or dark mode setting. Per-document logo placement is a separate, existing setting — see Print Configuration.
- The Direct Tax (TDS) module — out of scope for Theme Framework V1 by design; its screens render with the platform's fixed colors regardless of organization theme.
Validation¶
| Check | Method | Pass condition |
|---|---|---|
| A new organization renders correctly with no configuration | Provision an organization, sign in, change nothing | Platform default branding throughout, no broken images or missing colors |
| A color change is refused when it should be | Attempt to save a near-white primary color | 422, refused, with the exact contrast ratio named |
| Dark mode default applies for a new user | Set the organization default to Dark, sign in as a user who has never chosen a preference | Dark mode on first load |
| A user's own choice overrides the organization default | Pick Light in the shell bar switcher, reload | Stays Light, regardless of the organization's default |
| Login screen renders before authentication | Load /login directly, no prior session |
Renders without error, with the platform default branding |
Troubleshooting¶
| Symptom | Cause | Action |
|---|---|---|
| Branding change does not appear for a signed-in user | The change is picked up on next navigation/reload, not mid-session automatically | Ask the user to reload |
| Login screen still shows the platform default after configuring an organization's theme | Expected in V1 — the login screen is not yet organization-aware (see The login screen and pre-session branding) | Not a fault; a recorded limitation |
| Uploaded logo does not display | logo_url set to something other than this API's own returned URL |
Re-upload through the console or POST /assets rather than pasting an external image URL |
| A color is refused that "should" be fine | Check which text color the error names — primary is checked against white, secondary/accent against dark text; a color valid for one may fail for the other | Use the color for the field it is actually valid for, or choose a different shade |
Related Articles¶
- Theme API
- Feature Flags — the per-GSTIN counterpart this is deliberately scoped differently from
- In-product Help Centre: "Theme Framework" guide (end-user light/dark switching) and "Branding & Themes" screen help (administrator configuration)