# Chapter 5 — Composition, Pieces, and Capabilities So far we've built single programs. The point of Common Fabric, though, is *networks* of programs: patterns composing into bigger patterns, and deployed pieces linking to each other through shared cells. This chapter covers composition inside one source file, the piece lifecycle, linking across pieces, navigation, and the built-in LLM capability. ## Composing patterns in source A pattern instantiates another pattern by calling it — as a function or as JSX (equivalent; the runtime extracts `[UI]` from the result): ```tsx // Shown inside a pattern body. {items.map((item) => ItemCard({ item }))} {items.map((item) => )} ``` What gets passed down is **the cell, not a copy**. In the todo list (Chapter 4), `TodoItemPiece` receives the `item` cell; when its checkbox writes `item.done`, the parent's computeds see it — there is no prop-drilling/state-lifting dance because there is no ownership boundary: both patterns are graphs over the same cells. Streams pass the same way (`removeItem` is sent down so the child can ask the parent to remove it). The contract for a composable child: its `Output` must include `[NAME]: string` and `[UI]: VNode` if the parent will render it. And the wiring is **by exact field name** — the child's input names must match what you pass; there is no automatic mapping. Two cautions, both compiler-rooted (Chapter 7): - Pattern inputs are cell proxies, so spreading them (`{...extraTools}`) is a silent no-op; merge inside a `computed()` instead. - If a value passed to a child came from *another* composed pattern, bridge it through a local `computed()` before using it in `ifElse` (Chapter 4's gotcha). Passing a plain value to a child input creates fresh state owned by that instance; passing a cell shares state. The same `Counter` pattern can be ten independent counters or ten views of one counter, depending only on what the parent passes. ## Pieces: patterns, deployed A **pattern** is source code — a template. A **piece** is an instance of a pattern living in a space. Instantiation (via `cf piece new`, the shell, or another piece) does roughly this (see `packages/piece/src/manager.ts`): 1. The pattern source is compiled and registered, so the space knows the program (not just its output). 2. An **argument cell** is created to hold the piece's inputs, and a **result cell** to hold what the pattern returns; metadata links the piece to its pattern source. 3. The piece is added to the space's piece list (the space's default pattern maintains `allPieces` and exposes an `addPiece` stream — note, even space management is "just a pattern"). 4. From then on, any runtime that opens the space can load the piece: the pattern graph is re-instantiated over the argument cell, and the result (including `[UI]`) flows from there. A piece is identified by an entity id (a hash, e.g. `fid1:abc...`) and can carry a human **slug** for URLs. In the shell, `/{spaceName}/{pieceIdOrSlug}` shows a piece's UI. ## Linking pieces Because a piece's inputs and outputs are cells, you can wire *deployed* pieces together after the fact: ```bash deno task cf piece link /items /items ``` This points the viewer's `items` input at the editor's `items` output — the same cell-sharing as in-source composition, but done at runtime between independently deployed programs. Under the hood it writes a **link** (a serialized cell reference) into the viewer's argument cell; the runtime resolves links transparently on read (Chapter 8). This is the payoff of the whole design: integration between programs is a pointer, not an API project. ## Navigation For drill-down flows (list → detail), a handler can return `navigateTo(somePiece)`: ```tsx // Shown as JSX element children. navigateTo(ItemDetail({ item }))}>Edit ``` `navigateTo` with a freshly-instantiated pattern creates the detail piece and navigates the shell to it; with an existing piece it just navigates. The canonical list/detail example is `packages/patterns/reading-list/` — the detail pattern receives each editable field as a `Writable<>` input and binds them directly with `$value`. ## Capability: LLM calls Patterns can call language models declaratively — `generateText` / `generateObject` are *reactive nodes*, not awaited promises (`docs/common/capabilities/llm.md`): ```tsx // Shown inside a pattern body. const response = generateText({ prompt: userInput, // reactive — re-runs when it changes system: "You are a helpful assistant.", }); // response: { pending: boolean, result?: string, error?: unknown, // partial?: string /* streaming text so far */ } {response.pending ? : {response.result}} ``` The request flows through the server's LLM proxy (Toolshed — Chapter 11), results are cached per distinct input, and `pending`/`error`/`result` are just cells your UI binds to. A real use from `packages/patterns/shopping-list.tsx` — note it's *inside a `.map()`*, one cached classification per item: ```tsx // Shown inside a pattern body. const itemsWithAisles = items.map((item) => { const aisleResult = generateObject({ system: "You are a grocery store assistant. ...respond with one of the exact locations...", prompt: `Store layout:\n${effectiveLayout}\n\nItem: ${item.title}\n...`, model: "anthropic:claude-haiku-4-5", }); return { item, aisle: aisleResult }; }); ``` Model names must be `vendor:model` (e.g. `"anthropic:claude-sonnet-4-5"`, `"openai:gpt-4o"`); a malformed name fails with an unhelpful `TypeError`. `generateObject` accepts `cache: false` to force regeneration (`generateText` is always cached per distinct input). Think about what this composition means: an LLM call whose *prompt is a reactive function of durable shared state*, whose result is durable shared state, inside a list comprehension, synced to every user of the space. That sentence is the product. ## Background execution A piece can keep working with no browser open. A pattern that exposes a `bgUpdater` stream (or registers via the `cf-updater` component) gets picked up by the **background piece service**, which polls registered pieces (every 60 s by default) and sends to that stream server-side — same graph, same cells, headless executor (details in Chapter 11). This is how "summarize my feed every morning" works without anyone keeping a tab open. --- **Next:** [Chapter 6 — The development workflow](06-workflow.md): actually building, deploying, and testing. **Under the hood:** what links physically are and how cross-piece reactivity syncs — [Chapters 8](08-runtime-internals.md) and [9](09-storage-and-sync.md); how the server runs pieces — [Chapter 11](11-deployed-system.md).