Expressions

Output variables, access nested values, and control HTML escaping in your templates.

Variable output

Use double curly braces to output a variable. HTML is escaped by default to prevent XSS:

{{ site.name }}
{{ page.title }}

If a variable contains <script>alert('xss')</script>, the output will be safely escaped as &lt;script&gt;alert('xss')&lt;/script&gt;.

Raw output

When you need to output unescaped HTML, use the raw syntax:

{!! raw_html !!}
Only use raw output with the raw expression syntax when you trust the content. Never use it with user-provided data.

HTML escaping

By default, all expressions escape these characters:

  • & becomes &amp;
  • < becomes &lt;
  • > becomes &gt;
  • " becomes &quot;
  • ' becomes &#x27;

This makes {{ }} safe for use in HTML attributes and text content alike:

<a href="{{ link_url }}" title="{{ link_title }}">
    {{ link_text }}
</a>

Dot notation

Access nested values using dot notation. This works with site configuration, page frontmatter, and any structured data:

{{ site.name }}
{{ site.base_url }}
{{ site.description }}
{{ page.title }}
{{ page.date }}
{{ author.name }}

Available variables

Site variables

Every field in the [site] section of tulip.toml is available via the site prefix. The built-in fields are:

  • {{ site.name }} — the site name
  • {{ site.base_url }} — the base URL
  • {{ site.description }} — the site description

You can add any custom fields and they become available as variables:

[site]
name = "My Blog"
base_url = "https://example.com"
author = "Eduardo"
github = "https://github.com/eduardostuart"

Then use them in templates:

<footer>{{ site.author }} — <a href="{{ site.github }}">GitHub</a></footer>

Page variables

Frontmatter fields defined at the top of a page or markdown file are available as template variables:

---
title: My Page
date: 2025-01-15
author: Jane
---

These become:

{{ title }}    <!-- "My Page" -->
{{ date }}     <!-- "2025-01-15" -->
{{ author }}   <!-- "Jane" -->

Expressions in attributes

Expressions work inside HTML attributes just like in text content:

<meta name="description" content="{{ site.description }}">
<body class="{{ page.body_class }}">
<img src="{{ page.image }}" alt="{{ page.title }}">