1.8 KiB
type, title, description, tags, timestamp
| type | title | description | tags | timestamp | |||
|---|---|---|---|---|---|---|---|
| guide | Theming | How the 10 canonical themes are loaded, validated, and applied to the SPA via CSS custom properties. |
|
2026-07-21T18:28:00Z |
Theme catalog
HIPCTF ships 10 canonical themes defined as JSON files in
backend/themes/ (01-classic.json … 10-monochrome.json). The full
list lives in backend/src/common/types/theme-ids.ts:
classic, midnight, sunset, forest, cyber, paper, crimson,
ocean, neon, monochrome.
Each theme is a flat map of CSS custom properties (colors, radii, font
family) consumed by frontend/src/styles.css.
Backend loading
ThemeLoaderService (backend/src/common/utils/theme-loader.service.ts)
runs on module init:
- Reads every
*.jsonfile inbackend/themes/. - Validates each against the
Themeinterface (backend/src/common/types/theme.ts) — unknown theme ids, malformed JSON, or missing tokens throwApiError(THEME_INVALID). - Backfills any of the 10 canonical themes that are missing from disk (safety net so a partial checkout still boots).
- Reads
SETTINGS_KEYS.THEME_KEY(default'classic'). If the value is not inTHEME_IDS, the loader falls back toclassic, logs a warning, and persists'classic'back to settings so the next request is self-healing.
The resolved theme object is sent to the SPA in the
GET /api/v1/bootstrap payload (see System Endpoints).
Frontend application
BootstrapService (frontend/src/app/core/services/bootstrap.service.ts)
writes each theme token onto document.documentElement (e.g.
--color-primary, --radius-md, --font-family). Because styles.css
references the tokens via var(--token), swapping themes is instant.