Primitives, recipes, promotion: what agents can build

How agents assemble Kugel Platform pages from typed building blocks and shared recipes instead of hand-written markup, with the repeat, binding and fallback rules and the owner-only promotion path.

4 min read t_reference #t_architecture

What an agent can place

Pages on Kugel Platform are built three ways: from named section types, from composed sections assembled out of typed building blocks, and from recipes that save either of those for reuse. Agents use all three through the same object operations, without writing any page code.

The payoff is portability. A recipe built from building blocks renders the same way on every site that adopts it, and recipes in the shared library are kept in step across the fleet: an hourly sweep adds any that a site is missing.

Core terms: building blocks, composed sections, recipes

A composed section is a small tree of twelve building blocks. Four arrange things: grid, stack, columns (two or three stacks side by side) and card (a framed container). Eight hold content: heading, eyebrow (a short label above a heading), text, image, button, icon, divider and form. Each block has its own id, so one block can be edited or commented on alone.

The tree is bounded. By default it can be four levels deep, hold 48 blocks and repeat up to 24 rows. These limits are site settings, adjustable within fixed ceilings.

The shared library holds 59 recipes: 47 section recipes, such as an FAQ accordion, a comparison matrix, a pricing table, a testimonial row and a guarantee band, and 12 page recipes, such as a DTC landing page in two layouts, an offer page, an advertorial and a topic hub.

How blocks get their content, and how a recipe travels

A grid or stack can repeat: one child becomes a template for each row, filled from a live source such as categories and tags, articles, products or the current page's breadcrumb trail. Each row binds fields such as a label, a count or an image by name, and a field that does not exist fails validation instead of rendering blank.

A bound text field can carry a fallback written only from that row's own fields, so an empty value shows a neutral phrase and never another article's excerpt. An image resolves through four rungs: an explicit image, a bound image, a stable pick from a pool, or the site default. It never falls back to a placeholder.

Every recipe is either shared across the fleet or kept on one site. Promoting a site's recipe into the shared library is an owner-only action. Agents are refused.

Worked example: the topics grid

The live reference is the topics-grid recipe, in production on drlurie's /learn/topics. It's a grid of taxonomy terms — one card per category — sorted by label, hidden when empty. Each card binds its eyebrow to the term's article count, its heading to the term's label, its body text to the term's description (falling back to a same-row phrase when unset), and its image to the term's own image with a stable per-card pick from that category's articles.

The route kept its old hand-coded grid as a fallback until the composed section was verified pixel-for-pixel against it; the code path was deleted only after that sign-off.

What this does not cover yet

One common block still cannot be built honestly: a most-read or popular list. Analytics are not readable when the site is built, so use a most-recent list and label it as such. Earlier gaps, a plain divider, breadcrumbs, a weighted tag cloud and a pricing table that reads products from the store, have since been closed.

When a design needs something the blocks cannot express, ask for a new block rather than approximating it with the wrong type. A new block is engine work: typed, validated, rendered and tested centrally.

Back to Library