Bind slot to fact
Fill a slot from a known property fact, no AI.
Fill a slot from a known property fact, no AI.
Prerequisites
Section titled “Prerequisites”- A section with a slot to rebind — Install scaffolds one.
- Its
fixtures.tsbuilt from a scenario, so the fact resolves in preview — Pick a fixture scenario. - If you are swapping a slot off AI fill, the decision that fills it today —
AI writes slot content adds a
summaryand thefill:that writes it.
Give the slot a source: fact.<container>.<field> and a writeback boolean.
The pair is the whole declaration a fact-bound slot needs: the binding says
where the value comes from, and writeback says whether a user’s edit
propagates back to that fact.
Add fact to the section’s existing kit import — the scaffolded file takes only
defineSchema, text and textBlock, so it is missing until you do.
For a worked example at full size, scaffold the example workspace
(npm create @homepages/workspace@latest <name> -- --example spw-essential —
the -- is required, or npm silently drops the flag) and read a fact-bound slot
there.
// section.ts — the slot, bound to a fact instead of filled by AIsummary: text.long({ label: "Summary", source: fact.property.address, writeback: false,}),Then delete that slot’s fill:
(Sections and declarations). Both halves are
the same declaration, so this is one edit: a slot declares exactly one of source: and
fill:, and a bound slot that keeps its fill: is a compile error. The fact is baked in at fill
time, and there is no decision left for it to disagree with.
The same pattern works for any slot type — pick a fact whose runtime shape
matches, and the builder for the kind you want. For a numeric fact,
number({ source: fact.unit.beds, writeback: true }); for a text one,
text.long({ source: fact.property.address, writeback: false }) or any other text-shaped fact in
the fact vocabulary. A fact that does not exist
is a compile error on the fact.* path itself, before check ever runs.
writeback: true makes the editor offer “Update everywhere” on the slot, and
is legal only on a writable fact — on a read-only one (fact.property.address,
fact.contact.headshot) only writeback: false compiles, so the declaration
states what the catalog would otherwise decide silently. Omitting the boolean
on a fact-bound slot is a compile error.
A binding names one fact. The pools the platform also holds — the property’s
photos, videos, tours, floor plans, documents and their distilled notes — have no
binding, because a pool is a whole candidate set and there is no single value for
a slot to take from it. What a section wants from a pool is a count, a filter or
a pick, which is a computation: read it off f in
compute(), where every name you learned here reads
identically — fact.unit.beds as f.unit.beds, fact.contact.website as
f.contact.website.
Complete diff
Section titled “Complete diff”The one fence under Steps is the whole edit to section.ts’s slots,
plus fact on that file’s existing kit import and the deletion of the slot’s own
fill:. Renderer.tsx and fixtures.ts are untouched.
Verify
Section titled “Verify”Verify with the author loop.
Rules that can fire
Section titled “Rules that can fire”typecheck— the slot carries itssourcebinding and keeps itsfill:, which is the one combination a slot may not declare.
See also
Section titled “See also”- The fact vocabulary — every fact, grouped by the container it resolves against, and the derive-time view that shares its names.
- Binding a slot to a property fact — the
factbinding contract and why a bad name is a compile error. - AI writes slot content — the
fill:this edit removes, and why a bound slot may not also carry one.