Curriculum / Application Developer & Ontology Engineering
Assemble the Workshop command-center app: layouts, pages, widgets, variables
Introduction
Scenario: The supply-chain operations team needs a single command-center app where a duty operator can scan today's disruptions, drill into one, and triage it — so you assemble a Workshop 'Command Center' module over the Ontology and functions you built in earlier units.
Unit 6 turns the Ontology, the published functions, and the function-backed Action from the previous units into an application an operator actually opens. Workshop is Foundry's no-/low-code application builder: a Workshop 'module' is the app, and inside it you arrange the UI with layouts (a persistent header plus one or more pages, where each page is its own blank canvas and only the header carries across pages), place widgets (the core building blocks — object tables, lists, buttons, charts) into sections, and move data through the app with variables. Your deliverable is a Command Center module with a risk-list page that shows the disruptions needing attention, a detail page for the selected one, function-backed metric variables that surface a risk score, and the triageDisruption Action wired to a Button Group so the operator can act without leaving the screen.
The connective tissue of a Workshop module is its variables. A variable's value comes from a definition type — Static, Object set, Object property, Object set aggregation, Variable transformation, or Function — and most variables can be function-backed, meaning the variable calls one of the published query functions from Units 3 and 4 and exposes its structured result to the UI. Widgets consume variables as inputs and emit variables as outputs (a selected object, a filter), and the Variables panel plus the variable lineage graph let you trace how a selection on the risk-list page flows into the detail page and into a function call. This is how the app stays coherent: the operator clicks a disruption, that selection becomes an output variable, and a function-backed variable recomputes the risk summary for exactly that object.
Two honesty constraints shape this unit. First, interfaces are not supported in Workshop, so even though Shipment and DisruptionEvent implement the RiskEntity interface from Unit 2, every widget here binds to a concrete implementing object type, never to the interface itself. Second, almost nothing inside a Workshop module is exposed by a Foundry read API: layout, widget bindings, variable wiring, and Button Group configuration are all builder-side and cannot be introspected. The one machine-checkable fact is that the module resource exists at its expected path; everything else in this unit is self-attested in the build, with the Action's real effect proven downstream by the object-state checks you already exercised in Unit 5. Treat the existence check as a floor, not a guarantee that the app is wired correctly.
Capability focus: Workshop layouts/pages/widgets/variables; object-set widgets; function-backed variables; Button Group actions (interfaces are not supported in Workshop). · Artifact: A Workshop 'Command Center' module with risk-list + detail pages, function-backed variables, and the triageDisruption Button Group.
Key concepts
- Workshop module: A Workshop module is the application itself — a Foundry resource that builders configure in the Workshop editor. It is the unit that exists at a path in the filesystem; its internal configuration (pages, widgets, variables) is editor-side and not exposed by the Ontology read APIs.
- Layouts (header, pages, sections): Layouts organize a module's UI. A header persists across the whole app; pages enable a multi-screen application where each page is a blank canvas and only the header carries across pages; sections arrange widgets within a page using layout types such as toolbar, loop, tabs, flow, rows, and columns.
- Widgets: Widgets are the core building blocks of a module (object tables/lists, charts, buttons, and more). Builders place widgets into the layout and configure each one with input/output variables, display options, and Actions.
- Variables and definition types: Variables configure how data moves through a module. Each has a definition type — Static, Function, Object set aggregation, Object property, Object set definition, or Variable transformation — and a value type such as Object set, Object set filter, String, Numeric, Boolean, Date, Timestamp, Struct, Array, or Time series set. A Variables panel and a variable lineage graph show how values flow.
- Function-backed variables: Most Workshop variables can be function-backed, meaning the variable's value is computed by a published function. This is how the Command Center reuses the Unit 3/4 query functions (shipmentRiskRollup, reorderSuggestion) to surface a structured risk summary in the UI rather than recomputing logic in the app.
- Function-backed Actions via Button Group: A function-backed Action type calls an Ontology-edit function to modify objects. In Workshop, an Action is surfaced through a widget such as a Button Group, whose on-click runs the Action (here, triageDisruption) with parameter defaults; the edit function is NOT a query and never appears in Execute Query, so its effect is confirmed by the resulting object state, not by reading the widget.
- Interfaces are not supported in Workshop: Ontology interfaces are supported in Ontology Manager, TypeScript v2 Functions, and the Ontology SDK, but NOT in Workshop. Widgets must bind to concrete implementing object types (Shipment, DisruptionEvent), even though those types implement the RiskEntity interface defined in Unit 2.
- Existence vs. configuration (read-API limits): The Foundry filesystem read API can confirm a resource of a given type exists at a path, but Workshop layout, widget bindings, variable wiring, and Button Group configuration are not read-API-exposed. Existence is the only machine-checkable signal here; the rest is self-attested or proven by downstream object-state checks.
Companion video
Deep Dive Building Your First Application (update) · watch building the operational app in Workshop · open on YouTube
Hands-on activity
each step validates · the unit completes when all steps pass- 1
Design the multi-page layout
Before building, sketch the module's layout because in Workshop the layout is the app's skeleton: a persistent header plus pages, where each page is its own blank canvas and only the header carries across pages, and sections (toolbar, rows, columns, tabs) arrange widgets within a page. Plan a risk-list page (the operator's landing screen, showing disruptions that need attention) and a detail page (the selected disruption with its risk context and the triage control), and decide how a selection on the list page will flow to the detail page through an output variable. This step is self-attested: layout configuration lives inside the Workshop editor and is not exposed by any Foundry read API, so the sketch is the artifact — capture the header, the two pages, and the sections you intend to place widgets into.
not startedself-attestedSelf-attested: header + risk-list + detail pages are sketched before building (layout config is not read-API-exposed).
- 2
Confirm the Workshop module exists
Create the Workshop module so it exists as a resource at the expected app path. This is the one machine-checkable fact in the unit: the check confirms that a resource of type WORKSHOP_MODULE exists at the Command Center path under your application suite — existence only, not correctness. The check cannot see the module's pages, widgets, variables, or any binding inside it, because Workshop configuration is editor-side and not exposed by the Ontology or filesystem read APIs beyond the resource's type and location. Produce the artifact by creating the module at the right path and naming it so it is unambiguously the Command Center app; treat a passing check as proof the app shell exists, not that it is wired correctly.
not startedinstance checkConfirms a Workshop module exists at the expected app path (existence-only).
- 3
Wire function-backed variables and object-set widgets
Wire the data flow: add object-set widgets (an object table or list) on the risk-list page bound to a filtered set of disruptions and shipments, and configure a function-backed variable that calls a published query function from Units 3 and 4 — shipmentRiskRollup or reorderSuggestion — to surface a structured risk summary for the selected object. Move the selection from the list page to the detail page through an output variable, and feed that selection into the function-backed variable so the risk score recomputes for exactly the disruption the operator opened. Bind widgets to the concrete implementing object types (Shipment, DisruptionEvent), NOT to the RiskEntity interface: interfaces are not supported in Workshop, even though those object types implement RiskEntity. This step is self-attested — variable definitions, widget bindings, and the function-backed variable's wiring are all editor-side and not introspectable through a read API; the artifact is the configured variables and widgets, verifiable only by opening the module.
not startedself-attestedSelf-attested: object-set widgets and a function-backed variable are configured (bindings are not read-API-exposed).
- 4
Expose the triage action via a Button Group
Expose the triage control by adding a Button Group widget on the detail page and wiring its on-click to the triageDisruption function-backed Action from Unit 5, supplying parameter defaults (for example, the selected DisruptionEvent and the assigning owner) so the operator can triage in one click. Remember the underlying edit function is NOT a query — it never appears in List Query Types or Execute Query — so neither the Button Group nor the Action is confirmable by reading the widget. This step is self-attested for the wiring; the only machine-verifiable proof is downstream: applying the Action produces object state where a DisruptionEvent has an owner set and a triaged status (assigned or resolved), which is the same object-state signal the Unit 5 and capstone checks bind to. The artifact is the Button Group wired to triageDisruption with sensible defaults, demonstrated by triaging a disruption and seeing its state change.
not startedself-attestedSelf-attested: triageDisruption is wired to a Button Group on-click (wiring is not read-API-exposed).

