STE Reference
Complete syntax reference for LiteNode's Simple Template Engine — variables, tags, filters, and nested loops.
Blog-Doc templates are rendered by LiteNode's STE (Simple Template Engine), an AST-based engine. All expressions use {{ }} delimiters.
Variables
{{ site.title }}
{{ post.date }}
{{ pagination.currentPage }}
Nested properties use dot notation. Array items by index:
{{ post.tags[0] }}
Bracket notation for keys with special characters:
{{ user["first-name"] }}
Raw HTML injection
Variables whose name starts with html_ are injected as unescaped HTML. Blog-Doc uses this for rendered Markdown:
{{ html_content }}
Never pipe untrusted content into an html_ variable — it renders as-is.
Important:
{{site.headerCode}}injects raw HTML directly (nohtml_prefix needed for settings values). Do not use{{html_site.headerCode}}— it does not work. The same logic applies to{{site.footerCode}}.
Expressions
Arithmetic
{{ pagination.currentPage * 10 }}
{{ posts | length }}
Comparison — operators: =, ==, ===, !=, !==, >, >=, <, <=
{{#if pagination.currentPage > 1}}…{{/if}}
Logic — operators: &&, ||, !
{{#if post.featured_image && post.featured_image != ""}}…{{/if}}
Ternary
{{ post.category ? post.categoryName : "Uncategorised" }}
if / elseif / else / not
{{#if postRoute}}
<p>Reading a post.</p>
{{#elseif pageRoute}}
<p>Reading a page.</p>
{{#else}}
<p>Welcome home.</p>
{{/if}}
not is shorthand for a single falsy check:
{{#not post.featured_image}}
<img src="/assets/default.webp" alt="Default cover" />
{{/not}}
each
Iterates over arrays and objects.
Inside a loop: {{this}} is the current item, {{@index}} is the zero-based index, {{@key}} is the current key.
{{#each posts}}
<h2><a href="/blog/{{ slug }}">{{ title }}</a></h2>
<p>{{ excerpt }}</p>
{{#if category}}
<span>{{categoryName}}</span>
{{/if}}
{{/each}}
Simple arrays:
{{#each tags}}
<span class="tag">{{ this }}</span>
{{/each}}
Nested loops
Use numbered suffixes to avoid variable conflicts:
{{#each menus.primary}}
<li>{{ label }}
{{#if children | length}}
<ul>
{{#each1 children}}
<li>{{ label }}
{{#if children | length}}
<ul>
{{#each2 children}}
<li>{{ label }}</li>
{{/each2}}
</ul>
{{/if}}
</li>
{{/each1}}
</ul>
{{/if}}
</li>
{{/each}}
The suffix increments with each nesting level: {{#each}}, {{#each1}}, {{#each2}}.
include
Pulls in another template file. The included file inherits the full data context.
{{#include("partials/header.html")}}
{{#include("partials/footer.html")}}
Prefer absolute paths from the templates/ root. Blog-Doc runs in root mode and relative paths can lose context in deeply nested includes.
Inside a loop, included files see the current loop item:
{{#each posts}}
{{#include("partials/post-card.html")}}
{{/each}}
set
Define or overwrite a variable within the template:
{{#set activeClass = "is-active"}}
{{#set recentPosts = posts | take(3)}}
set supports filters:
{{#set reversedTags = post.tags | reverse}}
Filters
Applied with the pipe operator |. Chainable.
| Filter | Example | Output |
|---|---|---|
dateFormat |
{{ post.date | dateFormat("MMMM D, YYYY") }} |
June 1, 2025 |
timeAgo |
{{ post.date | timeAgo }} |
2 days ago |
truncate |
{{ post.title | truncate(50) }} |
My long title... |
truncateWords |
{{ post.excerpt | truncateWords(20) }} |
First twenty words... |
join |
{{ post.tags | join(", ") }} |
javascript, node |
length |
{{ posts | length }} |
12 |
capitalize |
{{ post.categoryName | capitalize }} |
General |
uppercase |
{{ site.language | uppercase }} |
EN |
slugify |
{{ post.categoryName | slugify }} |
web-dev |
defaults |
{{ post.featured_image | defaults("/default.webp") }} |
fallback value |
take |
{{ posts | take(3) }} |
first 3 items |
skip |
{{ posts | skip(1) }} |
all but first |
reverse |
{{ posts | reverse }} |
reversed array |
where |
{{ posts | where("status", "published") }} |
filtered array |
sortBy |
{{ pages | sortBy("order") }} |
sorted array |
first |
{{ post.tags | first }} |
first item |
last |
{{ post.tags | last }} |
last item |
escape |
{{ post.title | escape }} |
HTML-escaped string |
wordCount |
{{ post.excerpt | wordCount }} |
42 |
has |
{{ theme.features | has("blog") }} |
boolean |
Full filter reference: LiteNode Filters