Design the page (Loom)

A tiny DSL that turns your project into a real-looking page.

When you deploy a project, Weft needs to know how to render it for the visitor. What fields to expose, what outputs to show, what the page looks like, what the CTA button says. That is what Loom is for.

Loom is a small declarative language that sits alongside your Weft code. It describes the visitor-facing page. Themes, phases, fields, outputs, hero, text, columns, cards, CTA, footer. If you want a page to look like a product landing, Loom gets you there in 30 lines.

You rarely write Loom by hand. Ask Tangle: "set up a deploy page for this humanizer, make it look clean, use a purple theme, expose the input field and the result". Tangle writes the Loom. You review, tweak, ship.

Hello Loom

Here is the minimum viable deploy page for a one-LLM project:

Screenshot needed
Side-by-side: this Loom block on the left, the rendered page on the right. Ideally with the purple theme visible.

That is a dozen lines that describe a full page. The rest of this doc goes through each directive and what it does.

theme

The visual style for the whole page. One block, optional, top of the file. Every attribute is optional.

You will almost always want to set primary, mode, and layout. The rest are nice-to-have when you care about a specific visual feel.

phase

A group of fields the visitor fills in. One phase per logical step. If you have more than five or six fields, split them.

The two quoted strings after phase are the title and the optional description. Inside the braces, each field line points at one node config field.

field

Expose one field of one node to the visitor.

The first two positional tokens are nodeId and fieldKey. The rest are attributes.

Variants via as: pick the widget the renderer uses:

  • Text: text, textarea, password, email, url
  • Numbers: number, slider
  • Booleans: toggle, checkbox
  • Single choice: radio, select, cards
  • Multiple choice: multiselect, multicards, tags
  • Time: date, time, datetime
  • Other: file (file upload), color (color picker)

Other attributes:

  • label, description, placeholder: the labels you would expect.
  • options: comma-separated or JSON array, used by select / radio / cards.
  • visibility: both (default), admin, visitor.
  • height, minHeight, maxHeight, width, chrome: sizing and framing.

Sensitive fields (password, api_key) are force-clamped to admin visibility even if the Loom says otherwise. You cannot accidentally publish a credential.

output

Display one output port of one node as a result block.

First two tokens are nodeId and portName. The as: variants for outputs are render targets:

  • text, markdown, code, json, log: text-shaped outputs.
  • image, gallery, audio, video: media.
  • download: a download link for file outputs.
  • stat, progress, chart: number-shaped outputs.

Outputs live outside any phase. They render in the order you declare them.

live

Show live data from a running infrastructure node. Useful when the page is powered by a long-running service (a bridge, a browser pool, a message queue) and you want the visitor to see its current state without clicking Run.

The first token is the nodeId of an infrastructure node. At render time, the runner reads from that infra node's live-data stream and shows whatever it is currently publishing: text values, images, or progress bars. If the infrastructure is not running yet, the live block shows "Start infrastructure to see live data". Live items never trigger executions, they only display.

Presentation bricks

Loom also lets you shape the page around the phases and outputs. Bricks are the visual pieces: hero, heading, text, images, columns, cards, CTAs, footer.

Simple bricks (no children):

Container bricks (can hold other bricks, phases, outputs):

Available brick kinds: hero, heading, text, image, video, embed, divider, spacer, quote, stat, stats, feature, feature-grid, faq, qa, testimonial, badge, banner, section, columns, card, tabs, tab, cta, footer, navbar, navlink, logo.

The cta action supports two modes. action: "run" (the default) runs the project on click. action: "link:https://..." turns the CTA into a plain external link. Useful for "learn more" or "book a demo" buttons that take the visitor somewhere else.

Visibility

Every directive accepts a visibility attribute: both (default), admin, or visitor. It controls who sees the block.

The runner has two modes: admin and visitor. When you open the runner view in the builder (on the project you own), you default to admin mode with a toggle in the corner that lets you preview the visitor view. When a visitor opens your published URL at /p/<user>/<slug>, the mode is forced to visitor and the toggle is disabled.

  • both: the default. Visible in admin mode and in visitor mode.
  • admin: only visible in admin mode. Use for debug output, internal stats, fields the deployer needs to edit but the public should never see.
  • visitor: only visible in visitor mode. Use for a disclaimer or warning that the admin does not need to see.

Password and API key fields are force-clamped to admin at render time, regardless of what the Loom says. You cannot accidentally expose a credential by marking it visibility: visitor.

A richer example: humanizer

Putting it all together. A full humanizer landing page, with a hero, a feature grid, a phase, an output, and a CTA.

Screenshot needed
Rendered humanizer page from the Loom above. Ideally full width, showing hero + 3-column feature grid + phase + output.

Editing Loom

Three ways to change the page.

  1. Ask Tangle. "Make the hero bigger and change the primary color to blue." Tangle patches the Loom for you. Most common.
  2. Open the Configure Runner modal. Switch the Builder to the runner view (the view toggle at the top-right of the editor). In runner view, a Configure Runner button appears at the top of the page. Clicking it opens a modal with the raw Loom source in a syntax-highlighted editor. Edit it, click Save. The runner view updates when the modal closes. Syntax errors block the save.
  3. Write it in the chat inside a \`\`\`\`loom block (four backticks). Tangle applies it as a full replacement or as a patch.
Screenshot needed
The Configure Runner modal open on a project, showing syntax-highlighted Loom source in the editor.

What's next