Templates
Templates control how your notes look — sidebar, header, footer, and layout.
A template is an HTML file stored in _layouts/. It receives the note's content and frontmatter, then produces a complete page. Your markdown stays clean; the template decides how it's presented.
How templates work
Step 1. Create a file in _layouts/, for example _layouts/my-page.html:
<!DOCTYPE html>
<html>
<head>
<title>{{ note.Title() }}</title>
</head>
<body>
<h1>{{ note.Title() }}</h1>
{{ note.HTMLString() | unsafe }}
</body>
</html>
Step 2. Assign the template in your note's frontmatter:
---
layout: my-page
title: My page
---
Page content in markdown.
The page now uses your template.
Default template layout properties
The built-in default template supports these frontmatter keys — no custom HTML required:
| Key | Purpose |
|---|---|
header: [[Navigation]] |
Note to use as site header (logo + nav) |
footer: [[Footer]] |
Note to use as site footer |
left_sidebar: [TOC, inlinks] |
Left sidebar widgets |
right_sidebar: [outlinks] |
Right sidebar widgets |
content: [selfcontent, magazine] |
Content blocks rendered in order |
magazine_include_property: featured |
Only show notes that have this frontmatter key |
magazine_sort_property: priority |
Sort magazine cards by this frontmatter key |
magazine_include_files: "posts/**/*.md" |
Glob pattern for magazine notes |
Set any sidebar to false to hide it. Set left_sidebar: null (or omit) for no sidebar.
Available sidebar widgets
TOC— table of contents (JavaScript-enhanced, tracks active heading)inlinks/Backlinks— notes that link to this noteoutlinks— links from this note[[Title]]— embed another note by titlepath/to/file.md— embed a note by file path
Content block types
selfcontent(orself) — this note's own article with<h1>+ bodymagazine— multi-tier card layout (featured, grid, list)[[Title]]— embed a note by titlepath/to/file.md— embed a note by file path
Magazine layout
The magazine layout shows child notes as cards in three tiers:
| Tier | Position | Visual |
|---|---|---|
| Featured | First note | Large full-width card |
| Grid | Notes 2–5 | Smaller cards, 4-column |
| List | Notes 6+ | Minimal, vertical list |
Activate it on an index note:
---
content:
- magazine
magazine_sort_property: priority
magazine_include_files: "posts/**/*.md"
---
Header and footer from markdown
The header and footer are ordinary notes. The default template reads:
- Logo — the first image in the header note
- Navigation — the first list in the header note
- Footer columns — a nested list (top-level items become column headings)
Example header note _nav.md:
---
title: Navigation
---

- [Home](/)
- [Docs](/docs)
- [Getting started](/docs/start)
- [Templates](/docs/templates)
- [About](/about)
Then reference it from any note:
header: [[_nav]]
Sidebar from a markdown file
Store navigation in a separate markdown file so you can update it without touching the template:
---
title: Sidebar
---
### Section 1
- [Page 1](/docs/page-1)
- [Page 2](/docs/page-2)
Reference it as a sidebar widget:
left_sidebar:
- _sidebar.md
What's available in a custom template
The Jet template engine provides these variables:
{{ note.Title() }} — title from frontmatter
{{ note.HTMLString() }} — full content as HTML
{{ note.Permalink() }} — page URL
{{ note.ReadingTime() }} — reading time in minutes
{{ note.CreatedAt() }} — creation date
{{ note.M().GetString("author", "Unknown") }} — frontmatter field
Access other notes via nvs:
{{ sidebar := nvs.ByPath("/_sidebar.md") }}
{{ if sidebar }}
{{ sidebar.HTMLString() | unsafe }}
{{ end }}
Load assets:
<link rel="stylesheet" href="{{ asset("style.css") }}">
Splitting content into sections
PartialRenderer breaks a markdown note into logical blocks — useful for landing pages, FAQs, and card grids:
{{ intro := note.PartialRenderer().Introduce() }}
<p class="lead">{{ intro.ContentHTML | unsafe }}</p>
{{ range i, s := note.PartialRenderer().Sections(3) }}
<details>
<summary>{{ s.TitleHTML | unsafe }}</summary>
{{ s.ContentHTML | unsafe }}
</details>
{{ end }}
Introduce()— content before the first headingSections(level)— sections under headings of a given levelSection("Title")— a specific section by heading text
Organizing multiple templates
For sites with shared header, footer, and styles, use a blocks.html file:
_layouts/
└── my-theme/
├── blocks.html — shared header, footer, wrapper
├── page.html — standard article page
└── landing.html — landing page
blocks.html defines reusable blocks; page.html imports and uses them:
{{ import "blocks" }}
{{ yield main_layout() content }}
<article class="prose">
<h1>{{ note.Title() }}</h1>
{{ note.HTMLString() | unsafe }}
</article>
{{ end }}
Jet template syntax
Templates use the Jet engine:
{{ variable }} — output
{{ if condition }}...{{ end }} — conditional
{{ range i, item := list }}...{{ end }} — loop (always capture both index and value)
{{ block name() }}...{{ end }} — define a block
{{ yield name() }} — call a block
{{ include "path" data }} — include a partial
{{ value | unsafe }} — output HTML without escaping
Two Jet rules to remember:
- Block parameters need default values or named arguments won't bind:
{{ block card(title="", body="") }} contentis a reserved keyword — don't use it as a parameter name
Querying notes in templates
nvs.ByGlob() selects notes by path pattern and supports sorting and pagination:
{{ range i, post := nvs.ByGlob("blog/*.md").SortBy("CreatedAt").Desc().Limit(5).All() }}
<a href="{{ post.Permalink() }}">{{ post.Title() }}</a>
{{ end }}
Methods: SortBy("Title"), SortBy("CreatedAt"), SortByMeta("order"), .Desc(), .Asc(), .Limit(n), .Offset(n), .All(), .First(), .Last()