Typst is the template

Blocks on a grid, one language filling the layout.
Contents

Most site generators ask you to hold two languages at once: one for prose, one for the markup around it. The seam between them is where the awkwardness lives. A loop belongs to the template language, a footnote to the content language, and a footnote inside a loop belongs to an argument.

One language

Here there is no seam. A heading is a heading, and the layout that wraps it is written in the same language, with the same functions:

#let page(page, body) = h("article", {
  h("h1", page.frontmatter.title)
  body
})

That template is not a string being assembled. It builds real elements, which is why an attribute with a hyphen, an ARIA role, or an inline <svg> needs no escape hatch.

What that buys

Your pages, your layouts, and your data are one language, so a heading, a footnote, and a nav menu are all written the same way.

— the README

  1. 1Like this one.