Your First App with stzApp: A World That Lives, and Wants
Aïcha builds a tool for a bank in Niamey. Field agents visit clients. She doesn't think "database, screens, deployment." In Softanza she thinks about a small world — what lives in it, what's true of it, how it moves, what it's for, and where it endures.
by Mansour Ayouni · in the repository since 2026-07-09 · tutorial · area Web & app server
A narration. It builds a real application with
stzApp— the Softanza construct that holds that an application is a living world of meaning. A world is made of a domain (things and their truths), a life (what it does and what it wants), and a body (where it endures); and it is met by being seen, engaged, tuned, and reached. Written as ifstzAppalready ships. Watch a world come into being, begin to move — and begin to strive.
The setting
Being — the world's things and their truths
load "stzlib.ring"
oApp = new stzApp("SonibankVisits")
oApp {
Thing(:Account) { Has([ :number, :chapter, :balance ]) IsTrue(:balance) = '@ >= 0' }
Thing(:Client) { Has([ :code, :name, :city ]) Owns(:Account) }
Thing(:Visit) { Of(:Client) Has([ :agent, :date, :subject ]) }
Knows(:Account, :belongsTo, :Client)
}illustration
A domain — a graph of things — declared without ever saying "graph," and told what should hold: a balance below zero is simply not true in this world.
Becoming, part one — how the world reacts
oApp {
When(:agent, :records, :Visit) { Require(:subject) Then( Keep(:Visit) ) }
Whenever(:Client).Unseen(90, :Days) { Propose(:Visit) }
}illustration
A flow: an agent records a visit, the world requires a subject, then keeps it. A reaction: whenever a client goes unseen for ninety days, the world stirs and proposes a visit — nobody scheduled it. This is the push of life: events flow, patterns fire, consequences follow.
Becoming, part two — what the world wants
Here Aïcha adds the part that gives the world its meaning. A world that only reacts is a mechanism. She tells it what it is for:
oApp {
Want(:EveryClientSeenThisQuarter) {
Means = 'every :Client Has(:visit) Since(:quarterStart)' # the wanted state
ReachedBy = :planning # how to get there
}
}illustration
Want declares a goal — not a list of steps, but a wanted state of the world: every
client visited this quarter (stzGraphGoal). ReachedBy names how the world should find its
way there (stzGraphPlan): :planning searches the graph programmatically; had the problem been
harder she'd have climbed the ladder — :optimization (order visits by route and workload),
:learning (predict who's most at risk), or :llm as a last resort. Programmatic first,
intelligence only when needed — and always in service of a declared goal, bounded by the world's
truths. The pull of life: the world now strives, not just twitches.
Body — where the world endures
oApp { LivesIn([ :GraphDB, :Files ]) }illustration
She gives the world a body. The graph database is its living substance — queryable, the structure of its being and becoming. The files are its familiar, editable face. Edit a file → the world updates; the world moves → the files reproject. (With no body declared, the world still lives — in memory — it just wouldn't endure past a run.)
The world lives — and pursues
oApp.Explain()
illustration
WORLD SonibankVisits lives in: GraphDB + Files
BEING Account (…) true when balance>=0 · Client owns Account · Visit of Client
BECOMING · when agent records Visit → require subject → keep
· whenever Client unseen 90 days → propose Visit
· WANTS every Client seen this quarter → reached by planningoApp.Live()
illustration
Explain() makes the whole world visible — being, behavior, and purpose. Live() animates
it: stale clients surface on their own (reaction), and the plan quietly reorders the world toward
its goal, proposing the visits that would make "every client seen this quarter" become true. With
no UI at all, the world already lives and wants.
Seen · Engaged · Tuned · Reached (the emergents)
oApp.Screen(:ClientFile) { ToUnderstand(:Client) Shows([ :identity, :accounts, :visits ]) }
oApp.Refine(:balance).Bounds(0, 1_000_000)
oApp.Reaches([ :mobile, :desktop, :web ])
oApp.Generate(:all)illustration
The screen is an intent (an agent wants to understand a client), rendered per surface. Refinement turns a knob without touching being, life, or body. Reach projects the one world onto phone, desktop, web — where it appears (distinct from its body, where it resides). Each artifact is just the world + the Haro runtime + the stz engine, portable anywhere.
What just happened
Aïcha declared a world's being (things, truths, relations), its life (a flow, a reaction,
and a goal with a plan), and its body (graph + files). Softanza gave her a living,
striving application, composed from stzGraph, Reaxis, stzWorkflow, stzGraphGoal/
stzGraphPlan, stzAppServer. Because it is a living world that wants, everything else — how it
is seen, engaged, tuned, reached — emerged. And because it is just a world, the same construct
could be an agent, a game, or a simulation. Softanza gave the world; what it lives for is hers.
A living world of meaning. Being · life (behavior and purpose) · body. Seen, engaged, tuned, reached. One dependency. Any language. Everywhere.
See also: stzApp — Design(opens in a new tab) — the three constitutive aspects (domain, life, body), life's two arms (behavior, purpose), and the four emergents.
Related reading
- Intelligence in Motion: Graph Planning in Softanza
- stzGraph — Modeling Knowledge Through Structure
- stzGraph: The Art of Connected Thinking
Cite
Mansour Ayouni. "Your First App with stzApp: A World That Lives, and Wants". Softanza narrations, 2026. https://mayouni.github.io/stzsite/en/narrations/stzapp-building-your-first-app-narration.html
Not run: its code touches files, the network, the clock or chance. The article is published as written; its blocks are illustrations. The code of the articles is Haro code. Where an article was written before the language took its present name, the name was changed and nothing else. Genre, area and series read from the file's name, the year from its first commit: derived, until the article carries its own header. The file on GitHub(opens in a new tab)

