Skip to content

The Frontmatter

Every template begins with a --- frontmatter header declaring its inputs. The whole block is consumed (nothing leaks into the output); the body then uses bare ${ name } references — no inline types.

---
params {
service: iri
endpoint: iri optional
classes: iri[] min 1
tags: string[] optional max 5
people: { id: iri, name: string optional }[] min 1
limit: int
}
---
  • Sections are brace-delimited. params { … } is mandatory; example … { … } blocks are optional (see Example blocks). params and example are keywords only here, so any parameter name is allowed.
  • Types: iri, pname, string, int, decimal, double, bool, date, dateTime, time, literal(<dt>), term, raw.
  • Modifiers (in order): <type> ['[]'] ['optional'] ['min' N] ['max' N]. [] marks an array; min/max bound its length; optional marks that a value may be omitted.
  • raw inserts verbatim with no escaping — the single auditable unsafe hatch, visible in the header.

The engine validates the whole context against the header up front (missing required, unknown key, wrong type, out-of-range cardinality). Typing is strict: "10" is not an int, a list is not a scalar.

${ name } / ${ p.id } reference declared params or loop variables. The same reference serializes differently by construct: standalone → per its declared type; inside $"…" → string-escaped; inside $<…> → percent-encoded.

Keywords and type names are case-insensitive; variable names, IRIs, and string content are case-sensitive.

---
params {
service: iri # the endpoint this query federates to
people: {
id: iri # stable identifier
name: string
}[] # one row per person
}
# everything below is preview-only
example demo {
service: <http://dbpedia.org/sparql>
people: [
{ id: <http://ex.org/1>, name: "Ada" }, # the first row
{ id: <http://ex.org/2>, name: "Grace" }
]
}
---

# runs to the end of the line. Put one wherever an item may start — at any nesting depth — or trail an item on the same line: between sections, between declarations or bindings, between the fields of a record type, and between the elements of an example list or record.

A comment may not split an item, so name # … : string is a syntax error.

Comments live in the header only. In the body # is ordinary text and does not suppress interpolation — # ${title} renders as a Markdown heading with ${title} filled in. See Specification §2.2 for the normative rule.

Comments never reach the output, but they are not thrown away either: each one survives as a positioned comment symbol in symbols(), so a formatter or IDE can re-indent a header without losing them.

example dbpedia "DBpedia — people & orgs" {
service: <http://dbpedia.org/sparql>
classes: [ foaf:Person, foaf:Organization ]
limit: 10
}

An example <id> ["<description>"] { … } block (in the --- frontmatter, alongside params) declares a named, validated set of sample values. They are development/preview fixtures, not production defaults: render(context) still requires real values, while previewExample(id) / a CLI renders with a set so a query is runnable while you develop. An IDE lists blocks by id and shows the description. Prefixed names resolve against the template’s PREFIX declarations.

A leading --- frontmatter header is a positive “this is a Triplate template” marker, complementing the fail-fast guarantee (the body is invalid host syntax until rendered).