All docsBuild a Tilo appPage source

Add one capability once

Declare edits in the existing #[resource] implementation in src/lib.rs. The starter’s clear operation is an example:

#[action]
pub fn clear(&mut self) {
    self.name.clear();
}

Bind the generated descriptor in the view:

let clear = cx.button("starter-clear", Greeting::CLEAR.invoke());

The label is a Fluent key. A text field uses the same door: cx.input(|state| state.name.clone(), Greeting::SET_NAME). Read visual values with cx.text or another bound shared control so peer edits and undo update the view too. Keep render caches out of the model.

That resource action is the public capability for buttons, keyboard input, accessibility, scripts and agents. Resource edits participate in the system’s history, undo and CRDT synchronization; an app does not add its own action bus or sync implementation. Use typed effects for external work rather than pretending a network request or file write is an undoable resource edit.

Give a common action the other words people use for it, so search finds it by them as by its label: #[action(keywords = "mkdir, make directory")] on a verb, #[effect(keywords = "…")] on an effect. Write plain words, one phrase each, never code or the implementation’s names (check_action_keywords.py). Search keeps no list of its own; test the words with ui::search::system::actions_found_by.

Effect ids share the root resource’s action surface. InspectPackage becomes inspect-package; keep names distinct across effect enums and root actions. The effect’s operation names its vocabulary, not an id prefix.

Test the action through the generated TestApp harness. Enumerate the permission-filtered action descriptors and invoke their stable identities; display labels and pointer coordinates do not identify an operation. Confirmed effects and role restrictions use the same host door as the controls.

tilo-app test --json
tilo-app inspect --audit --json

More: Build an app.