All articles

The case for sections over pages

Why we generate every site as independent, typed components with real prop contracts instead of one monolithic page blob.

The obvious way to build a page generator is to generate the page. In goes a brief, out comes one finished artifact. It demos beautifully. It also falls apart the moment a real person wants to change one thing, and real people always want to change one thing.

So we made a different bet. We don't generate pages. We generate sections, independent components that happen to be arranged into a page. The idea isn't new, and that's the point: the rest of the frontend world settled this argument years ago.

A page is the wrong unit of work

A monolithic page is one blob of markup. To change the hero headline, something has to locate the hero inside the blob, edit it without disturbing the rest, and re-render the whole thing. Every edit risks every other part of the page. Every regeneration discards work the user wanted to keep.

The same failure mode shows up in how the page is generated in the first place. Ask a model for one long artifact and you bet the whole output on every token: a single malformed tag near the bottom can break the parse for the entire file, and you cannot keep the good parts. This is why production LLM pipelines lean on constrained, schema-aware decoding. With freeform output a model can "slip extra comments, omit quotes, or add creative text that violates the expected structure," and at scale "a 95% success rate means 1 in 20 requests fails." A section with a known shape is a small, bounded generation target. A page is a long one where the error budget compounds line by line.

A section is a component contract

The thing that makes a section independently editable, regenerable, and testable is that it has an interface. Its props are its API. As one TypeScript guide puts it, props "are the API of your React components, how other developers (including future you) will interact with what you've built." A <Hero> that accepts headline: string, subhead?: string, and cta: { label, href } is a contract: anything that satisfies those types is a valid hero, and nothing else can reach inside it.

That contract is what every serious system underneath this is really enforcing. WordPress made it explicit with block.json, the canonical way since 5.8 to register a block, where the attributes field "describes the custom data the block requires" so the editor can parse them and pass them to the block's Edit component. Storyblok models each component as a reusable schema of typed fields delivered as JSON. Sanity stores rich content as Portable Text, an array of structured blocks kept "separate from its presentation." Builder.io's registerComponent takes an inputs array that is literally "the input schema for the component." Contentful and Webflow land in the same place. Different vocabularies, one conclusion: the section is the unit, the page is an arrangement, and the boundary between them is a typed contract rather than a position in a string.

A real boundary is also what makes a section testable. "Understanding a component's contract is the most important part of testing": you assert against its props and its output, not against the document it happens to live in. Generating a well-typed component you can validate beats generating a freeform blob you can only eyeball.

Independent rendering, not one big tree

Component boundaries pay off again at render time. Islands architecture treats a page as mostly static HTML with "small, independent zones of interactivity dropped into it," and the isolation is the whole point: "Two islands on the same page do not share a React tree, a virtual DOM, or a state store unless you explicitly wire one up," so "a bug in one island cannot crash another." React Server Components reach for the same property, re-rendering a server component on demand and streaming back only what changed instead of reloading the document.

That is exactly the property you want from a generator. If the features section is wrong, you regenerate the features section. The blast radius is one component, not the page, because nothing couples it to a neighbor three blocks away.

Consistency lives below the section

A section never hard-codes its color, type, or spacing. It reads them from shared design tokens, so changing one token updates every page that uses it with no manual sync and no drift. The W3C Design Tokens spec reached its first stable version (2025.10) in October 2025, with editors from Adobe, Google, Figma, and others, so this is now a portable, vendor-neutral contract rather than a per-tool convention.

What sections buy you

Once a page is a list of contracted components, a lot falls out for free.

Editing and reordering get safe. Select a section, change it or move it in the list; the boundary is real, so the blast radius is exactly one block. Regeneration gets surgical too: don't like the features section, ask for a new one, and the system swaps a single component instead of rolling the dice on the whole page. Iterant proposes the new draft; you approve it before anything ships.

Testing gets honest. When the hero is its own component, you can A/B test it in isolation: assign a variant, render it, and track impressions and conversions at the component level, with everything else held constant so the result actually means something. You learn that this hero beat that hero, not that some tangle of changes moved a number.

Reuse compounds. A section that satisfies a clean contract is a library entry. The hundredth page is cheaper than the first because the good components already exist and render anywhere their props are met.

The hard part is the seams

The interesting engineering problem isn't generating a section. It's deciding where one section ends and the next begins, the way a designer would rather than the way a naive parser would.

Cut in the wrong place and you get a section that's half hero and half testimonial, useless to edit and ugly to reuse. Cut well and each section is a coherent idea with a contract that makes sense: one job, one visual rhythm, one editable unit. Getting those seams right across wildly different source sites is most of the work, and most of the value. Brad Frost made the case for thinking this way in Atomic Design: "We're not designing pages, we're designing systems of components."

If the user can't change one thing without fear, we haven't shipped an editor. We've shipped a slot machine.

Why this matters to someone who'll never read the code

None of this shows up in a demo. What shows up is the feeling you get the first time you change a headline and nothing else moves, when reordering two blocks just works, when asking for a fresh variant of one section doesn't cost you the rest of the page.

That feeling is the architecture leaking through in the best way. Treat the section as the unit of work, give it a real contract, and building a site stops feeling like editing a fragile document and starts feeling like arranging confident, independent pieces. The page was never the point. The pieces are.

EngineeringArchitectureEditing
I

Iterant

The website that builds itself

Iterant learns your brand, then designs and writes on-brand landing pages your team can edit and ship. On the blog, we share playbooks and product notes for teams who'd rather launch than wait on a sprint.