Spec format
A spec is a folder of markdown. Each file mixes prose (for humans, and for the agent that
composes the screens) with exactly one spec: YAML block that holds the machine read
facts.
spec/
project.md identity, nav shell, global rules, ordered flow list
flows/<name>.md one flow per file: prose plus a single spec: blockThis page is written for two readers: you, and your coding agent. It is the contract the agent follows when it authors a spec.
project.md
The root file. Prose for the product's intent and its global rules, then one spec: block:
spec:
nav:
- { flow: notes, label: Notes, icon: home }
- { flow: collections, label: Collections, icon: folder }
- { flow: settings, label: Settings, icon: sliders }
flows: [welcome, notes, collections, settings]flowsis the ordered list of flows in the product. A name here with no matching file underflows/is a planned flow.navis the top level navigation shell: the sections a user can always reach. Everyflowinnavmust be a known flow.
flows/<name>.md
One file per flow. Prose describing the happy path and the flow's own rules, then one
spec: block:
spec:
screens:
- { id: home, states: [default, empty] }
- { id: note, states: [default] }
- { id: new, states: [default], overlay: true }
- { id: record, states: [default], overlay: true }
edges:
- { from: home, to: note, on: open }
- { from: home, to: new, on: create }
- { from: home, to: collections, on: nav }
- { from: note, to: home, on: back }
- { from: note, to: record, on: dictate }
- { from: new, to: home, on: done }
- { from: record, to: home, on: save }Fields
| Field | Meaning |
|---|---|
screens[].id |
The screen's identifier, unique within the flow. |
screens[].states |
The states this screen has, for example default, empty, loading. |
screens[].overlay |
true if the screen is a modal or sheet over the current one; it then needs an outgoing edge to dismiss it. |
edges[] |
A transition { from, to, on }. to is a screen in this flow or the name of another flow. |
The first screen in screens is the flow's entry.
The checks
foundry check runs a fixed set of coherence checks. An error fails the build; a
warning is surfaced but does not fail it. The rule library grows over time; this is
what it guarantees today.
| Check | Level | What it enforces |
|---|---|---|
edge-endpoint-exists |
error | Every edge's from is a screen in the flow, and every to is a screen here or a known flow. |
overlay-has-exit |
error | A screen marked overlay: true has an outgoing edge that dismisses it. |
nav-target-exists |
error | Every nav section in project.md points to a known flow. |
no-orphan-screen |
warning | Every screen is reachable from the flow's entry by following edges. |
index-lists-flow-files |
warning | Every flow file is listed in project.md's flows. |
Reading a finding
Each finding names the check, the flow, and the screen, so a failure points straight at the line to fix. For example:
overlay-has-exit: overlay "record" has no outgoing edge to dismiss it
means a screen marked overlay: true has no edge leaving it, so there is no way back. Add an
outgoing edge, and the check passes.
Complete examples
Four reference projects ship with Foundry, spec and screens. Each one opens as a live canvas you can pan around and click through, with its spec beside the screens it produced.
- murmur, a mobile notes app and the canonical example: a full journey (welcome, notes, collections, settings) with overlays, an empty state, and settings detail pages. The guides follow it.
- ledger, a freelancer invoicing app.
- aurora and lueur, larger multi flow specs.
They also live under examples/ in the repository, if you would rather read the raw files.