A collection slot — a repeating, per-item list
Add a repeating list whose items the editor selects and edits one at a time.
Add a repeating list — a unit table, agent cards, a feature list, a gallery — whose items the editor selects and edits one at a time.
The delta
Section titled “The delta”Starting from the starter’s hero section, add an object_list slot: a row of
nested item slots that repeats. Bind the whole array to a list fact with
direct("units") (a unit table) — the array is baked from the property, so it
needs no fill-spec.ts decision, exactly like a fact-bound scalar
(bind-property-fact.md). Each item field binds to a
per-row fact with its own direct(...).
// schema.ts — a repeating list of units, after the `blurb` slotunits: { type: "object_list", source: direct("units"), editable_by_user: true, required: true, source_title_field: "unit_label", display_name: "Units", item: { unit_label: { type: "text", size: "short", editable_by_user: true, display_name: "Unit", source: direct("unit_label") }, beds: { type: "number", editable_by_user: true, display_name: "Beds", source: direct("beds") }, baths: { type: "number", editable_by_user: true, display_name: "Baths", source: direct("baths") }, sqft: { type: "number", editable_by_user: true, display_name: "Sqft", source: direct("sqft") }, price: { type: "text", size: "short", format: "currency", editable_by_user: true, display_name: "Price", source: direct("price") }, },},// Renderer.tsx — <Slot> marks the whole array, <SlotItem> marks each rowimport { Image, Section, Slot, SlotItem } from "@homepages/template-kit";
// SectionProps types an object_list as Record<string, unknown>[], so narrow// each row to your item shape at the map site.type UnitRow = { unit_label: string; beds: number; baths: number; sqft: number; price: string };
<Slot id="units" as="ul" className="mt-4 flex w-full flex-col divide-y"> {(slots.units as UnitRow[]).map((unit, i) => ( <SlotItem key={unit.unit_label} index={i} as="li" className="flex justify-between py-2"> <span>{unit.unit_label}</span> <span>{unit.beds} bd · {unit.baths} ba · {unit.sqft} sqft · {unit.price}</span> </SlotItem> ))}</Slot>// fixtures.ts — supply the array from a scenario's factsimport { scenarios } from "@homepages/template-kit/fixtures";// ...in base.slots:units: scenarios.luxuryMultiUnit.facts.units,Two contracts to know before you widen this:
direct()binds only a registry collection —unitsorcontacts(the List sources). For any other repeating data, drop thesourceand give the slot aproduced_bydecision instead (see the fill-spec decision types).- An
itemneeds more than one field, or a non-scalar one — a lone scalar field is rejected; use alistslot for a flat list of scalars.
object_list is one of five collection types. A gallery of framed photos is an
image_collection, several hosted videos are a video_collection, a flat scalar list is
a list, neighborhood points are a poi_list — same <SlotItem> render pattern,
different value shape. See
the slot types for which to pick.
Commands
Section titled “Commands”None — this is a pure content edit. No CLI command beyond the author loop below.
Verify
Section titled “Verify”Verify with the author loop.
See also
Section titled “See also”- Contract primitives —
the
SlotItem/SlotGroupcontract: both markers a collection needs, and whyindexmust be the row’s array position. - The closed vocabulary — every collection slot type
(
object_list/image_collection/video_collection/poi_list/list) and thedirect()List sources. - The schema system — the
produced_bydecision types (structured-list,list-extract,image-collection,video-collection) for a collection AI fills instead of binding to a fact. - Bind a slot to a property fact — the
direct()pattern this extends from a scalar to a whole array.