Slots - moss
Slots
Template slots#
Slots are named injection points in the HTML template where plugins can insert content.
Slot Position Authorable
head-endBefore — for stylesheets, scripts, and meta tags. no
after-titleInside , after the title/date row — for article metadata (e.g. book block, review colophon). no
before-article-endInside , before — for article addenda. no
after-articleBetween and — for comments, reactions (NOT part of the article). no
footer-shapeThe data-moss-shape attribute value on the open tag. Advanced: controls footer chrome mode. no
footer-leftInside footer, leading position — filled by footer.md or any file with slot: footer-left frontmatter. yes
footer-endInside footer, trailing position — for the auto-injected subscribe form and plugin widgets. no
body-endBefore
— for scripts that must run after DOM is ready.
no
How slots work#
During generation, moss writes HTML comment markers at each slot position:
<article>
<h1>Page Title</h1>
<!-- slot:after-title -->
<p>Content...</p>
<!-- slot:before-article-end -->
</article>
<!-- slot:after-article -->
During the enhance phase , each plugin with the enhance capability returns content for the slots it fills. moss replaces the markers with that content. Unfilled markers are stripped from the final output and never appear in the published HTML.
Multiple plugins can write to the same slot. Their content is concatenated in plugin load order.
EnhanceResult#
The enhance hook returns an object mapping slot names to HTML strings:
async enhance(ctx) {
return {
slots: {
"after-article": `<section class="comments">
<script src="https://comments.example/embed.js"></script>
</section>`,
"head-end": `<link rel="stylesheet" href="/comments.css">`
}
};
}
Include only the slots your plugin fills. Omitted slots are left for other plugins or stripped.
Zero-flicker preview#
During preview, moss rebuilds the site on every file change. To prevent flickering during rebuilds:
New output is built to .moss/site-stage/.
The preview server atomically switches its pointer to site-stage/.
The staged content is copied to .moss/site/ (the canonical directory).
The pointer switches back to .moss/site/.
The preview server never serves from a half-built directory. The switch is instant — a pointer update, not a file rename.