What is a vertical?
A vertical is the business: the software a service firm, a workshop, a shop, or an HR team actually runs on. It owns everything with a user's fingerprints on it — vocabulary, pricing, roles, screens, workflows — and it composes the engines and the kernel underneath.
Where an engine is a reusable contract, a vertical is a composition plus a product. It is where the three layers meet: the kernel's guarantees, the engines' invariants, and the business's own logic, wired together in one place you can read.
What a vertical owns (and what it borrows)
- Borrows invariants from engines by calling their in-scope functions inside its own operations — same transaction, so an engine's state machine and the vertical's own tables commit together or not at all.
- Does its own permission check as the first line of every operation; engines never decide who may call a vertical.
- Adds side tables keyed by an engine's ids when it needs extra data on an engine entity — never a column upstream (a module's tables are private).
- Owns the screens — the app is the vertical's, composed over one API; the kernel and engines ship headless.
The design test cuts both ways: if a vertical ever needs to fork an engine, the engine drew its line wrong; if a vertical hand-rolls tenancy, audit, or permissions, it's reaching below its layer.
A curated set, not a pile
These demos are chosen, not accumulated. Each one exists to prove a different way of using the platform — a distinct point in the design space — so the set as a whole shows the range, and no two demos teach the same lesson.
| Vertical | Package | The shape it uniquely shows | Engines composed |
|---|---|---|---|
| Meridian (HR) | demos/meridian | The shape-breaker — its core domain has no engine, so leave, time and expenses are vertical code on the kernel alone (protocol is composed for onboarding only); multi-country scopes diverging from one codebase; one role-adaptive app (employee + manager in the same surface) | protocol only |
| Callout (field service) | demos/callout | The canonical composition — two engines cooperating through events with zero imports between them (the star-topology showpiece), plus the pricing moment where vertical logic meets an engine transition | workorder · invoicing · protocol |
| Handlebar (bike workshop) | demos/handlebar | Engine reuse — the same engines under new vocabulary; the second shape that forced the protocol engine to be extracted from Callout | workorder · invoicing · protocol |
| Kallkälla (coffee shop) | demos/shop | Two audiences, one source of truth — a customer storefront and a staff back-office as separate apps over one API; invoicing reused far outside field service | invoicing (+ its own commerce module) |
| Manyfold (headless CMS) | demos/manyfold | Content lifecycle on the kernel alone — a draft → review → publish state machine that can't skip, append-only revisions, freeze-on-publish with a content hash, and references resolved at delivery, all composing no engine at all; multi-scope, "site = scope" — one tenant runs many sites, each its own scope, the same login a different role in each | none — kernel only |
| Todo (shared lists) | demos/todo | User-initiated sharing on a record app — sharing one list with one person is ctx.grant/ctx.revoke on that entity, revocable and transactional with the operation, never an org per row; a 403 wall told apart from an empty list; and the walkthrough shows every file of it | none — kernel only |
| ticket0 (support desk) | demos/ticket0 | A public, unauthenticated surface — an embeddable chat widget confined by a session token and an origin allowlist rather than a login; an AI assistant as a member of staff with a principal and a granted role, supervised or autonomous per desk; honest cost through an append-only meter only the desk admin may read — the desk on Ask the docs is this demo | metering |
| Tock (measured file loads) | demos/tock | A runtime schema the data may disagree with — Manyfold also models content types as data but refuses anything that does not match; Tock records the mismatch instead, so a field that arrived undeclared and a field declared that never arrived are both findings. Plus corrections that supersede without destroying: a re-run writes a new run, the old one keeps its numbers and the content-hashed rules that produced them, and which run is current is derived rather than stamped. Runs locally end to end; not deployed | none — kernel only |
The through-line: structurally repetitive, operationally rich — the foundation is the same, the vocabulary and shape are not. That is exactly the segment Substrat is for.