Skip to content

triplate, to:=safely template RDF languages with ease

Triplate lets you write templates for RDF query and data languages, with typed parameters, loops, and conditionals. It’s designed for dynamically generating SPARQL queries in backend and AI applications, though it can also be used to generate other languages such as Markdown, HTML, or CSV.

What sets it apart from other templating languages is that all parameters are validated and escaped according to their declared RDF type, so rendered output is injection-safe by construction. Triplate’s syntax is deliberately invalid in the host language, so any unprocessed template parameters fail fast rather than silently producing malformed output.

SPARQL Query

Template SPARQL queries for backend applications and AI agents — typed, validated parameters instead of string concatenation. Query examples →

RDF Data

Stamp author and provenance metadata onto RDF artefacts, or generate synthetic Turtle/TriG datasets from plain records. Data examples →

The following example illustrates a SPARQL query and many of the unique features, such as the frontmatter, for loops and conditionals:

---
params {
service: iri
classes: iri[] min 1
limit: int optional
}
example demo "DBpedia" {
service: "http://dbpedia.org/sparql"
classes: [ foaf:Person, foaf:Organization ]
limit: 10
}
---
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?s WHERE {
SERVICE ${service} {
{% for c in classes join "UNION" %}
{ ?s a ${c} }
{% endfor %}
}
}
{% if limit %}LIMIT ${limit}{% endif %}

The example section named demo will be rendered with the following output:

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?s WHERE {
SERVICE <http://dbpedia.org/sparql> {
{ ?s a foaf:Person } UNION { ?s a foaf:Organization }
}
}
LIMIT 10

Zero dependencies

No runtime dependencies in any implementation — the TypeScript, Python and Java cores are pure-language. (Python’s optional term type uses rdflib only if you install the extra.)

Injection-safe by construction

Each value is validated and escaped per its declared RDF type. The only unescaped path is the explicit raw type.

One typed header

A single ------ frontmatter declares every input — type, cardinality (min/max), optionality — and is stripped from the output. The body stays clean ${ } references.

Host-agnostic & fail-fast

The ${ }, $"…", $<…>, {% … %} syntax and the leading --- are invalid in SPARQL/Turtle/TriG/N-Triples, so an unprocessed template can never run by mistake.

Loops & conditionals

{% for %} with join, the ${...x} spread operator, and {% if %} with type-directed conditions that make optional params usable.

Runnable examples

example blocks let an IDE preview and execute a query without hand-built input — fixtures for development, never production defaults.

Three reference implementations

TypeScript, Python and Java — verified byte-identical by a shared conformance suite.

General-purpose engines treat SPARQL queries or RDF documents as opaque text; Triplate understands the RDF term model it emits.

Triplate Jinja2 Mustache Jena PSS¹
RDF-typed params (iri, pname, literal(<dt>), …) ◐²
SPARQL/Turtle-aware escaping (injection-safe) ○³ ○³
Whole context validated before rendering
IRI minting — percent-encoded, validated absolute
@lang / ^^datatype literal construction ◐²
Dynamic query shape (loops with join, if)
Unrendered template fails fast at the endpoint
Byte-identical across TypeScript, Python, Java ◐⁴ ◐⁴
● full support◐ partial○ none— not applicable

¹ Apache Jena ParameterizedSparqlString (Java-only, SPARQL-only).

² Code-side via Jena objects, not declared in the template.

³ Autoescaping targets HTML, not SPARQL.

⁴ Ports exist (Nunjucks, Jinjava, …) but diverge in semantics.