Skip to content

Template syntax cheat sheet ​

A template has exactly one root element, which carries class="root". The root cannot use directives.

FeatureSyntaxNotes
Text{expression}A top-level signal is unwrapped. Write a literal brace as {"{"}.
Attribute binding:title="expression"Re-evaluated when its signals change.
Static attributetitle="text"
Event@click="handler" or @click="count++"Native DOM events. A handler is a function name or a statement.
Behavior event@press="handler"Needs the behavior in the contract (T4015).
Two-way bindingbind:value="name"On input, textarea, select; name must be a state().
Element referenceref="box"On an HTML element; box must be a state(). It holds the element while it is on the page, and null after.
SVG<svg viewBox="0 0 100 40"><svg> and everything in it is created as SVG. Attributes keep their case (viewBox, attributeName).
Conditionalif="expr", else-if="expr", elseOn consecutive sibling elements.
Listeach="item in items" key="item.id"A key is required (T4011).
Slot<slot />, <slot name="icon" />Declared in the contract. Content may be a fallback.
Fill a slotslot="icon" on a childGoes to that named slot; other children go to the default.
Component<Button tone="danger">Found by name; variants, events and slots are checked.
Classclass="root"Scoped to the component. :class is not scoped (W4102).

Script names in a template ​

A name in an expression must be declared in <script> or be an each variable (T4006). Signals are unwrapped only when they are top-level bindings; {state.field} where field is a signal is T4012.

Always available in a script ​

state, derived, effect, onCleanup, onMount, props, emit, and in pages and components useRoute and navigate. They need no import in a .tess file; see Auto-imports.

The blocks ​

BlockInPurpose
<contract>componentsJSON: the component's public surface. Must not appear in pages and layouts.
<script>allLogic.
<template>allOne root element.
<style>allCSS with nesting and $token values.
<page>pagesJSON: title, layout.