Skip to main content

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.

BindJS is Metabind’s declarative cross-platform UI framework. You write a component once in a SwiftUI-inspired component language, and it renders as React on the web, SwiftUI on iOS, and Jetpack Compose on Android — without web views, and without per-platform forks. It’s the language MCP App Studio uses to author Interactive Tools. Those tools render inside MCP hosts like Claude Desktop, ChatGPT, and VS Code, and they render natively when embedded in your own iOS, Android, or web app via the Metabind Assistant SDK. The component definition is the same on every surface.

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 natively — as SwiftUI on iOS, Jetpack Compose on Android, or React on the web — rather than a web view embedded everywhere. The same defineComponent source produces native, 60 FPS UI on all three targets, with native gestures, native animations, and native typography. 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.
const properties = {
  title: PropertyString({ title: "Title", required: true, defaultValue: "Welcome" }),
  showAction: PropertyBoolean({ title: "Show action", defaultValue: true }),
}

const body = (props, 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.
SurfaceRendererPlatform
MCP hosts (Claude Desktop, ChatGPT, VS Code, Cursor)@bindjs/renderer in a sandboxed iframeReact on the web
Assistant SDK embedded in your iOS appBindJSRuntimeSwiftUI on iOS, macOS, and visionOS
Assistant SDK embedded in your Android appBindJS runtimeJetpack Compose
Assistant SDK embedded in your web app@bindjs/rendererReact
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 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.
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.

Quickstart

Build your first BindJS component in five steps.

Authoring components

The defineComponent shape, metadata, body, and previews in depth.

MCP host integration

How a BindJS component becomes an Interactive Tool inside an MCP host.

Layout — Stacks

A reference page for VStack, HStack, ZStack, and the lazy variants.