The only way
for Claude to do UI.
Author components with zero boilerplate. Loom is the first UI language optimized for both human maintainability and agentic development.
- props
label: string
variant: 'primary' | 'ghost' = 'primary'
- ts
const isPrimary = variant === 'primary'
- pug
button.btn
:class { 'btn--ghost': !isPrimary }
::
padding 10px 20px
border-radius 8px
background {isPrimary ? '#7c3aed' : 'transparent'}
{label}export function Btn({ label, variant = 'primary' }: {
label: string
variant?: 'primary' | 'ghost'
}) {
const isPrimary = variant === 'primary'
return (
<button
className={`btn${!isPrimary ? ' btn--ghost' : ''}`}
style={{ padding: '10px 20px',
background: isPrimary ? '#7c3aed' : 'transparent' }}
>
{label}
</button>
)
}Same component.
96% fewer tokens.
Traditional frameworks require heavy boilerplate, saturating context windows. Loom eliminates the noise, giving AI agents more room to reason.
import { useState } from 'react'
interface Props {
name: string
role: string
}
export function Card({ name, role }: Props) {
const [liked, setLiked] = useState(false)
return (
<div className="card">
<h3>{name}</h3>
<span>{role}</span>
<button
onClick={() => setLiked(!liked)}>
{liked ? '♥' : '♡'} Like
</button>
</div>
)
}<script setup lang="ts">
import { ref } from 'vue'
defineProps<{
name: string
role: string
}>()
const liked = ref(false)
</script>
<template>
<div class="card">
<h3>{{ name }}</h3>
<span>{{ role }}</span>
<button @click="liked = !liked">
{{ liked ? '♥' : '♡' }} Like
</button>
</div>
</template><script lang="ts">
export let name: string
export let role: string
let liked = false
</script>
<div class="card">
<h3>{name}</h3>
<span>{role}</span>
<button
on:click={() => liked = !liked}>
{liked ? '♥' : '♡'} Like
</button>
</div>card.loom
14 lines · 35 tokens · Infinite Context
One .loom file.
Any framework.
Explicit zones cleanly separate props, logic, and template. By eliminating boilerplate, Loom accelerates iteration for both humans and AI agents.
- props
name: string
role: string
- ts
const liked = ref(false)
- pug
div.card
h3 {name}
span.role {role}
button
@click liked = !liked
{liked ? '♥' : '♡'} Like- propsComponent interfaceTyped props with optional defaults. Compiles to framework-native declarations — no boilerplate.
- tsLogicStandard TypeScript. Import any library. Loom wires reactivity per-framework automatically.
- pugTemplateIndentation-based markup. :: for scoped styles, @event for handlers.
- genericsTypeScript genericsGeneric type parameters for type-safe, reusable component APIs.
Built for the
agent era.
loom-llm gives agents a structured projection of your component — block IDs, symbols, markup tree — so they read and patch only what they need.
# File: src/Counter.loom
Component: Counter
Mode: outline
Token Estimates: source=68, outline=41, edit=18
## Diagnostics
- none
## Symbols
- imports: none
- props: title, initialCount
- state: count
- computed: isBig
- elements: div, h2, button, span, p
## Blocks
- [props:0] 2 props
- [state:0] 1 state var: count
- [computed:0] 1 computed: isBig
- [markup:0] div.counter-card
## Markup Tree
- [markup:0/div:0] div.counter-card
- [markup:0/div:0/h2:0] h2
- [markup:0/div:0/button:0] button (@click)
- [markup:0/div:0/span:0] span
- [markup:0/div:0/if:0] if isBig- props
title: string
initialCount: number = 0
- state
count: number = initialCount
- computed
isBig = count > 10
- pug
div.counter-card
::
padding: 1.5rem
border: {isBig ? 'red' : '#ddd'}
h2 {title}
button
@click
count++
+ Increment
span Current: {count}
if isBig
p.warning BIG NUMBER!import { useState, useMemo } from 'react'
export function Counter({
title, initialCount = 0
}: { title: string; initialCount?: number }) {
const [count, setCount] = useState(initialCount)
const isBig = useMemo(
() => count > 10, [count]
)
return (
<div className="counter-card"
style={{ padding: '1.5rem',
border: isBig ? '1px solid red'
: '1px solid #ddd' }}>
<h2>{title}</h2>
<button
onClick={() => setCount(c => c+1)}>
Increment
</button>
<span>Current: {count}</span>
{isBig && <p className="warning">
BIG NUMBER!
</p>}
</div>
)
}[computed:0]replace-block patch JSON Use fewer tokens.
Do more.
Context tokens needed for an agent to understand and edit the same component, across tools.
Built for how you
actually work.
From incremental adoption to full-stack SSR — Loom fits your workflow.
Write once, deploy anywhere
One .loom file compiles to idiomatic React, Vue, or Svelte. No rewrites when your stack changes.
Zero runtime overhead
Compiles to native framework code at build time. No wrapper layers, no abstraction tax.
Incremental adoption
Drop .loom components into any existing React, Vue, or Svelte project. No migration required.
TypeScript-native from the start
Typed props, generics, and full IDE support out of the box. Loom knows your types — and so does your editor.
High-Performance Compiler
Written in Rust to ensure instantaneous compilation. ~28ms builds keep your development loop fast as your project grows.
Automated Migration
Ship with confidence. Our codemod tools automatically transform existing React components into clean Loom zones.
Token Efficiency
Significantly reduce LLM token usage. By compressing component structure, Loom lowers the cost of agent-driven development.
Ready to build
with Loom?
Start writing cleaner components today. Works seamlessly with Vite — drop in the plugin and you're ready to go.