Files
jobtrackingapp/docs/architecture/cv-theme-engine.md
T
cesnimda 17edf19f89
CI and Deploy / test (push) Failing after 1m53s
CI and Deploy / deploy (push) Has been skipped
docs(architecture): document CV builder, theme engine, Phase 4 status
cv-builder.md (variant model, rendering pipeline, API, builder workflow,
extension points, known deep-link limitation) + cv-theme-engine.md (how a
theme is data and how to add one). Roadmap Phase 4 marked foundation-shipped
with the remaining polish itemised.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 10:07:43 +02:00

2.8 KiB

CV Theme Engine

Phase 4 (2026-07-18). How CV themes work and how to add one. Companion to docs/architecture/cv-builder.md. Verified against code.

The rule

A theme is data, not code. There is exactly one renderer — ThemedCvRenderer (JobTrackerApi/Services/ThemedCvRenderer.cs) — with a single render path. Every visual difference between themes is expressed by the fields of a CvTheme record (Models/CvTheme.cs). Adding a theme never touches the renderer.

This replaces the previous approach (CvTemplateRenderer, one hand-written HTML method per template), which is retained only for the legacy tailored-draft flow and is not used by the builder.

CvTheme fields (the knobs)

Group Fields
Identity Id, Name, Category, Description
Layout Layout (single | sidebar-left | sidebar-right | header-band), SidebarWidthMm, SidebarSections
Palette Accent, Ink, Muted, Line, Paper, SidebarBg, SidebarInk, HeadingColor
Typography HeadingFont, BodyFont, NameSizePt, HeadingSizePt, BodySizePt, LineHeight
Spacing PageMarginMm, SectionGapMm, EntryGapMm
Styling HeaderStyle (plain|band|centered|kicker), HeadingStyle (caps-rule|underline|plain|bar), PhotoShape (none|square|rounded|circle), DefaultIcons

The renderer computes CSS variables from these plus the variant's runtime overrides (accent, fonts, density, page size, photo, icons) and picks one of the layout wrappers. SidebarSections decides which section keys move to the sidebar for the two-column layouts.

Adding a theme

  1. Append one CvTheme { … } to CvThemeCatalog.Themes (Models/CvTheme.cs). Only override the fields that differ from the defaults.
  2. Nothing else. It appears in GET /api/cv/themes, the Customize tab picker, and renders.

Add a CvBuilderTests.Every_catalog_theme_renders_valid_html already loops the whole catalog, so a new theme is smoke-tested automatically.

Shipped themes (8)

modern (header-band), minimal (single), executive (single, serif), technical (sidebar-left, dense), ats-classic (single, no graphics), nordic (sidebar-right), elegant (single, editorial), creative (sidebar-left, bold).

Deliberately not here (yet)

  • Rich-text inside bullets. The render model treats bullets as plain strings, so the builder's text areas are plain text. Adding bold/italic/links means the render model carries inline runs and the renderer emits them — a self-contained extension, no theme changes.
  • PDF page numbers. ShowPageNumbers is carried through settings but the actual footer is a Playwright footerTemplate concern (the PDF exporter), not CSS paged-media (Chromium's margin boxes are unreliable). Wire it in PlaywrightCvPdfExporter when needed.