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 (no html_ 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