# Templates

A template in Celena is a set of `.tpl` files inside `templates/<slug>/`. **PHP in `.tpl` is forbidden** (the `<?php`/`<?=` tags are escaped as text) — you use only template-engine tags. This is safe, convenient for markup and easy to document.

On first access a `.tpl` is compiled to PHP and cached in `storage/cache/tpl/`. Invalidation is automatic, based on the file's modification time.

## Syntax

### Variables

```html
{title}                <!-- $vars['title'], auto-escaped -->
{user.name}            <!-- dot access -->
{news.body|raw}        <!-- unescaped (trusted HTML) -->
```

### Inline tags

A tag with parameters is a handler call:

```html
{include file="_partials/head.tpl"}
{lang key="hello.world"}
{csrf}                          <!-- hidden field -->
{csrf format="meta"}            <!-- <meta name="csrf-token"> for AJAX -->
{icon name="check" size="20"}   <!-- inline SVG icon -->
{plugin_assets}                 <!-- CSS/JS of active plugins -->
```

Interpolation `{var}` is allowed in parameters:

```html
{lang key="greeting" name="{user.name}"}
```

### Conditions

```html
[if {user.role}="admin"]
  Hi, boss.
[else if {user.role}="editor"]
  Hi, editor.
[else]
  Guest.
[/if]

[if {is_published}]            <!-- truthy check -->
  Published
[/if]
```

Operators: `=`, `!=`, `>`, `<`, `>=`, `<=`. `>`/`<` comparisons are numeric, the rest are string. You can compare two variables: `[if {a}={b}]…[/if]`.

### Loops

```html
[foreach var="news" as="n"]
  <article>
    <h2><a href="{n.url}">{n.title}</a></h2>
    <small>{n.date} · {n.author}</small>
  </article>
[/foreach]
```

Helper variables inside a loop:

| Variable | Meaning |
|----------|---------|
| `{_index}` | 0-based iteration number |
| `{_total}` | total elements |
| `{_first}` | `"1"` if first, otherwise `""` |
| `{_last}` | `"1"` if last |

If the array is empty, the body isn't rendered. Loops and conditions can be nested.

### Comments

```html
{* This text won't appear in the output *}
```

## Theme structure

```
templates/mytheme/
├── theme.json          theme manifest
├── home.tpl            home page
├── page.tpl            regular page
├── news_list.tpl       news list
├── news_full.tpl       single article
├── search.tpl          search
├── 404.tpl             404 error
├── _partials/          reusable pieces (head, header, footer)
└── assets/             theme CSS/JS
```

## Variables the core always passes

```
{site.name}   {site.url}
{page.title}  {page.seo_title}  {page.seo_description}  {page.og_image}
{locale}      {canonical_self}
{account.is_guest}  {account.name}
```

## Protecting `<script>` and `<style>`

The contents of `<script>`/`<style>` are protected from block-tag parsing (CSS selectors like `[data-x]` won't be mistaken for tags). Inline tags such as `{lang …}` still work inside scripts — so you can translate JS-generated markup.

## Async blocks

A heavy section can be loaded with a separate request after the page renders:

```html
{async block="latest_news" url="/api/blocks/latest_news" placeholder="Loading…"}
```

Parameters: `trigger` (`load`/`visible`/`manual`), `poll` (`30s`/`5m`), `class`. After loading, the container gets the `is-loaded` class.

## Restrictions

- `<?php`, `<?=` — escaped as text.
- Direct DB/session/file access from a template is not allowed (only via registered tags or async blocks).
- Third-party CDNs are forbidden (CSP). Keep all assets in `templates/<slug>/assets/`.
