4.5 KiB
Catalog page (Zola + Solid + Mermaid)
Read this when editing /catalog/, templates/catalog.html, sass/_catalog.scss, or frontend/src/**/catalog-*.
Zola side
| Piece | Path |
|---|---|
| Page | content/catalog.md → template = "catalog.html" |
| Shell | themes/openfreebooks/templates/catalog.html |
| Compare doc (math only) | templates/partials/math-curricula-compare.html — embedded in <template id="catalog-compare-template"> |
| Build-time JSON | #catalog-data — merged subject curricula from data/{subject}-curriculum.json + data/catalog.json |
| Styles | themes/openfreebooks/sass/_catalog.scss |
Tera: never bind curriculum JSON to a variable named math (reserved). Use math_catalog, etc.
URL and views
| View | view param |
UI |
|---|---|---|
| List (default) | (omit) | Strand sections + CatalogChapterCard |
| Map | tree |
Lazy CatalogMermaidView — DAG from graph.edges |
| Compare | compare |
Math only — CatalogCompareDoc clones compare partial HTML |
Example: /catalog/?subject=math&view=tree
Curriculum filter chips come from data/catalog.json → curriculums[]. Math chapters use curriculumCoverage in math-curriculum.json (core / extension / related per framework). Compare matrix uses all roles; list/map badges show framework labels only.
Solid / Vite
| Piece | Path |
|---|---|
| App shell | frontend/src/components/catalog-app.tsx |
| List card | frontend/src/components/catalog-chapter-card.tsx |
| Compare mount | frontend/src/components/catalog-compare-doc.tsx |
| Map viewer | frontend/src/components/catalog-mermaid-view.tsx (lazy chunk catalog-mermaid-view-*.js) |
| Mermaid source | frontend/src/lib/catalog-to-mermaid.ts |
| Theme (hex) | frontend/src/lib/catalog-mermaid-theme.ts |
| Strand header chrome | frontend/src/lib/catalog-mermaid-strand-headers.ts |
| Light/dark mode | frontend/src/lib/catalog-canvas-theme.ts (siteCanvasTheme, watchSiteTheme) |
| Badge classes | frontend/src/lib/catalog-badge.ts |
| Types | data/catalog.types.ts (CatalogViewMode: "linear" | "tree" | "compare") |
After any catalog frontend change: bun run build:js then hard-refresh.
Mermaid map — theming (important)
Mermaid writes inline fill on SVG nodes. CSS fill on .cluster rect does not override themed colors.
| Rule | Detail |
|---|---|
| Custom colors | Only with theme: "base" + themeVariables (hex). Other themes (default, dark, …) are not customizable via variables. |
| Color format | Hex only (#121110). Named colors (red) are ignored by the theming engine. |
| Site-wide init | mermaid.initialize({ …mermaidInitializeOptions(mode) }) in catalog-mermaid-view.tsx |
| Strand subgraph body | clusterBkg in mermaidThemeVariables() |
| Strand title band | secondaryColor — also applied to overlay header rect in enhanceStrandClusterHeaders() |
| Borders / edges | clusterBorder, lineColor, nodeBorder, etc. |
Do not try to drive strand cluster fills from Sass variables on .cluster rect; keep SCSS for typography, label chrome, and map chrome (pan/zoom, card links).
Strand subgraph titles
Mermaid puts subgraph titles on the cluster border. Post-render:
enhanceStrandClusterHeaders(svg, mode)findsg.clusterids containingstrand_- Inserts header
rect+ rulelineatSTRAND_HEADER_HEIGHT(44px) - Repositions
foreignObjectlabel into the header band - Sets
rx="0"on cluster frame (square corners)
Diagram source uses HTML in subgraph titles, e.g. <header class='catalog-mermaid-strand__header'>…</header> — see catalog-to-mermaid.ts.
Map chapter cards
List and map share card markup via CatalogChapterCard. In the map, only the title is a link for live chapters; planned chapters are non-clickable.
Sass notes (_catalog.scss)
- Curriculum badge tokens and dark-mode contrast live here.
- Map card title underline: under
.catalog-mermaid-view/.catalog-canvaslegacy class names if present. - Strand label styling:
.catalog-mermaid-strand__header,.catalog-mermaid-strand-label-fo— not clusterfill.
Tests
bun test frontend/src/lib/catalog-to-mermaid.test.ts
bun test frontend/src/lib/catalog-mermaid-theme.test.ts
bun test frontend/src/lib/catalog-mermaid-strand-headers.test.ts
Verify locally
bun run build:js && zola serve
Open /catalog/?subject=math, toggle List / Map / Compare (math), and switch site light/dark — strand header band should differ from subgraph body in both modes.