Skip to content
HomePagesHomePages template kit

The pipeline

Where a template sits between a property's facts and a published page, and which of those stages your code actually runs in.

A template does not stand on its own. It sits in the middle of a longer path that starts with a property nobody has described yet and ends with a page a buyer is reading. Almost everything the framework asks of you is a consequence of where along that path your code sits.

The path has four stages, and they always run in this order.

Intake. An agent hands the platform a property’s raw material — photographs, listing documents, floor plans, a voice memo, a few typed basics — and the platform normalizes all of it into one structured account of that property: its facts. Nothing you author is involved.

Fill. The platform reads your section’s declarations — what content the section has, and where each piece of it should come from — and turns the property’s facts into a value for every piece. This is the stage that writes the draft page. See AI fill.

Edit. A user opens that draft and revises it: rewrites a headline, swaps a photo, hides a section they do not want. Their edits replace what fill produced, and the page they are looking at while they work is your section, re-rendered.

Publish. The finished content is rendered one last time to static markup, and that markup is what gets served. There is no server application running behind a published page.

Your template is the shape all of that pours into: a set of sections you author, a composition that lays them out across the site’s pages, and a theme they render against — all of it developed inside a workspace, the folder you work in, holding one or more templates and pinned to one kit version. You write a template once, against no property in particular.

Stage What it consumes Does your code run?
Intake the property’s raw uploads No
Fill your declarations, and the property’s facts No — your declarations are read; your component is not
Edit a user’s revisions to the draft Yes — the renderer, repeatedly while a user edits
Publish the finished content Yes — the renderer, once

Read the right-hand column twice. The two stages that decide what a page says never run your code at all, and the two that run your code are only laying out content that has already been decided.

One template is rendered many times, once per deliverable — a property’s own copy of that template, holding that property’s content and edits. So a section declares what it needs and how those needs should be filled, and the platform supplies the values per deliverable — which is what makes a template you author once the same code behind every home it ever renders.

That is the whole reason the declarations are separate, readable files rather than logic inside your component. At the moment you author a section, the property it will render does not exist. You cannot fetch its content, because there is nothing to fetch. You cannot branch on it, because there is nothing to branch on. What you can do is describe the content the section has and where each piece should come from — and a description is something the platform can read and act on long before your component would ever be called.

This inverts the habit most React work builds. In an ordinary application the component decides what it needs and goes and gets it. Here the deciding happens in a stage that has already finished by the time your component runs, and the component’s entire job is to lay out values that arrive on its props.

The cost is worth naming plainly: content a section cannot describe declaratively is content the platform cannot fill for it. The payoff is that a single authoring pass covers every property the template will ever meet — including the one with four photographs instead of forty, no floor plan, and no agent headshot. Those are not edge cases to handle later; they are the ordinary case, which is why the kit ships shared scenarios to preview against rather than leaving each author to invent sample content.

Your code does not run during fill. Fill reads your declarations; it never calls your component. A slot’s value is settled by what the schema says that slot is and what the fill declaration says it should be sourced from — never by anything the renderer does with the value afterwards. A renderer cannot influence its own inputs, and it is not asked to.

Your code runs at render, and render happens in two places: on the platform’s server, once, when a deliverable is published; and behind the editor, again and again while a user edits.

That is the entire runtime story, and nearly every constraint the kit puts on a renderer follows from it rather than from house style:

  • A renderer must be a pure function of its props. The two renders have to agree. One of them is the page a buyer will read and the other is the preview the user edited against, so a disagreement between them is a bug the user only finds after publishing. Same props in, same markup out — see Server and client.
  • Nothing may be read that differs between the two. A clock or a random number answers differently every time it is asked, and the two renders happen at different moments. A browser global is simpler still: neither render is in a browser, so there is nothing there to read — not at publish, and not for the editor either. The rule that enforces this is no-nondeterminism.
  • The rendered markup has to say what it is. The editor never sees your component — only the DOM it produced. For a click on the canvas to select the right piece of content, the elements carrying that content must be identifiable in the output. That obligation, and its strict limits, are the marker contract.
  • Interactivity is a separate file. A render produces markup, not an application. Anything that has to run in a browser is authored as its own client file and loaded beside the page, which is what keeps the two renders comparable in the first place. See Server and client and Islands.

The editor preview and the published page are not two implementations of your section that have to be kept in agreement. They are the same render of the same content, reached by the same path — which is what makes the preview trustworthy rather than approximately right.

It also sets which surface is the demanding one. Publishing renders a section once; the editor re-renders it over and over, against content that changes under it. A section that holds up there will publish without surprises, and a section that only usually agrees with itself shows that in the editor first, long before a buyer would.

Not a CMS. A template stores no property content. It declares the shape of what a page needs — the content it has, and where each piece comes from — and the property’s own content is bound to those declarations per deliverable. The one exception proves the rule: a static asset ships inside the template precisely because it is not property content.

Not a page builder. Composition is code: you list a template’s sections, and the pages they sit on, in a file you write rather than on a canvas, and cross-section behaviour is authored there too — see Composition and reconcile. Layout is the JSX and CSS you author, not a builder’s model you configure.

A section is not a React app. A renderer is server-rendered and ships no JavaScript. That is not a restriction on what a section may do — interactivity is relocated, not banned — but it does mean a section is markup first, with the interactive parts named and isolated rather than assumed everywhere. See Server and client.

Read the two pages that describe what you actually author, then go and build one.

  • Sections and declarations — the section folder in detail, and its three contract files.
  • Slots — the one thing every schema declares.
  • What you’re building — the same ground, told as the first step of the Start track, which walks you to a shipped template.
  • Versioning — what a new kit version means for your workspace.