A ui surface is the overlay's access side: a concrete interface deliverable through which a persona reaches a capability. A screen a customer clicks, the REST API a client calls, the event stream a subscription reacts to — each is a ui surface that exposes capabilities and is implemented by the built thing.
Chowk's checkout screen exposes the whole order lifecycle:
ui CheckoutScreen {
title "Checkout"
kind screen
system OrderingSystem
exposes [OrderCheckout, OrderPayment, OrderTracking]
doc "The single screen a customer completes checkout on: open the order, pay, and see it confirmed."
labels { surface: "web" flow: "checkout" }
}system and exposes — and the rule that ties them
A surface names the system that owns it and the capabilities it exposes. There is one rule to respect: a surface may only expose capabilities its owning system actually provides — exposes ⊆ system.provides. A checkout screen can't expose "reserve stock" if the ordering system doesn't provide it; the compiler enforces the subset. This keeps a surface honest: it presents only what its app can actually do.
kind — screen, endpoint, event
A surface's kind says what sort of interface it is. The common three:
kind | The interface | Realized by |
|---|---|---|
screen | A hand-built UI screen | your SPA (no framework realization) |
endpoint | A REST API surface | routes (implements) |
event | An event-reaction surface | subscriptions (implements) |
An endpoint surface is the abstract API that concrete routes realize. Chowk declares one alongside the screen:
ui OrderingApi {
title "Ordering REST API"
kind endpoint
system OrderingSystem
exposes [OrderCheckout, OrderPayment, OrderTracking]
doc "The HTTP surface of the order lifecycle — place, add lines, pay, and read orders. Each ordering route implements this surface."
labels { surface: "rest" flow: "lifecycle" }
}implements — the built thing realizes the surface
The access chain runs:
capability ◀─exposes─ ui surface ◀─implements─ route | subscriptionA route declares implements <UiSurface> by bare name, closing the loop from a built HTTP endpoint back to the capabilities it serves:
post "/orders" : PlaceOrder systems [OrderingSystem] … implements OrderingApi
post "/orders/{id}/pay" : MarkOrderPaid systems [OrderingSystem] … implements OrderingApi
get "/orders/{id}" : GetOrder errors[404] systems [OrderingSystem] … implements OrderingApiThe kind must match the realizer: a route may only implement an endpoint surface, a subscription only an event surface. Implementing the wrong kind — a route pointing at a screen — is a validation error, because it would claim an access path that doesn't exist.
Surfaces can be forward-looking too
Just like a capability, a surface can be presented by a business_process step before it is declared. When a step says ui ReturnScreen and no ui ReturnScreen exists yet, that is not an error — it records a UI deliverable on the backlog (the framework never builds a screen; it is hand-authored downstream), and it reconciles once the surface is declared. This is the access-side twin of the forward-looking capability, and it's covered with the rest of reconciliation in the Business Process & Journey Modeling manual.
The full picture
Put the four supply-side constructs together and the overlay is complete:
flowchart LR R[route: POST /orders] -->|implements| API[ui: OrderingApi<br/>kind endpoint] API -->|exposes| CAP((capability:<br/>OrderCheckout)) SYS[system: OrderingSystem] -->|provides| CAP SYS -->|depends_on| DB[system: PrimaryDatabase<br/>kind database] FEAT[feature: Priority checkout] -.->|requires_capability| CAP
A capability is built and provided by a system (which depends on infrastructure), packaged by a feature (and gated, when paid, by requires_capability), exposed by a UI surface, and implemented by a route. On top of all this sits the demand side — the actors and flows that require these capabilities — which the Business Process & Journey Modeling manual covers next.