# Templates and shortcodes

How a page is assembled from small templates and shortcodes, and how templates are found.

Templates use shortcodes enclosed in `[#` and `#]`.

```
[#shortcode#]
[#shortcode param#]
[#shortcode key=value key2=value2#]
```

Shortcodes can be nested - any parameter value or shortcode name can itself contain a shortcode:

```
[#get data.users.[#get selected-id#]#]
```

This also works inside `tpl=` parameters and shortcode names, which lets you **compose template names dynamically**:

```
[#if current_image=(not-empty) tpl=card-image[#if current_image=(empty) echo=-placeholder#]#]
```

Resolves to `tpl=card-image` when an image exists, `tpl=card-image-placeholder` when it doesn't.

A particularly powerful application is **content-type dispatch** - embed a type field directly in the shortcode name to route to a type-specific template without any branching:

```
[#card-[#get item.type#]#]
```

Resolves to `[#card-news#]`, `[#card-event#]`, `[#card-download#]`, etc. based on the item's type. This pattern eliminates chains of `[#if item.type=X tpl=Y#]` conditions and scales cleanly as new types are added.

Use `default=` to guarantee a valid shortcode name when the value may be missing or unrecognised - an unresolved shortcode renders as literal text in the output:

```
[#card-[#get item.type default=unknown#]#]
```

Implement `[#card-unknown#]` as a generic fallback (or leave it empty to render nothing).

Templates are plain files in the target output format (HTML, JSON, CSS, etc.). They have a `.tpl` extension.

## Route templates

Every URL maps to a file in `ext/uri/`:

```
ext/uri/index.tpl              → /
ext/uri/about/index.tpl        → /about/
ext/uri/blog/(slug)/index.tpl  → /blog/<anything>/
```

A route template renders the page:

```
[#html#]
```

The `main.tpl` in the same folder contains the page body, rendered inside the HTML shell. It is always scoped to that route - even `ext/uri/main.tpl` is only the body for the home page (`/`), not a global layout.

## Reusable templates

Stored in `ext/tpl/<name>/index.tpl`. Called with their name as a shortcode:

```
[#hero-section#]
```

Template components do **not** receive parameters directly. To pass data to a template, use `[#set ... overwrite#]` before calling it:

```
[#set back_url=/agenda overwrite#]
[#back-button#]
```

Inside the template, read the variable with `[#get back_url default=/#]`. Lib shortcodes (`ext/lib/<name>/`) are different - they receive `$params` and can be called with inline parameters.


## URI-scoped templates

Templates can also live flat inside a URI folder (not in a subfolder). These are not routes - they are partial templates included from within that route's `index.tpl` or `main.tpl`.

```
ext/uri/new/page-settings-fields.tpl   ← partial, not a route
ext/uri/new/index.tpl                  ← route
ext/uri/new/main.tpl                   ← route body
```

Important: a subfolder inside `ext/uri/` **always** creates a new route. A flat `.tpl` file in a URI folder is a partial template scoped to that route.
