Build a reactive app
A Lux app is one file: structure, style, logic, and state in a single syntax. No HTML, no CSS files, no component framework to install.
1. Create a project
lux new counter
cd counter
2. Write the app
app Counter:
count = signal(0)
view:
column gap=16 padding=24:
text "Count: {count}" size=24
row gap=8:
button "+" on:click -> count.update(n -> n + 1)
button "-" on:click -> count.update(n -> n - 1)
text "{energy.total()} J" color=gray size=12
The pieces:
signal(0)creates a reactive value. Reading it inside the view registers a dependency; writing it invalidates exactly the nodes that read it.view:is a declarative tree — elements by name, styled by properties, composed by indentation. It compiles to a virtual DOM with O(n) keyed diffing.on:click -> …wires an event to an update. NoaddEventListener, nothis.{energy.total()}— the app can read its own meter.
3. Develop with hot reload
lux dev # JIT dev server on port 3000
lux dev compiles through Cranelift into executable memory and hot-swaps on
file change.
4. Ship it
lux build --wasm --release
A complete application — reactive runtime, VDOM, CSS engine, and the standard library modules it uses — compiles to a WebAssembly binary around 398 KB. The browser instantiates it directly: no parsing, no JIT warmup, no bundler.
Derived state and effects follow the same model when you need them:
total = memo(items.map(i -> i.price) |> sum())
effect:
print("total changed: {total}")
Try the counter in the playground, or read the reactive-state section of the spec.