--- type: guide title: Theming description: How the 10 canonical themes are loaded, validated, and applied to the SPA via CSS custom properties. tags: [guide, theming, design] timestamp: 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: 1. Reads every `*.json` file in `backend/themes/`. 2. Validates each against the `Theme` interface (`backend/src/common/types/theme.ts`) — unknown theme ids, malformed JSON, or missing tokens throw `ApiError(THEME_INVALID)`. 3. Backfills any of the 10 canonical themes that are missing from disk (safety net so a partial checkout still boots). 4. Reads `SETTINGS_KEYS.THEME_KEY` (default `'classic'`). If the value is not in `THEME_IDS`, the loader falls back to `classic`, 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](/api/system.md)). # 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. # See also - [System Endpoints](/api/system.md) - [Backend Module Map](/architecture/backend-modules.md)