> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# What is BindJS

> The open component language for agent UI. One component definition, written once with its logic, rendering as native SwiftUI, Jetpack Compose, and React

BindJS is the open component language for agent UI. Write a UI component once, with its logic, and BindJS renders it as native SwiftUI, Jetpack Compose, and React, wherever an agent renders UI: as an MCP Apps View, as an A2UI catalog, or inside an in-app assistant.

A component is written in JavaScript against a SwiftUI-shaped API; a runtime executes it in an isolated context and emits a JSON view tree, and a renderer on each platform draws that tree with real platform widgets. The renderer never sees code, only the tree: no web views, and no per-platform forks.

It's the language Metabind Studio uses to author Interactive Tools. Those tools render inside MCP hosts like Claude Desktop, ChatGPT, and VS Code, and they render as native SwiftUI or Jetpack Compose — or React on the web — when embedded in your own app via the Assistant SDK. The component definition is the same on every surface.

BindJS is open source under the Apache License 2.0: the specification and all three renderers.

<CardGroup cols={2}>
  <Card title="bindjs" icon="github" href="https://github.com/metabindai/bindjs">
    The BindJS Specification, its MCP Apps and A2UI bindings, conformance statements, and the BEP change process. Normative where it and these docs disagree.
  </Card>

  <Card title="bindjs-runtime" icon="github" href="https://github.com/metabindai/bindjs-runtime">
    The core runtime and React renderer — `@metabindai/bindjs-runtime` and `@metabindai/bindjs-react` on npm.
  </Card>

  <Card title="bindjs-apple" icon="github" href="https://github.com/metabindai/bindjs-apple">
    The SwiftUI rendering engine for iOS, macOS, visionOS, tvOS, and watchOS.
  </Card>

  <Card title="bindjs-android" icon="github" href="https://github.com/metabindai/bindjs-android">
    The Jetpack Compose rendering engine for Android — `ai.metabind:bindjs-android`.
  </Card>
</CardGroup>

## Why BindJS

A growing class of applications needs to render server-defined or model-generated UI on multiple platforms. Interactive UI returned from MCP tool calls is one example. LLM-generated component output that ships into a mobile app is another. Most existing approaches in this space assume the renderer is a web view, so the UI ends up looking like a website wherever it appears.

BindJS takes a different position. A UI definition should be one declarative document that the host renders with its own UI toolkit — SwiftUI on iOS, Jetpack Compose on Android, React on the web — rather than a web view embedded everywhere. The same `defineComponent` source produces real SwiftUI and Jetpack Compose on mobile — 60 FPS, with native gestures, native animations, and native typography — and React components on the web. Authors stay in one source file; users get the platform their device runs on.

## The four pieces

A conforming BindJS implementation has four parts:

1. **Runtime** — a small JavaScript runtime that executes component code, manages state, and emits a JSON AST describing the UI tree.
2. **AST and component catalog** — the wire format that the runtime emits, plus the catalog of component and modifier names a renderer must understand (`Text`, `VStack`, `padding`, `onTapGesture`, and so on).
3. **Renderers** — per-platform implementations that walk the AST and produce native views: React, SwiftUI, and Jetpack Compose.
4. **Modifier pipeline** — the chained styling and behavior modifiers (`.padding()`, `.foregroundStyle()`, `.onTapGesture()`) applied in order before the renderer paints the underlying view.

The execution flow is straightforward: you author component code in JavaScript using the BindJS API; the runtime executes it with the BindJS globals (hooks, property helpers, animation builders) injected; component bodies return AST structures describing the UI tree; the renderer walks the AST and produces native views.

## A first look

A BindJS component packages a `body` render function and an optional `properties` schema into a `defineComponent` call exported as the module default. Properties are declared with helper functions like `PropertyString` and `PropertyBoolean`, and the body's `props` argument is typed against the schema with no manual interface needed.

```typescript theme={null}
const properties = {
  title: PropertyString({ title: "Title", required: true, defaultValue: "Welcome" }),
  showAction: PropertyBoolean({ title: "Show action", defaultValue: true }),
}

const body = (props: InferProps<typeof properties>, children) =>
  VStack({ spacing: 16 }, [
    Text(props.title)
      .font("headline")
      .foregroundStyle(Color("primary")),

    props.showAction
      ? Button("Get started", () => console.log("Tapped"))
      : Empty(),
  ])

export default defineComponent({
  metadata: { title: "Welcome card", description: "A simple example" },
  properties,
  body,
})
```

Two things to notice. First, the body's `props` is fully typed — `props.title` is `string`, `props.showAction` is `boolean` — inferred from the property schema. Second, layout and styling use function calls and method chaining instead of JSX. `VStack`, `Text`, and `Button` are functions that return components; modifiers like `.font()` and `.foregroundStyle()` chain off them.

## Where BindJS runs

BindJS components compile to a single bundle that reaches multiple rendering targets. Each target is a different renderer reading the same AST.

| Surface | Renderer | Platform |
| - | - | - |
| MCP hosts (Claude Desktop, ChatGPT, VS Code, Cursor) | `@metabindai/bindjs-react` in a sandboxed iframe | React on the web |
| Assistant SDK embedded in your iOS app | `BindJS` library from [bindjs-apple](https://github.com/metabindai/bindjs-apple) | SwiftUI on iOS, macOS, and visionOS |
| Assistant SDK embedded in your Android app | [bindjs-android](https://github.com/metabindai/bindjs-android) (`ai.metabind:bindjs-android`) | Jetpack Compose |
| Assistant SDK embedded in your web app | `@metabindai/bindjs-react` | React |

The runtime and React renderer are published to npm as `@metabindai/bindjs-runtime` and `@metabindai/bindjs-react` from the [bindjs-runtime](https://github.com/metabindai/bindjs-runtime) repo. All of the renderers are open source under Apache 2.0.

The component definition is identical across rows. The renderer translates each component and modifier to the platform's native equivalent — `VStack` becomes a SwiftUI `VStack` on iOS, a Compose `Column` on Android, and a flex container on the web. Same governance, same brand, same behavior; the renderer changes, the component does not. See [native rendering](/guides/concepts/native-rendering) for the full mapping.

## Authoring primitives

BindJS files declare one of two primitives, each exported as the module's default.

**`defineComponent`** is the canonical case. It packages a `body`, an optional `properties` schema, and optional `metadata`, `previews`, `thumbnail`, and `icon` fields into a single component definition. Almost every component you write — buttons, cards, lists, layouts — is a `defineComponent` call.

**`defineButtonStyle`** is the sibling primitive for custom button styles. It takes a `body` that receives a `configuration` (with the button's `label` and `isPressed`) and optional `props`, and is applied to a `Button` via the `.buttonStyle()` modifier. Use it when you want a reusable button appearance you can attach to any button in your project.

```typescript theme={null}
export default defineButtonStyle({
  body: (configuration, props) =>
    Capsule()
      .fill(Color(props?.color || "blue"))
      .overlay(configuration.label.foregroundStyle(Color("white")))
      .frame({ height: 44 })
      .opacity(configuration.isPressed ? 0.7 : 1),
})
```

Both primitives are typed in `metabind.d.ts`, the canonical TypeScript declaration file the runtime ships.

## Open source

Everything that renders BindJS is open source under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0): the runtime, the React renderer, and the native SwiftUI and Jetpack Compose engines, all under [github.com/metabindai](https://github.com/metabindai). Fork them, audit them, contribute — your components and the code that renders them carry no proprietary dependency. The hosted platform — Metabind Studio, the generated MCP server, the agent proxy — is the commercial product built on top.

## What to read next

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/bindjs/quickstart">
    Build your first BindJS component in five steps.
  </Card>

  <Card title="Authoring components" icon="code" href="/bindjs/authoring/components">
    The `defineComponent` shape, metadata, body, and previews in depth.
  </Card>

  <Card title="MCP host integration" icon="grid" href="/bindjs/authoring/mcp-host">
    How a BindJS component becomes an Interactive Tool inside an MCP host.
  </Card>

  <Card title="Layout — Stacks" icon="layer-group" href="/bindjs/components/layout-stacks#vstack">
    A reference page for `VStack`, `HStack`, `ZStack`, and the lazy variants.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.