The App
How an App derives its screens from a Product's Nouns, Verbs and Personas, what derives today, and how Access Levels and slots shape it.
An App is the Interface where people work with a Product's Nouns and Verbs through screens, backed by its API. Its screens derive from the same definition as every other Interface, so no screen holds a second copy of it.
What derives today
The screens for the team derive from the definition alone. Each Noun gets one list, one record page, a create form and an edit form, and each Verb gets a button. API only or with an App says when a Startup needs them.
| Part | Derived from | Rule |
|---|---|---|
| A list, a record page and two forms | each Noun | screens |
| Up to 7 list columns | the short properties, in declared order, references last | list-columns |
| One control per field | the property's declared type | control-text, control-date, control-number |
| The name a record goes by | the first of name, title, label, email and slug, else the first one-line property | representation |
| A picker over other records | a property typed with another Noun | reference-forward |
| A button | each Verb beyond create, get, list, update and delete | verb-action |
| The reason a call failed | the Verb's refusal | refusal-message |
For leaseclock.com's Lease, that is seven columns from residentName to status, date pickers for startsOn and endsOn, and Renew and Terminate buttons. Every button runs its Verb, and the Verb's rules decide. When Lease.renew is refused, the record page stays as it was and shows why.
What each Persona gets
A Persona names a type of person who signs in and the job they come to do. The screens for the team serve one Persona, the Startup's own people.
PlanAn App per Persona
In the design, each Persona holds one Access Level in a Customer's Tenant. Its Permissions say which Verbs it may call on which Nouns, within which Limits. The App reads that one chain and derives a default set of screens per Persona.
| Default | Derived from |
|---|---|
| A list and a record page per Noun | the Nouns the Access Level may read, with their properties and relationships |
| A form per Verb | the Verb's inputs, with its Mode, Price and any Approval beside the button |
| An ask and answer thread | every open Question addressed to the person |
| Approval cards | the Approvals the Access Level may answer, through Approval.approve and Approval.refuse |
| A usage panel | the Entitlements and Meters of the Customer's Subscription |
| An ask control | Problem.suggest, which records the request as Evidence with the asker attached |
No screen is drawn by hand. A Verb the Access Level lacks never renders, so no button hides behind CSS. Grant the Access Level one more Verb, and its button appears on the next request.
An App holds no rule the API lacks. Every screen also renders as Markdown for an Agent and as JSON for a native client, from the same frame (UI).
One App, many Personas
Three people at one property management company want different things from the same Lease records.
PlanThree Personas on leaseclock.com
In the design, each Persona opens on its own screen and sees only the Verbs its Access Level grants.
| Persona | Holds | Opens on | Calls |
|---|---|---|---|
| Property manager | admin | Leases that end in the next 60 days | Lease.renew, Lease.terminate |
| Leasing agent | member | the Leases of the Properties they show | Lease.create, Lease.renew |
| Owner | viewer | each Property and its Leases | none: reads only |
The record behind it is short. The App names its Personas and fills two slots, and every other part derives.
{
"$type": "App",
"path": "/app",
"personas": ["property-manager", "leasing-agent", "owner"],
"slots": { "record.aside": "RenewalTimeline", "list.empty": "FirstLeasePrompt" }
}The App runs on the Startup's own Domain, under its Brand. A Customer never sees the platform's name.
Flows: first run to value
A Flow is the ordered path one Persona takes from first sign-in to an Offer's activation Event. Its steps are Dashboards, each ending in the Verb that opens the next.
PlanFlows in the App
In the design, time to value runs from the first step to that Event, per Persona and per Offer. A new property manager on leaseclock.com adds a Property, adds its first Lease, and sees the renewal date. The Flow ends at the first Lease.created.
Where Customers stall, the step that holds them shows in the Flow's numbers.
Slots: replace a part, keep the rest
A slot is a named place on a derived screen where a Component replaces the default part.
PlanSlots
In the design, every derived screen names its slots: list.toolbar, list.empty, record.header, record.aside, record.actions, record.tab, form.after and dashboard.section. A slot takes any Component whose props bind to the record in view.
Everything outside the slot keeps deriving, so a fix to the default reaches the App on the next request. A slot never widens what the reader may do. A Component in record.actions calls Verbs through the same Permissions as a derived form.
Building an App API first
Add a Lease Noun to leaseclock.com, call it from the CLI, SDK and MCP, watch a rule refuse a Verb, then see what the App shows for Lease.
Plans inside your App
How an Offer locks a feature, caps a count and prices each seat inside an App, and what each screen shows when a Customer's Offer moves.