shizuka
shizuka  /  docs

Making Templates

How Shizuka renders pages with Go html/template.

Shizuka templates are Go html/template files. Each content page selects a template by name from the frontmatter key template = "...", unless a config default supplies the template.

Folder Structure

By default, paths.templates points at the template directory:

templates/
  html/
    page.tmpl
  md/
    demo.tmpl

HTML page layouts are loaded from templates/html/**/*.tmpl. Markdown component templates are loaded from templates/md/**/*.tmpl when markdown components are enabled.

Names

You can define multiple named templates in each file. You can then reference these names in other templates, or in content frontmatter.

Defined template names must be unique across all template files in their folder.

Page Rendering

Each page is rendered with this root object:

KeyMeaning
.PageThe current page.
.SiteGlobal site data.

Page Fields

FieldMeaning
.Page.Title, .Page.Description, .Page.Tags, .Page.Featured, .Page.DraftBasic page fields.
.Page.PathRoot-relative route path, for example / or /posts/hello/.
.Page.SlugPage identifier. Explicit slugs come from frontmatter; missing or duplicate slugs receive generated hex values.
.Page.WeightInteger ordering hint.
.Page.CanonAbsolute canonical URL.
.Page.SectionResolved section name.
.Page.ParamsArbitrary map.
.Page.Created, .Page.Updated, .Page.PubDatetime.Time values.
.Page.File.Available, .Page.File.Created, .Page.File.Updated, .Page.File.SizeSource file data.
.Page.Bodytemplate.HTML.
.Page.Sections[]template.HTML, split on Markdown thematic breaks. Use a blank line before a separator after paragraph text.
.Page.ToCMarkdown headings as { Level, ID, Text } entries.

Optional Git Metadata

FieldMeaning
.Page.Git.TrackedWhether the page source is tracked by Git.
.Page.Git.Created, .Page.Git.UpdatedFirst and latest Git commit timestamps for the page source.
.Page.Git.CommitHash, .Page.Git.ShortHash, .Page.Git.AuthorNameLatest Git commit data for the page source.

Tables of Contents

You can access headers via .Page.ToC. Level is the heading level, Text is the plain heading text, and ID is the rendered heading ID.

Enable content.markdown.parser.auto_heading_id to generate IDs for headings without explicit IDs. Enable content.markdown.parser.attribute when pages use explicit heading IDs such as ## Install {#install}.

Site Fields

FieldMeaning
.Site.Title, .Site.Description, .Site.URLConfigured site identity.
.Site.ParamsConfigured params map.
.Site.Dev, .Site.BuildTimeBuild mode and timestamp.

Optional Git Metadata

FieldMeaning
.Site.Git.Available, .Site.Git.RepoRoot, .Site.Git.GitDirRepository paths.
.Site.Git.Branch, .Site.Git.CommitHash, .Site.Git.ShortHash, .Site.Git.DirtyCurrent Git state.

Template functions

FunctionMeaning
datefmt layout tFormat a time value; returns "" for zero time.
uniq valuesDeduplicate []string, preserving original order.
firstReturn the first item from an array-like value.
dict key value ...Build a map[string]any.
merge map ...Merge maps; later maps win.
raw valueConvert a string to template.HTML.
markdown valueRender Markdown text to template.HTML using configured markdown options.
debug valueRender any value as escaped nested HTML tables for inspection.
debugShort valueLike debug, but omits zero and empty values.
discardAbort the current template artefact without failing the build.

Queries

FunctionMeaning
query sql args...Return []map[string]any.
queryRow sql args...Return the first row as map[string]any, or nil.
queryPages sql args...Return page template data objects; the result must include _page.
queryPage sql args...Return the first page template data object, or nil; the result must include _page.

The built-in query tables include pages and tags. select * from pages ... includes _page, so use queryPages when you want page objects. Projected queries like select Title from pages return ordinary row data and can use query.

{{ queryPages "select * from pages where Section = ? order by Created desc limit ?" "posts" 5 }}

tags has one row per page/tag occurrence. It includes Tag, TagSlug, PageSlug, PagePath, PageTitle, Section, Draft, PubDate, Weight, and _page, so tag indexes can filter by page fields without reshaping .Page.Tags in templates.

{{ query "select distinct TagSlug, Tag from tags where Section = ? order by Tag" "posts" }}
{{ queryPages "select _page from tags where TagSlug = ? order by PubDate desc" "shizuka" }}

If a data/ directory exists, its manifests may register additional tables for the same query functions.

Pagination

FunctionMeaning
paginate perPage template itemsAbort the current render and render numbered child pages from items.
paginateRoot perPage pageTemplate rootTemplate itemsLike paginate, but also render rootTemplate at the current page route.
paginateOn field template itemsAbort the current render and render one child page per comparable field value.
paginateOnRoot field pageTemplate rootTemplate itemsLike paginateOn, but also render rootTemplate at the current page route.

Pagination functions are render effects. They discard any bytes already written by the current template and request new template renders.

paginate chunks a slice or array into numbered child routes under the current page:

{{ queryPages "select * from pages where Section = ? order by Created desc" "posts" | paginate 10 "posts-page" }}

If the current page is /posts/, the generated pages are /posts/1/, /posts/2/, and so on. Use paginateRoot when the source route should also produce output:

{{ queryPages "select * from pages where Section = ?" "posts" | paginateRoot 10 "posts-page" "posts-root" }}

paginateOn groups input items by a named map key or exported struct field and renders one child route per group:

{{ query "select Params.tag as Tag, Title from pages" | paginateOn "Tag" "tag-page" }}

Group values must be comparable. String group values are used directly as URL path segments, so values containing spaces, slashes, or other unsafe path characters fail the build instead of being slugified.

Paginated templates receive the normal .Page and .Site data, plus .Pagination:

FieldMeaning
.Pagination.ItemsItems selected for this generated page or group.
.Pagination.Page, .Pagination.PagesCurrent page number and total page count.
.Pagination.Total, .Pagination.PerPageTotal selected items and chunk size.
.Pagination.Prev, .Pagination.NextPrevious and next route paths, when present.
.Pagination.GroupGroup value for paginateOn; nil for paginate.

Everything else is standard Go template behavior: range, if, len, index, and the usual comparison functions.

Example

{{ define "page" }}
<!doctype html>
<html lang="en">
<body>
    <main>{{ .Page.Body }}</main>
</body>
</html>
{{ end }}