S01E05 β 10-04-2026.
zo 0.3.0 β Next Level Mode.
0.1.0 showed the counter as syntax. 0.3.0 makes it move. State turns reactive, closures run as event handlers, and the first step of a built-in style system lands.
reactive state
The interfaces our first release could only declare now run. A mut variable bound in a template is reactive: change it from an event handler and the view follows. Click flips the switch, and the slot bound to it repaints. The same source drives the native runtime (egui) and the web (wry).
fun main() {
mut open: bool = false;
imu view: </> ::= <>
<button @click={fn() => open = !open}>switch</button>
<p>{open}</p>
</>;
#render view;
}
closures
Inline closures fn() => expr now unify their types, so a closureβs parameters and result resolve, whether you bind it to a name or write it straight into an event. A closure captures the variables it names, and a captured mut stays mutable inside, so count += 1 reaches back out and changes the state the view reads.
imu square: Fn(int) -> int = fn(x: int) -> int => x * x;
showln(square(7)); -- 49
booleans
showln prints booleans as true and false now, not 1 and 0.
showln(true); -- true
showln(false); -- false
zo-styler
The first step toward a built-in style system. zo-styler reads a $: { } block, with styles scoped to the component by default. It heads toward one styling story shared across web and native.
$: {
p {
color: blue;
font-weight: 800;
}
}
Alongside the features, the corpus that proves them grew: more test programs under zo-tests and more how-to examples, each a small program that compiles and runs.