The App
An App compiles from a Product's Personas, the Role each holds and that Role's Permissions into Dashboards, Flows and slots, with no screen built by hand.
An App is where people work with a Product after they sign in. StartupBuilder compiles it from records the Product already holds: its Personas, the Role each holds, and that Role's Permissions.
What compiles
A Persona names who signs in and the job they come to do. It holds one Role, and the Role holds the Permissions: which Verbs it may call on which Nouns, within which Limits. The App reads that one chain and emits a default Dashboard set for each Persona.
| Default | Compiled from |
|---|---|
| A list and a record Dashboard per Noun | The Nouns the Role 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, from ask and answer |
| Approval cards | The Approvals the Role 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 |
A Verb the Role may not call never renders, so no button is hidden with CSS. Grant the Role one more Verb, and its button appears on the next request. Every Dashboard also renders as Markdown for an Agent and as JSON for a native client, from the same frame (UI).
One App, many Personas
A marketplace has at least three Personas, and each sees a different App on the same records. stitchly.co matches people who need clothes altered with tailors nearby:
| Persona | Holds Role | Opens on | Calls |
|---|---|---|---|
| Customer | customer | Their Orders | Order.place, Action.answer |
| Tailor | tailor | Open Orders near them | Order.deliver, Action.ask |
| Admin | admin | Disputes and Approvals | Order.refund, Approval.approve |
The record behind it is short. The App names its Personas and fills two slots; every other part compiles.
{
"$type": "App",
"kind": "app",
"path": "/app",
"personas": ["customer", "tailor", "admin"],
"slots": { "record.aside": "FitNotes", "list.empty": "FirstOrderPrompt" }
}The App runs on the Startup's own Domain, under its Brand, as part of its Publication. 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. Each step is a Dashboard that ends in the Verb that opens the next. Time to value is measured from the first step to that Event, per Persona and per Offer.
A new Customer on stitchly.co describes a garment, picks a tailor and pays for a first Order. The Flow ends at Customer.activated. Where Customers stall, the step that holds them shows in the Flow's numbers.
Slots: replace a part, keep the rest
Every compiled Dashboard 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 compiling, 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 the compiled form. An Agent reads the slot's Markdown rendering like any other part.