Skip to content
HomePagesHomePages template kit

AI writes slot content

Have AI write a slot's content.

Have AI write a slot’s content.

  • A section to add the slot to — Install scaffolds one.

A section declares how AI fills a slot on the slot itself, in section.ts (Sections and declarations). The slot and the decision that fills it are one declaration, so they are one edit:

// section.ts — in `defineSchema`'s `slots`
summary: text.long({ label: "Summary", cap: 200 }),

…giving it a fill:, built with the builder for the decision you want — textBlock, for a slot the model writes prose into:

// section.ts — the same slot, now carrying the decision that fills it
summary: text.long({
label: "Summary",
cap: 200,
fill: textBlock({
structure: "paragraph",
perspective: "third",
voice:
"Warm, concrete paragraph a buyer would want to read. Never a specific checkable claim the facts do not support.",
// The slot's `cap` is inherited, not restated. Name the character budget in
// the brief too — the cap alone is a generation target, and an over-cap
// answer is retried once and then trimmed.
content:
"Summarize the property's standout feature in 1–2 sentences, under 200 characters total.",
}),
}),

The slot is the whole binding. Its key mints the decision’s id and its produces list — so neither is written by hand, and neither can drift out of agreement with the slot it fills.

Every slot answers where its value comes from, exactly once. A slot bound with source: — to a fact or to a compute() — is baked from that binding, so also giving it a fill: is a compile error; so is a fill: on a kind no decision can produce too. (The one slot that is both bound and filled is a record list whose row fields are authored: its source: originates the rows, and each authored field carries its own fill:.) Those are the two ways a section’s slots and its fill could disagree, and colocating the decision closes both by construction.

textBlock’s options are the brief itself — the character budget is not among them, because the slot already declares it. structure is single_sentence, paragraph or bullet_list, a closed union (TextStructure), so a fourth spelling is a compile error rather than a check finding; perspective is required and names the grammatical person the copy is written in; voice sets the tone every answer is written in, and content is the optional extra instruction for this one slot. The voice above follows the house pattern — register, then qualities, then the grounding clause that keeps the model from inventing a checkable detail (Writing a voice brief). A slot of a different kind takes a different builder — imageAssign for an image, videoAssign for a video, tourAssign for a tour, contactAssign for an image or text whose value is one attached contact’s (a developer’s logo, a builder’s name — the model picks the card, the builder’s field says what of it the slot bakes), and the one listFill for EVERY list, whatever its items hold: what the fill does (generate short strings, choose from the element’s select vocabulary, pick from the property’s media, curate nearby places) follows from the item you declared, never from a builder you chose. Each builder takes only its own kind’s options, so one pointed at the wrong slot is a compile error rather than something check finds later. See the fill decision types for the full set and what each produces, the fill declaration for the serialized contract underneath them, and Video slots for what the video pair deliberately does not take.

One addition to section.ts. Nothing else in the section folder moves, so check stays red on missing-slot-marker until the slot is rendered — Fix a failing check walks that finding from this exact state.

// section.ts — in `defineSchema`'s `slots`
summary: text.long({
label: "Summary",
cap: 200,
fill: textBlock({
structure: "paragraph",
perspective: "third",
voice:
"Warm, concrete paragraph a buyer would want to read. Never a specific checkable claim the facts do not support.",
content:
"Summarize the property's standout feature in 1–2 sentences, under 200 characters total.",
}),
}),

Verify with the author loop.

  • missing-slot-marker — the slot is declared but not yet rendered, so no fixture carries its marker.
  • schema-invalid — the decision’s config is malformed for its type in a way the builder’s own types cannot state: a cap of 0, say, which is a plain number at the builder and a positive integer at the wire.