Templates and examples

tilo-app offers two ways to start an app, for two different needs.

A template is where you start when you know what you are building. It is small, opinionated and yours: tilo-app new NAME --template T renders it once, and from then on it is your code. A template carries only what every app of its shape needs, so there is little to delete.

An example is where you go to learn one idea. It is a complete, runnable program that does one thing well, with tests that state the rules it teaches. You read it in examples/apps/, run it, and when it is close to what you want you start from it with tilo-app new NAME --from-example E, which copies it and renames it to your app.

Both follow the app HIG: every colour and size from the theme, every word from a Fluent catalog, only shared widgets, apps that start empty, and every capability an action.

Templates

Template Starts you with
starter (default) One resource, one bound field, one action: the smallest correct app.
document One collaborative document with a live preview, undo and a destructive clear.
collection Items the user adds, edits, checks off and removes, each with its own actions.
graph Serialized, live-editable screens above controls bound to the resource.

tilo-app new --list-templates prints this list (--json for scripts). The shapes earlier versions offered as templates (data, list, tree, workspace, async, qr) were each teaching one widget rather than giving an app a starting point, so they are examples now; naming one tells you which.

The starter’s generated tests exercise its public actions and live controls, Viewer refusal, persistence, and a two-participant edit. That journey checks that sync updates both replicas and the running view, history retains the peer’s authorship, and local undo/redo preserves the collaborator’s edit. It exchanges production resource documents headlessly; it does not certify network transport or sign-in on two devices.

Examples

Example Teaches Web
counter Resources and actions: validation, undo, confirmation, roles. yes
bound-controls Text, checkbox, number, slider and dropdown bound to fields. yes
virtual-list A sparse, virtualized list with stable keys and row controls. yes
data-table Columns over a sparse table model, cells that invoke actions. yes
tree-browser Tree navigation and an adaptive master-detail shell. yes
background-task Cancellable work off the UI thread, started through an action. yes
shared-checklist What merges when two people edit at once, and what undo takes back. yes
localized Catalogs, arguments, plurals, live language switching, pseudo-locale. yes
graph-screens Serialized screens, a Rust component mounted in one, the router. yes
qr-code A generated visual with alternative text, empty until it has input. yes

Inspect one example or read just its embedded source without a repository checkout or network access:

tilo-app examples shared-checklist
tilo-app examples shared-checklist --file tests/app.rs --json
tilo-app examples shared-checklist --file src/lib.rs

The named command lists that example’s files and scaffold command. With --file, human output is the file itself; JSON carries the selected example, file and content. Files come from the installed CLI’s embedded examples, so the tests and code match the examples that version of new copies. Unknown paths report the available files.

tilo-app examples prints this list (--json for scripts, with each example’s path and whether it is web-capable). The examples that load data or compute in the background do it through ui::background, which runs on a thread where the target has one and on the page’s executor on the web.

The column is what the portability lint finds, not a promise: the lint records the sites of its web rules (threads, the std clock, std files and sockets: W1-W3 in tools/policy/app_portability_rules.toml) apart from its findings, and every_example_is_indexed_and_portable fails when an example’s Web flag disagrees with it. tilo-app build --platform web refuses an app that uses one. CI builds every web-capable example for the web when one of them, or the web build itself, changes: tools/ci/build-web-examples.sh builds the web core once with those examples in its collection, then each example’s app module.

Where they live and how they stay correct

Examples are workspace members under examples/apps/<name>/, package example-<name>, app id so.tilo.example.<name>. Being members means every change to the SDK compiles, lints and tests them: CI’s affected-package selection runs their Clippy and tests, and tilo-app check --lint --all lints them with the apps.

Each example was generated by tilo-app new and then rewritten, and the CLI test every_example_is_what_new_renders_for_it keeps it that way: rendering the example under its own identity must reproduce every file in its directory byte for byte. So its Cargo.toml, tilo-app.toml and src/main.rs are exactly what new writes, and the files that are the example’s own are the ones the CLI embeds and copies. an_app_from_an_example_is_renamed_and_ready starts a standalone app from each example and runs tilo-app doctor on it.

Every example has tests (tests/app.rs, through Replica and TestApp), a native-contract certification test, and a saved headless scenario (tests/headless-actions.json) that tilo-app check runs with the accessibility audit. CI runs those scenarios too, for every example its affected-package selection tests: tools/ci/example-scenarios.sh drives each example’s own binary through tilo-app scenario run --audit, the same stage tilo-app check runs.

Adding an example: create it with tilo-app new example-NAME --id so.tilo.example.NAME --directory examples/apps/NAME (move its workspace member line under # Examples), rewrite it, and add it to crates/dev/tilo-app-cli/src/examples.rs, examples/README.md and the table above. The CLI tests fail until all four agree.

This page is docs/examples.md in the Tilo repository, at 29fbb80121. Changes to it are made there.