Syntax Latte was born out of the practical requirements of web designers. We were looking for the most user-friendly syntax, with which you can elegantly write constructs that are otherwise a real challenge. At the same time, all expressions are written exactly the same as in PHP, so you don't have to learn a new language. You just make the most of what you already know.

Below is a minimal template that illustrates a few basics elements: tags, n:attributes, comments and filters.

{* comment *}
<ul n:if="$items">
{foreach $items as $item}
	<li id="item-{$iterator->counter}">{$item|capitalize}</li>

Let's take a closer look at these important elements and how they can help you build an incredible template.


A template contains tags, which control the template's logic (such as for-loops) or output expressions. They use a use only one delimiter: { ... }, so you don't have to think about which delimiters to use in which situations, as with other systems.

You can find detailed description of all the built-in tags. Furthermore, you can make your own tags.

{$item|capitalize} tag which prints the $item variable contains so called filter, in this case the capitalize filter which makes the first letter of each word uppercase.

A very important feature of Latte is that it escapes variables by default. Escaping is needed when printing a variable because we have to convert all the characters which have a special meaning in HTML to other sequences. In case we forget it can lead to a serious security hole called Cross-Site Scripting (XSS). Because of different escaping functions that are needed in different documents and different parts of a page, Latte features a unique technology of security which recognizes the context in which the tag is placed and chooses the right escaping mode. You don't have to worry that your coder forgets about it causing you goosebumps because of a security hole. Which is great!

If the $item variable stores trusted HTML code and you want to print it without any alteration you just add the filter noescape. Forgetting the filter won't cause any security holes in the spirit of „less code, more security“ principle.

Inside the tags, we can use PHP as we know it. Even including comments. Latte also adds some nice features to the PHP syntax:

  1. we can omit quotes around the strings consisting of letters, numbers, and dashes
  2. short condition notation $a ? 'b' which is the same as $a ? 'b' : null in PHP
  3. you can use filters $a|upper
  4. you can use undefined-safe operator like $var??->call()??->elem[1]??->item

For example:

{$cond ? hello}  // prints 'hello' if $cond equals true

{$order->item??->name} // means isset($order->item) ? $order->item->name : null


Each pair tag, such as {if} … {/if}, operating upon single HTML element can be written in n:attribute notation. For example, {foreach} in the above example could also be written this way:

<ul n:if="$items">
	<li n:foreach="$items as $item">{$item|capitalize}</li>

The functionality then corresponds to the HTML element in which it is written:

{var $items = ['I', '♥', 'Nette Framework']}

<p n:foreach="$items as $item">{$item}</p>


<p>Nette Framework</p>

By using inner- prefix we can alter the behavior so that the functionality applies only to the body of the element:

<div n:inner-foreach="$items as $item">


	<p>Nette Framework</p>

Or by using tag- prefix the functionality is applied on the HTML tags only:

<p><a href="{$url}" n:tag-if="$url">Title</a></p>

Depending on the value of $url variable this will print:

// when $url is empty

// when $url equals ''
<p><a href="">Title</a></p>

However, n:attributes are not only a shortcut for pair tags, there are some pure n:attributes as well, for example the coder's best friend n:class.


See the summary of standard filters.

Latte allows calling filters by using the pipe sign notation (preceding space is allowed):


Filters can be chained, in that case they apply in order from left to right:


Parameters are put after the filter name separated by colon or comma:


Filters can be applied on expression:

{var $name = ($title|upper) . ($subtitle|lower)}</h1>

On block:

<h1>{block |lower}{$heading}{/block}</h1>

Or directly on value (in combination with {=expr} tag):

<h1>{='  Hello world  '|trim}<h1>


Optional Chaining with Nullsafe Operator

Optional chaining lets us write code where Latte immediately stops evaluating expressions if it encounters null. With the new ?-> operator allowing optional access to variables or array elements. PHP 8 brings the same thing, but you can also use it in PHP 7 in Latte.

When we write code like


this is a way of saying that when $order is not null, $order->id will be computed, but when $order is null, stop what we’re doing and just return null.

You might find yourself using ?-> to replace a lot of code that performs repetitive nullish checks:

// roughly means ($user !== null) && ($user->address !== null) ? $user->address->street : null

// roughly means ($items[2] !== null) ? $items[2]->count : null

// roughly means $user->getIdentity() !== null ? $user->getIdentity()->name : null

The meaning are “roughly” because in fact the expression is evaluated more sophistically and no step is repeated. For example, $user->getIdentity() is called only once, so there cannot be a problem due to an object being returned in the condition and then null.

Optional chaining expressions can be used anywhere, for example, in terms of:

{if $blogPost?->count('*')}
	// means if (isset($blogPost) && $blogPost->count('*'))

Optional Chaining with Undefined-Safe Operator

The undefined-safe operator ??-> is similar to the nullsafe operator ?->, but does not raise an error if a variable, property, or index does not exist at all.


this is a way of saying that when $order is defined and not null, $order->id will be computed, but when $order is null or doesn't exist, stop what we’re doing and just return null.

You might find yourself using ?-> to replace a lot of code that performs repetitive nullish checks:

// roughly means isset($user) && isset($user->address) ? $user->address->street : null

Array Expansion Operator (expand)

The (expand) operator allows you to use an array where multiple arguments are expected. This is the equivalent of the ... operator from PHP, but retaining the keys.

It can be used, for example, to pass arguments into blocks or included templates if we have them in the array.

{include 'foobar.latte' (expand) $args}          {* arguments for include *}


Latte also has a {* comment tag *} which doesn't get printed to the output.