Control Flow
Conditionals, loops, includes, comments, and escaping for dynamic template logic.
Conditionals
Use @if, @elseif, @else, and @endif to conditionally render content:
@if(show_header)
<header>Welcome back!</header>
@endifElse and elseif
Chain conditions for more complex logic:
@if(role == "admin")
<span class="badge">Admin</span>
@elseif(role == "editor")
<span class="badge">Editor</span>
@else
<span class="badge">Guest</span>
@endifTruthiness rules
Conditions are evaluated as truthy or falsy. The following values are considered falsy:
falsenullor undefined variables- Empty strings
"" - The number
0 - Empty arrays
[]
Everything else is truthy. This means you can check for the presence of a variable directly:
@if(page.subtitle)
<p class="subtitle">{{ page.subtitle }}</p>
@endifLoops
Use @for and @endfor to iterate over arrays:
@for(item in items)
<li>{{ item }}</li>
@endforAccessing properties in loops
When iterating over objects, use dot notation to access their properties:
@for(post in posts)
<article>
<h2>{{ post.title }}</h2>
<time>{{ post.date }}</time>
<p>{{ post.summary }}</p>
</article>
@endforCombining loops with conditionals
@for(page in pages)
@if(page.published)
<a href="{{ page.url }}">{{ page.title }}</a>
@endif
@endforIncludes
Use @include to inline another template file. The included file is rendered in place with access to the same variables:
@include('components/nav')The path is relative to the project root, without the .tulip extension:
<!-- layouts/main.tulip -->
<html>
<head>
@include('partials/head')
</head>
<body>
@include('partials/header')
@yield('content')
@include('partials/footer')
</body>
</html>Comments
Template comments are completely stripped from the rendered HTML output:
{{-- TODO: add pagination here --}}
{{-- This entire block is for the beta feature --}}
@if(beta_enabled)
<div>Beta content</div>
@endifUnlike HTML comments (<!-- -->), template comments produce no output at all.
Escaping
If you need to output a literal @ character in your template (for example, in an email address), use @@:
Contact us at hello@@example.comThis renders as:
Contact us at hello@example.comCode blocks
Use @code to embed syntax-highlighted code examples. Content inside is treated as raw text — directives, expressions, and HTML are not processed:
@code('toml')
[site]
name = "My Site"
@endcodeThis renders a <pre><code class="language-toml"> block. HTML inside is automatically escaped — no need for &lt; entities. Tulip supports a custom tulip language for template code highlighting.
Verbatim
Use @verbatim to output content without processing any directives or expressions:
@verbatim
{{ this will not be evaluated }}
@if(neither will this)
@endverbatimEverything between @verbatim and @endverbatim is emitted as plain text.