GSM Application delivers a fully branded experience to every tenant without shipping separate front-end builds. Each row inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ti-infinite/GSMApplication/llms.txt
Use this file to discover all available pages before exploring further.
TenantRegistryDb.Tenants carries a JsonStyles column that encodes a complete design system — light palette, dark palette, and identity metadata — as a single JSON string. When a user types their company identifier on the login page, the frontend fetches that JSON, sanitizes it, and injects scoped CSS variables before the first pixel is painted.
The JsonStyles Structure
TheJsonStyles column stores a JSON object with three top-level keys:
light
A flat map of CSS custom property names to OKLCH color values used when the interface is in light mode.
dark
The equivalent map for dark mode. The same variable names are re-declared under the
.dark class selector.meta
Identity metadata: tenant name, initials, default locale, an optional logo path, and a localized tagline dictionary.
CSS variables
Keys must match the pattern
--[\w-]+. Any key that does not start with -- is silently skipped during CSS injection.The meta Object
The light and dark Objects
Both light and dark are flat Record<string, string> maps. Keys are CSS custom property names; values are valid CSS color or dimension tokens. The buildThemeCSS function accepts only keys matching --[\w-]+ and rejects any value that contains unsafe patterns (see Security below).
Example: Infinite Herbs (IH001) Theme
The following is the fullJsonStyles value for the Infinite Herbs tenant, as stored in seed-tenant-styles.sql:
How the Frontend Fetches and Applies a Theme
The theming pipeline runs entirely on the client side during the company-resolution step, before the user enters their credentials.User enters Company ID
The login page calls
resolveCompany(companyId) from src/shared/lib/tenant.ts, which posts the identifier to the gateway.Auth service returns TenantResolveDto
The
POST /api/security/v1/tenant/resolve endpoint returns an ApiResponse<TenantResolveDto> with two fields:Parse and validate the theme
The response body’s
data.jsonStyles string is parsed with JSON.parse into a TenantTheme object. If the tenant does not exist or jsonStyles is null, resolveCompany returns { valid: false } and the login form displays an error.Build scoped CSS with buildThemeCSS
buildThemeCSS(theme, tenantSlug) from src/shared/lib/theme.ts produces two CSS rule blocks:IH001 this produces CSS in the form:Security
ThebuildThemeCSS function sanitizes every CSS value before injection to prevent CSS-injection attacks:
--[\w-]+. Any key that does not begin with -- or contains characters outside [a-zA-Z0-9_-] is silently dropped.
Setting JsonStyles for a Tenant
To apply or update a tenant’s theme, execute anUPDATE statement against the registry database:
Theme changes take effect on the next company-resolution request. Because
resolveCompany is called at login time, existing browser sessions are not affected until the user logs out and back in, or clears their locally cached theme variables.Caching Theme Variables
After a successful resolve, the light-mode CSS variables are persisted tolocalStorage under the key gsm_theme_vars via cacheThemeVars. On subsequent page loads applyThemeVarsFromCache re-applies them before the resolve round-trip completes, eliminating the flash of un-themed content.