Skip to content

Tutorial — the Counter

Welcome! 👋 In this tutorial you build the counter, tempestweb's canonical app, from scratch. It is a + button, a - button and a text showing the count. Simple — but it exercises the entire wire contract: the view tree, state, handlers, patches and the two execution modes.

We go one concept per page, in order:

Prerequisite

You only need to have done the Installation. Each page assumes only the previous one — start on page one and keep going.

What we will build

By the end, this is the complete app — exactly what lives in examples/counter/app.py:

"""Counter — the canonical tempestweb example."""

from __future__ import annotations

from dataclasses import dataclass

from tempest_core import App, Button, Column, Row, Style, Text, Widget
from tempest_core.style import Edge


@dataclass
class CounterState:
    """State for the counter app."""

    value: int = 0


def make_state() -> CounterState:
    """Build the initial state."""
    return CounterState()


def view(app: App[CounterState]) -> Widget:
    """Render the counter UI from the current state."""

    def increment() -> None:
        app.set_state(lambda s: setattr(s, "value", s.value + 1))

    def decrement() -> None:
        app.set_state(lambda s: setattr(s, "value", s.value - 1))

    return Column(
        style=Style(gap=8.0, padding=Edge.all(16)),
        children=[
            Text(content=f"Count: {app.state.value}", key="label"),
            Row(
                style=Style(gap=4.0),
                children=[
                    Button(label="-", on_click=decrement, key="dec"),
                    Button(label="+", on_click=increment, key="inc"),
                ],
            ),
        ],
    )

Everything you need to know is here

There is no hidden magic. The next four pages explain every line above, piece by piece. Let's start with the view tree. 🚀