Files
HIPCTF2/docs/guides/theming.md
T

85 lines
3.4 KiB
Markdown

---
type: guide
title: Theming
description: How the canonical themes are loaded, selected by administrators, and applied to the SPA via CSS custom properties.
tags: [guide, theming, design, admin]
timestamp: 2026-07-22T13:40:00Z
---
# Theme catalog
HIPCTF ships canonical themes defined as JSON files in `backend/themes/`. The
catalog is identified by `THEME_IDS` in
`backend/src/common/types/theme-ids.ts`; the default is `classic`.
Each theme contains an `id`, display `name`, and token set containing colors,
font family, radii, and spacing values. The frontend maps the supported visual
tokens to CSS custom properties.
# Administrator workflow
1. Sign in as an administrator and open **Admin area → General**, or navigate
to `/admin/general`.
2. Wait for the settings and available-theme requests to finish.
3. Choose a value from **Global theme** (`data-testid="general-themeKey"`).
4. Click **Save** (`data-testid="general-save"`).
5. Verify that `Saved.` appears and that the page uses the selected colors,
font, and corner radii. Reloading the application should preserve the theme.
The selector lists themes exposed by `GET /api/v1/admin/general/themes`. Only
theme JSON files present in the configured `THEMES_DIR` are listed, while the
loader still maintains canonical fallback themes for bootstrap and runtime
safety.
# Backend loading
`ThemeLoaderService` (`backend/src/common/utils/theme-loader.service.ts`)
runs on module initialization:
1. Reads theme JSON files from `THEMES_DIR` (default `./themes`).
2. Validates IDs and tokens; malformed files are skipped or reported through
the loader's validation path.
3. Backfills missing canonical themes so the application always has a valid
catalog.
4. Validates the configured `SETTINGS_KEYS.THEME_KEY`; an unknown value falls
back to `classic` and is persisted as the repaired setting.
The selected theme is sent to the SPA in `GET /api/v1/bootstrap` (see
[System Endpoints](/api/system.md)). Administrators can read and update the
selection through [Admin Endpoints](/api/admin.md). A successful general-settings
update emits a `general` SSE event containing the new `themeKey`.
# Frontend application
`BootstrapService` (`frontend/src/app/core/services/bootstrap.service.ts`)
fetches `/api/v1/bootstrap` once per application lifecycle, stores the payload
in signals, and applies the returned theme before the UI is rendered. The
`applyThemeToCss` helper in
`frontend/src/app/core/services/bootstrap.types.ts` writes these tokens to
`document.documentElement`:
| Theme token | CSS custom property |
|---|---|
| `primary`, `secondary`, `accent`, `surface`, `text` | `--color-*` |
| `success`, `warning`, `danger` | `--color-*` |
| `fontFamily` | `--font-family` |
| `radii.sm`, `radii.md`, `radii.lg` | `--radius-sm`, `--radius-md`, `--radius-lg` |
Reapplying a theme replaces the existing values. `clearThemeCss` removes every
property managed by the helper. Components consume the properties through
`var(--token)` in the global stylesheet and component styles.
# Verification
The frontend theme tests in `tests/frontend/bootstrap-theme.spec.ts` verify
that all tokens are written, missing tokens are a no-op, reapplication replaces
values, zero-valued radii are preserved, and cleanup removes every managed
property.
# See also
- [System Endpoints](/api/system.md)
- [Admin — General Settings](/guides/admin-general-settings.md)
- [Admin Endpoints](/api/admin.md)
- [Backend Module Map](/architecture/backend-modules.md)