System Map
Generator System Map
This file is the shortest path to understanding the generator as a whole.
Source Of Truth
- Hugo templates and partials under
layouts/are the render authority. - Markdown content files in site repos are the authoring authority for page text and structured fenced blocks.
- Browser editors in
cdn/custom/are editing interfaces, not render-authority. - The local markdown bridge remains the localhost and future-local-app path.
- Hosted website editing should use the
workspaceprovider backed bygenerator-api. - For websites, the draft host under
*.drafts.quantalumin.comis the primary editor surface. Nextcloud/qloudis the shell and discovery layer, not the main website editor UI.
Main Runtime Layers
Render pipeline
- Page shells:
layouts/_default/ - Shared partials:
layouts/partials/ - List/summary cards:
layouts/partials/views/summary.html - Shop/storefront section templates:
layouts/shop/list.htmllayouts/shop/single.htmllayouts/partials/shop/product-contract.htmldocs/shop-section-contract.md
- Page chrome contract/render shell:
layouts/partials/page/chrome-contract.htmllayouts/partials/page/chrome-render.html
- Header contract:
layouts/partials/page/header-contract.html
- Site archetype contract:
layouts/partials/site/archetype-contract.htmldata/ql/site_archetypes.jsondocs/site-archetypes.md
- Hugo blog workspace contract:
- Render hooks / preprocessors:
layouts/_default/_markup/layouts/partials/preprocess.html
- Newsletter subscription surface:
layouts/partials/footer.htmllayouts/partials/form/newsletter-inner.htmllayouts/partials/helpers/newsletter-listmonk-config.html
Site/page chrome behavior such as sticky headers is now resolved through the shared header contract.
Preferred config lives in params.header.* and page front matter header.*. Older
params.chrome.stickyHeader, chrome.stickyHeader, top-level stickyHeader, and the legacy
header fixed class are still accepted as compatibility inputs, but they now flow into the same
header contract instead of staying separate chrome logic.
List-page summary cards also follow the Hugo render pipeline rather than flattening rendered output.
views/summary.html now routes summary sources through a first-paragraph helper, so cards only use
the first real paragraph and skip headings, quotes, figures, and similar leading blocks while
still preserving inline render output such as passthrough math/KaTeX inside that paragraph. That
helper must return a safe HTML fragment rather than escaped tag text because the summary card
injects it directly into the rendered card body.
List cards can now also read richer page front matter directly, including
summary_title, summary_eyebrow, summary_link_label, and icon, so list
pages can stay author-light while child pages own their own summary-card copy,
iconography, and CTA text.
Editorial TODO surfaces also stay draft-only across both supported authoring forms. The fenced
todo codeblock and the [!TODO] blockquote/callout path now both suppress output unless
site.BuildDrafts is enabled, so author notes do not leak into published pages.
The rendered header shell reads that semantic model in layouts/partials/header.html and passes
it down to logo and nav/breadcrumbs, which now prefer params.header.* first and only fall
back to legacy HeaderNav.* fields when the semantic fields are not yet present.
Header-bound runtime code should also treat the header as a replaceable SPA surface rather than a
static singleton. Shared navigation currently depends on ql:header-swapped from
cdn/prefetch/prefetch.js so
late header sync passes can re-bind burger toggles and other direct header DOM behavior after the
header node itself is replaced. The mobile header runtime in
cdn/custom/brochure-nav.js
also keeps a body-level MutationObserver on direct header swaps, so it can recover when a later
SPA header refresh lands after the usual route events.
That same runtime now owns the shared build-revision handshake as well:
layouts/partials/head.html
publishes meta[name="ql-build-version"] plus ql-build.json, while
cdn/prefetch/prefetch.js
uses that revision to invalidate stale SPA HTML and force one full reload onto a newer deployment
when the browser is still running an older head/runtime.
The brochure/mobile header path is owned jointly by
cdn/custom/brochure-nav.js
and
cdn/custom/brochure-responsive.css:
at phone widths the shared contract is burger toggle on the left, centered logo in the top row,
collapsed menu panel below. The toggle now renders in the shared header HTML so first paint
already matches the mobile shell; the runtime only wires aria-controls, open/closed state, CTA
relocation, and the mobile altmenu merge. Do not fork that behavior in site-local header CSS.
The shared image pipeline in
layouts/partials/media/resource-image.html
also treats .section-banner figures as banner-class assets explicitly, so large split-homepage
images keep the responsive WebP path even when the surrounding section layout tokens do not reach
the figure itself.
Page-level CTA rows in layouts/partials/main.html
should not depend on the template auto-title being visible: CV/download actions need to remain
available even when a page owns its title via a markdown H1 instead of the template header block.
Sections are now moving in the same direction. Hugo still emits legacy layout classes for
compatibility, but rendered section roots and #editorData now also carry a smaller semantic axis
contract:
flowmedia_sidesizecontent_alignsurfacelayout_family
Those section axes currently appear as data-ql-flow, data-ql-media-side, data-ql-size,
data-ql-content-align, data-ql-section-surface, and data-ql-layout-family on each rendered
section root.
Shared media/button render hooks also preserve backward compatibility for authored content:
- local
.htmlmedia defaults to inline rendering throughlayouts/partials/figure/html.html, while explicit iframe embeds still use the iframe path - local
.glband.gltfmedia resolve throughlayouts/partials/figure/model.htmland the lazy Three.js runtime incdn/custom/modelViewer.js, so sites can author 3D models with the normal markdown image contract such as{.fig .fit}; the runtime applies a neutral fallback material only to implicit bare-white meshes so materialless exports do not render as flat white by default, and pagemodelViewerfront matter can add a floor-plan backdrop (floorPlanSrc,floorColor,floorPlanOpacity), an optionalmodelColortint, and progressiveroomsnavigation that renders before the Three.js runtime is ready - the
buttonsfenced block accepts both standard markdown links and legacy angle-bracket shorthand such as[Label](</path .button .primary>)
Workspace-backed assets can be exposed to the render hooks through Hugo assets when the workspace
app writes a mount overlay for the build. The app remains responsible for access control: a Hugo
command run scans authored Markdown image destinations and may only mount source workspaces that
the current user can read. Once mounted, the generator resolves strict workspace markdown image
destinations through
layouts/partials/media/utils/find.html
using Hugo resources.Match.
Authors can use either same-owner or fully qualified workspace references:


Resolution is intentionally strict:
qulab:foo.pngmounts readable workspacequlabunder the same owner as the target workspace, then searchesworkspaces/qulab/**/foo.png.henry/qulab:foo.pngmounts readable workspacehenry/qulab, then searchesworkspaces/henry/qulab/**/foo.png.henry/qulab:some/path/foo.pngtries exactworkspaces/henry/qulab/some/path/foo.png, thenworkspaces/henry/qulab/**/some/path/foo.png.henry/qulab:**/figs/foo.svgis an explicit glob underworkspaces/henry/qulab/.- zero matches fail the Hugo build
- multiple matches fail the Hugo build and list the matching asset names
- missing or unreadable source workspaces fail in the workspace app before Hugo starts
This keeps workspace figure reuse author-friendly without silently publishing broken or ambiguous figures. Plain static URLs do not participate in strict asset validation.
The shared newsletter form is also site-configured rather than site-forked.
Newsletter copy and list IDs live in params.subscribe.*, while ListMonk
transport settings now live in params.subscribe.listmonk.*. That lets
different client websites point at different ListMonk nodes without modifying
shared partials.
The first site-wide archetype contract now lives alongside that config layer.
Sites should declare params.site.archetype once in config, then let shared
generator templates and editor runtime consume that semantic label through the
resolved site archetype contract. Current canonical archetypes are:
brochurevenuestorefrontservice-commerceresearchgeneric
Those archetypes are intentionally smaller than a full theme system. In
practice, the shared authored pattern for sites such as Rawson Hall and
TutorLumin is a place-network stack built from world, card_grid, steps,
calendar, booking, and platform shortcodes rather than site-local layout
forks.
Editor pipeline
- Edit-mode shell and inspector:
cdn/custom/toggleMarkdown.js - Nowtype source:
cdn/editor/src/ - Runtime editor bundle:
cdn/editor/nowtype.min.js - Local file bridge:
scripts/local-markdown-bridge.mjs
In replace-main presentation, the editor toolbar belongs to the editor shell flow.
Keep it mounted inside the replace-main panel rather than portaling it to document.body;
that allows the toolbar to sit above the page surface and push the editing surface down
instead of drawing over the page/header chrome.
The replace-main image-preview path also upgrades local SVG figure previews from <img> to
inline SVG markup inside cdn/custom/toggleMarkdown.js.
Those editor-side inline SVG instances must namespace their internal IDs per preview mount;
otherwise duplicated gradients, clip-paths, markers, or <use> targets can collide at document
scope and lose paint data in edit mode even though Hugo normal-mode rendering remains correct.
The shared inspector now has a first semantic chrome edit path:
- when no live section is selected, the
Layouttab exposes aHeadercard - that card edits site config
params.header.*or page front matterheader.* - the local bridge exposes:
/ops/header/read/ops/header/set/ops/header/unset
The shared inspector also now reads the new section axis contract first for selected live sections. Its current canonical write split is:
- section-frame semantics write to the section body’s leading
{ ... }attr block - content width and block layout presets write to the section body’s trailing
--- { ... }attr block
That keeps Hugo and markdown authoritative while older frontmatter.sections[*] metadata remains a
compatibility/editor seam instead of the primary render source.
Style/token pipeline
- Root + scoped tokens:
assets/css/variables.css - Shared SCSS entry:
assets/scss/main.scss - Widget integration contract: Widget integration
- Widget subsystem rule: widget roots alias site tokens into local
--widget-*variables, reset shared component leakage locally, and rebuild their own controls explicitly inside that namespace. - Shared motion/reveal layer:
assets/scss/libs/_animation.scsscdn/custom/fadeAnimation.js
- Chat/support bubble integration:
layouts/partials/page/chatwoot-contract.htmlcdn/custom/chatwoot.js- Site/page config flows through
params.chatwoot/chatwootfront matter and intobody[data-ql-chatwoot-*]; the runtime only loads Chatwoot when bothbaseUrlandwebsiteTokenare present. The shared contract prefers explicitparams.chatwoot.supportSiteSlug, but can also derive the support site from the currentsite.BaseURLhost againstparams.chatwoot.site.<slug>.websitemappings. Use this path for optional live chat before bridging into the wider helpdesk system.
- Navigation/discovery buttons:
cdn/vim/lib/help.jsassets/scss/components/_vim-help.scsscdn/spherelist/spherelist.jsassets/scss/components/_spherelist.scsslayouts/_default/sitemap.xmllayouts/partials/tools/spherelist.html- Keep the keyboard-shortcut helper and SphereList as explicit buttons, not invisible hover affordances, so visitors can discover them without knowing internal vimkeys.
- The keyboard helper renders its own searchable, grouped shortcut palette from the registered Vim binding metadata; do not duplicate that shortcut menu in site-local layouts.
- Public sitemap output should exclude page-lock-tracked pages, while SphereList should hydrate
from the embedded runtime site index and only surface member pages whose current lock status
has already resolved to
unlockedfor the visitor.
- Section/layout components:
assets/scss/components/_wrapper.scssassets/scss/components/_banner.scssassets/scss/components/_spotlight.scss
- Homepage hero rotator:
layouts/partials/page/homepage-banner.htmllayouts/partials/page/homepage-banner-config.htmlassets/js/homepage-banner.js- Contract: the first home section can opt in with
homepageBanneron the page or site; slides resolve from page resources or siteassets/globs and reuselayouts/partials/media/render.htmlfor responsive WebP output. Timing is controlled byintervalMsandtransitionMs; visual tuning can be driven per page/site withimageBrightnessandoverlayOpacityso banner imagery can be lightened or darkened without forking the shared component. Homepage-banner content width follows the shared--surface-content-max-widthpath, and text over mixed-luminance imagery can opt into the.ql-hero--liquid-glasscard utility fromassets/scss/libs/_theme-helpers.scss, which preserves the background image while giving hero copy deterministic contrast and exposes text-only shadow hooks (--ql-liquid-hero-text-shadow,--ql-liquid-hero-lead-shadow,--ql-liquid-hero-kicker-text-shadow) without changing the glass surface itself.
Reveal-enabled templates opt in declaratively with data-ql-reveal-* attributes.
Current shared knobs are:
data-ql-reveal: enable the runtime on a containerdata-ql-reveal-trigger: reveal mode such asloadorenterdata-ql-reveal-target: descendant selector to animatedata-ql-reveal-order: reveal ordering such assequence,reverse, orrandomdata-ql-reveal-duration: transition durationdata-ql-reveal-base-delay: initial delay before the first target startsdata-ql-reveal-stagger: per-item stagger duration
Inline markdown figures still use the shared floated figure-inline contract in
assets/scss/components/_figure.scss.
The first inline figure after prose still clears prior floats, but back-to-back opposite-side
inline figures are allowed to share a row instead of forcing a fresh clear on each figure. That
reduces dead whitespace in chapter flows while keeping headings below the float stack.
Authoring Surface
The generator currently supports four main authored input styles:
- Normal markdown sections and figures
- Structured fenced blocks like
team,gallery,contact,faq,stats,testimonials,world,card_grid,steps,pricing, andfacts - Hugo shortcodes under
layouts/shortcodes/ - Front matter / config token overrides, including
params.site.archetype
Agent/MCP Documentation Surface
For agents editing sites through an MCP-style protocol, the intended documentation stack is:
- human overview: Hugo system map
- human authoring reference: Shortcodes
- machine-readable shortcode inventory: shortcodes manifest
- machine-readable structured block inventory: structured blocks manifest
- machine-readable editor scope/token inventory: editor surface manifest
- machine-readable site archetype catalog: site_archetypes.json
- authoring rules for agents: Agent authoring contract
The manifest is the canonical inventory for shortcode availability and should be preferred over ad hoc template inference in agents.
Documentation Rule
When adding or changing a shortcode:
- update the shortcode implementation in
layouts/shortcodes/ - update shortcodes.manifest.json
- update shortcodes.md if the author-facing contract changed
- run
scripts/check-shortcode-manifest.mjs