skip to the page

Introduction

Loom is a runtime for interfaces that AI is allowed to change.

A page is not a file of components here. It is a tree — a validated data structure naming primitives you registered, with props those primitives declared. AI never writes that page. It proposes a delta: an ordered list of discrete operations against the tree you already have. A pure function called the Gate decides which of them are allowed, the runtime applies what survives, and the result is rendered.

Everything else on this site follows from those two sentences.

What the next hour looks like

The pages below, in that order, are the shortest way through this site. At the end of them somebody has asked your running page for a change, in a sentence, and it happened — and you can say exactly why it was allowed.

  1. Installation

    The package is in your project, and one call has proved it — you asked for the starter vocabulary and got it back, or got a sentence saying why not.

    2 code blocks3 min to readyou will have typed createStarterPrimitiveRegistry

  2. Your first tree

    You have written a page down as data: a heading, a sentence, the box around them. It is JSON, so you can print it, store it and read it back.

    4 code blocks3 min to readyou will have typed createTree

  3. Rendering a tree

    That data is on the screen, drawn by your own React components. Nothing about the page is generated code.

    4 code blocks3 min to readyou will have typed renderLoomTree

  4. Your first change

    Somebody has asked for a change in a sentence, and it happened. You watched the ask become a written-down list of operations, get an answer, and land on the page.

    2 code blocks4 min to readyou will have typed commitIntent

  5. Primitives and the registry

    A component you built is a word anybody can now use — the first one that was not handed to you. Everything a change is allowed to say comes off that list.

    5 code blocks3 min to readyou will have typed definePrimitive

  6. What the Gate decides

    A change has been refused, and you know why and could have decided otherwise. This is the step people skip and then discover on a Friday.

    3 code blocks5 min to readyou will have typed gatePolicySchema

The bargain

AI that emits UI code cannot be reviewed at a useful granularity. A diff of generated JSX tells you a file changed; it does not tell you that a checkout button was added to the sidebar, whether that was allowed, who asked for it, or how to put it back.

So Loom narrows what AI may produce, and asks you to accept a bounded vocabulary in return for four things a generated file cannot give you:

  • Addressable. A change names a node. "Insert a button into the sidebar" is a value, not a description of a diff.
  • Reviewable. The Gate is a pure function of the proposal and a policy. The same proposal under the same policy always gets the same answer.
  • Attributable. Every change carries who asked, what interpreted it, and why.
  • Reversible. An undo is another proposal — computed from what the change replaced, gated like any other.

The cost is real and worth saying plainly: AI can only say things your registry has words for. If no primitive is registered for a pricing table, nothing can propose one. That is the constraint doing its job, not a gap.

The smallest tree that renderslive · rendered through the runtime

Hello from a tree

Nothing here was written as markup.

Propose a change:

Every one of these goes through the same pipeline a model’s answer would: interpreted, analysed, weighed, judged, applied, appended. The log is real and it is in this tab — reload the page and the example is back as it was.

show the tree
{
  "kind": "element",
  "id": "n_firsttree5",
  "type": "loom.page",
  "props": {
    "fills": true,
    "width": "readable",
    "loom:theme": {
      "palette": "minimal",
      "fontPack": "minimal-sans",
      "stylePreset": "precise"
    }
  },
  "children": [
    {
      "kind": "element",
      "id": "n_firsttree2",
      "type": "loom.heading",
      "props": {
        "level": 1
      },
      "children": [
        {
          "kind": "text",
          "id": "n_firsttree1",
          "value": "Hello from a tree"
        }
      ]
    },
    {
      "kind": "element",
      "id": "n_firsttree4",
      "type": "loom.prose",
      "props": {},
      "children": [
        {
          "kind": "text",
          "id": "n_firsttree3",
          "value": "Nothing here was written as markup."
        }
      ]
    }
  ]
}
A page with a heading and a sentence. Every node names a registered primitive and carries props that primitive declared.

Behavior lives in the component, never in the tree

This is the line that keeps the bargain honest, and it is worth learning before anything else.

A node says what — a heading at level one, a section with this eyebrow, a grid with three columns. It never says how. There is no event handler in a tree, no expression, no callback, no string that gets evaluated. What a primitive does when it is clicked is part of the component you registered and vouched for.

That is why a proposal is safe to gate rather than to sandbox. The worst a delta can do is arrange your own vocabulary into a page you did not want — which is exactly the kind of mistake a review can catch, and exactly the kind an eval cannot.

Four operations, and no fifth

A TreeDelta is an ordered list of operations. There are four:

OperationWhat it does
insertput a new node at an address
removetake a node out
moveput an existing node somewhere else
configurechange a node's props

A re-theme is a configure. Reordering two sections is a move. Adding a feature to a grid is an insert. There is no operation that replaces the tree, because a change you cannot describe is a change you cannot review.

What this site is

Every rendered example on these pages is a real tree, mounted through the real runtime, with the same registry a host would use. Nothing here is a screenshot of a page that used to work. If an example stops rendering, the documentation fails its own tests before it misleads anyone.

Where to go next

Step one of the route above is Installation, and it is the right answer for almost everybody.

Two other openings are worth knowing about. If you would rather be persuaded before you type anything, How it fits together is the whole system in eight paragraphs and What it costs you is the same system from the other side — the eight things Loom takes away. And if you are deciding what an AI is allowed to touch on a page you already care about, What AI may change is the page that answers it.