Engine-arkitektur

3. Engine-arkitektur

TesseraCMS har tre kode-lag: engine, sitetypes, modules. Forstå hvor hvert af jeres ændringer hører hjemme, så du ikke bygger noget der senere brydes af refactors.

Engine (src/engine/)

Universelle byggesten der ikke ved noget om specifikke sites. Lag-niveauer:

  • Fields (engine/fields/) — primitiverne (Text, RichText, Image, Url, Number, Boolean, Date, Money, …). Hver Field har et input-component i admin og en render-helper i public-rendering.
  • Blocks (engine/blocks/) — komposable byggeklodser i rich content (Text, Image, Spacer, CTA, Columns, RollupBlock, FormBlock, …). Hver Block har config-fields + en Render-komponent.
  • Content-types (engine/types/) — schemas for record-shapes (BaseContentItem, Image, Page, Rollup, Hero, Form, Brand, Snippet, …). Genbruges på tværs af sitetypes.
  • Rollup-layouts (engine/rollup-layouts/) — visuelle templates for rollups (grid, list, masonry, …)
  • Modules (engine/modules/) — modul-registry; selve modul-koden lever i src/modules/
  • Views (engine/views/) — registry over hvordan content-types render'es på public-side
  • Site-layouts (engine/site-layouts/) — registry over hvilke layout-packages der findes

Engine MÅ IKKE importere fra src/sitetypes/*. Pilen peger kun den ene vej.

Sitetypes (src/sitetypes/)

Kategorier af site med shared content-shapes. I dag:

  • artist_portfolio — kunstner-portfolio (Frontpage, ContentPage, Artwork, Hero-block, AboutRollup-block, ContactSection-block)
  • riding_club — rideklub-website (Pony, Tournament, Sponsor, News + relaterede blocks)
  • docs — docs-style (genbruger Frontpage/ContentPage + DocsHero-block)

Hver sitetype:

  • Registrerer sine egne content-types der extends: "Page" eller andre engine-types
  • Registrerer site-specifikke blocks (Hero, AboutRollup, …)
  • Registrerer sine rollup-layout-variants
  • Har et bootstrap-callback der kører ved opstart

Når du tilføjer en ny site-type-feature, hold den scoped til sitetypen — engine kender ikke til kunsts dybdegående eller riding-clubs.

Modules (src/modules/)

Genbrugelige features uafhængigt af sitetype. Eksempler:

  • pages — page-CRUD (alle sites bruger det)
  • media — billede-upload + admin (alle sites bruger det)
  • images — image-records (alle)
  • branding — brand + snippet (alle)
  • navigation — menus (alle)
  • forms — formularer + submissions (alle)
  • mail — mail-templates + ACS-send (alle)
  • heroes — hero-records (alle som vil have heros)
  • art — artwork + galleries (kun artist_portfolio)
  • riding-club-admin — pony+tournament+sponsor admin-UI (kun riding_club)
  • site-layouts/artsite-classic, /riding-club-classic, /docs-classic — layout-pakker (én pr. site-look)
  • social — social-channel + featured-post (alle der vil have SoMe-integration)
  • documents — PDF/DOCX-arkiv (alle)

Hvert modul har en manifest.ts der erklærer name, version, dependencies, admin-route, dashboardCategory. Manifester registreres i engine/bootstrap.ts.

Site-layouts (src/modules/site-layouts/)

Layout-packages er en speciel form for module — de definerer shell (header/footer/layout) plus slot-fillers (default brand, default footer-snippet) som tenant kan overskrive.

Hvert layout-package har:

  • manifest.tsx — registrer SiteLayoutManifest med slots, defaults, Shell component
  • Shell.tsx — komposite layout-shell (Navbar + children + Footer)
  • Navbar.tsx, Footer.tsx — sub-komponenter
  • i18n.ts — display-strings

Når en tenant har layoutPackage = "artsite-classic", render'er routen den pakke's Shell rundt om content.

Hvor tilføjer jeg X?

  • Ny primitive field-typeengine/fields/
  • Ny generic block (genbruges af alle sites) → engine/blocks/
  • Ny site-type-specifik block (kun til kunstnere fx) → sitetypes/<sitetype>/blocks/
  • Ny generic content-typeengine/types/
  • Ny site-type-specifik typesitetypes/<sitetype>/types/
  • Ny feature i admin-UI der virker for alle sites → nyt module under src/modules/
  • Ny visual look for sites → nyt site-layout under src/modules/site-layouts/
  • Helt ny kategori af site (fx restaurants) → nyt sitetype under src/sitetypes/

Når i tvivl: start specifik (sitetype) og generaliser senere hvis et andet sitetype får brug for det.

Lag-grænse-håndhævelse

  • Engine src/engine/ må ikke importere fra sitetypes
  • Sitetypes må importere fra engine (én vej)
  • Moduler må importere fra engine
  • Site-layouts må importere fra engine + moduler
  • Hver sitetype er sealing — artist_portfolio må ikke importere fra riding_club

Hvis du har brug for at krydse en grænse, er der typisk et missing engine-abstraktion. Lift det op, og brug det fra begge sider.

Theme preset system — nyt i 2026-06

Engine har nu en preset-baseret theme-arkitektur. Hver layout-modul registrerer en LayoutThemeBinding der mapper semantiske preset-vars til layoutens egen CSS-var-konvention. Editor vælger en af 5 presets per layout via /admin/theme.

import { registerLayoutThemeBinding } from "@/engine";

registerLayoutThemeBinding({
  layoutId: "creator-classic",
  scopeSelector: ".theme-creator-classic",
  emitVars: (preset) => [
    `--cp-bg: ${preset.vars.bg};`,
    `--cp-text: ${preset.vars.text};`,
    // ... 7 vars total: bg, surface, text, textMuted, heading, border, accent
  ],
});

buildThemeCss(theme, layoutPackage) slår binding op + emitter preset's var-set under binding's scope-selector + tenant's per-var-tweaks ovenpå med !important.

Fuld guide: Tema-systemet.