Concepts
Frontmatter, mounts, bundles, preload, and hydration — how the build decides where everything goes.
Frontmatter
YAML at the top of a .c.html file between ---. System keys (all caps) control the build:
- MOUNT — Which slot receives this file's body (e.g.
content,nav). - TYPE —
pageorcomponent. - TEMPLATE — Which
.t.htmlwraps the page (pages only).
Any other keys (e.g. title, heroTitle) are yours. They are available as {{key}} in the template and when passing into mounts (e.g. {{MOUNT.hero:heroTitle}}).
--- title: Home heroTitle: Welcome TYPE: page MOUNT: content TEMPLATE: layout.t.html ---
Mounts
Named slots where content goes. On <style> and <script> you set mount="head" or mount="body" (or any name). In the template you have {{MOUNT.head}}, {{MOUNT.content}}, {{MOUNT.body}}, and any other slot names you use.
The body HTML of a page or component goes into the slot specified by MOUNT: in frontmatter. The build merges everything that targets a given slot into one place. Duplicate style or script blocks are not emitted twice.
<style mount="head" serve="inline">.x{}</style>
<script mount="body" serve="file" bundle="main" destination="static/js"></script><head> {{MOUNT.head}} </head> <body> {{MOUNT.content}} {{MOUNT.body}} </body>
Passing variables into a mount
{{MOUNT.hero}} inserts the hero slot's HTML. {{MOUNT.hero:heroTitle}} does the same but passes a variable: the component can use @@heroTitle or {{heroTitle}} and {{if heroTitle}}…{{/if}}. For several values use {{MOUNT.card:title,description}}; in the component use @@title, @@description, and conditionals on those names.
{{MOUNT.hero:heroTitle}}{{if heroTitle}} <h1>@@heroTitle</h1> {{else}} <h1>Default</h1> {{/if}}
Bundles
With serve="inline" (the default) each <style> or <script> is emitted inline in place. With serve="file" and a bundle="main" (or any name), all blocks that share that bundle name are merged into one file. You only need one destination per bundle (e.g. destination="static/js"). If no block in the bundle specifies it, the file is written at the dist root and the build warns. Duplicate blocks are not emitted; each block is included once.
Different bundle names (e.g. bundle="components") produce separate files. Same rules for styles.
<style mount="head" serve="inline">.a{}</style>
<script mount="body" serve="file" bundle="main" destination="static/js">console.log(1);</script>Preload
Without preload_mount you get normal output only: <link rel="stylesheet" href="..."> for file CSS (in the mount) and <script src="..."> in body for file JS—both can block rendering. To avoid blocking, add preload so the build emits a fetch in the head first.
Styles: On <style mount="head" serve="file" ...> add preload_mount="head". The build emits <link rel="preload" href="..." as="style"> in that mount (plus the normal stylesheet link). Omit preload_mount and you only get <link rel="stylesheet" href="...">.
Scripts: On <script> with serve="file" and type="module" add preload and preload_mount="head". The build emits <link rel="modulepreload" href="..."> in that mount and the script tag in body. Only pages that use that bundle get the link.
<style mount="head"
serve="file"
bundle="main"
destination="static/css"
preload_mount="head">...</style>
<script mount="body"
serve="file"
bundle="main"
destination="static/js"
type="module"
preload
preload_mount="head">...</script>Hydration
Use hydrate="load", hydrate="idle", hydrate="visible", or hydrate="visible:#id" to control when the script runs. If you omit the attribute, the script runs immediately. See Examples for snippets.
<script mount="body" serve="inline" hydrate="idle">/* runs when idle */</script> <script mount="body" serve="inline" hydrate="visible:#panel">/* runs when #panel in view */</script>