> ## 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.

# Components and Packages

> BindJS components are the code Types are backed by; packages are immutable, semantically-versioned snapshots

A **component** is the BindJS code that backs a Type. A **package** is an immutable, semantically-versioned snapshot of all the components in a project. Together they form the pair that makes MCP Apps reproducible and rollback-safe: a Type points at a component, the component lives in a package version, and that pairing never silently changes once published.

## Component shapes

Every BindJS component declares one of three shapes through a `defineComponent()`, `defineDataSource()`, or layout-component declaration. The shape determines what kind of Type the component can back.

| Component shape      | Backs                     | What it does                                                                                                                                                                                         |
| -------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Layout component** | Interactive Tool          | Defines a tool's input schema (via `properties`) plus the layout that renders the validated JSON. Allowed-children declarations let the AI compose approved view components inside the layout.       |
| **View component**   | (Reusable building block) | A reusable UI building block — a product card, a button, a chart, a media frame. View components are the building blocks layout components compose, and the candidates a layout's allowlist permits. |
| **Data component**   | Data Tool                 | Declares typed input/output and an `async handler(props, env)` that runs in a V8 sandbox.                                                                                                            |

A Data Tool is just a component with a different shape — it has the same lifecycle, same package, same versioning as a layout or view component. There is no separate "Data Tool" object underneath the surface.

## A component example

A view component (`ProductDetail`) declares what properties the AI can supply and renders the result:

```ts theme={null}
export default defineComponent({
  metadata: {
    title: "Product Detail",
    description: "Image, CTA, description, features, and reviews"
  },
  properties: {
    title: { type: "string", title: "Title" },
    price: { type: "string", title: "Price" },
    asset: { type: "asset", assetTypes: ["image", "video"] },
    // ...
  },
  body: (props) => {
    return VStack({ spacing: 28 }, [
      ProductImage(props),
      ProductTitle(props),
      ProductPrice(props),
      // ...
    ]);
  }
});
```

A data component declares its handler and the input/output schemas it implements:

```ts theme={null}
export default defineDataSource({
  metadata: {
    title: "Product Search",
    description: "Semantic product search via the Metabind Content API"
  },
  properties: {
    searchTerm: { type: "string" },
    needsImage: { type: "boolean" }
  },
  output: {
    products: PropertyArray({ /* ... */ }),
    total: PropertyNumber({})
  },
  handler: async (props, env) => {
    const res = await fetch(url, {
      headers: { "x-api-key": env.secrets.METABIND_API_KEY }
    });
    return res.json();
  }
});
```

For the full BindJS API, see the [BindJS Reference](/bindjs/introduction).

## Packages

A **package** is a frozen, semantically-versioned bundle of every component in a project, plus the asset references those components depend on. Packages are immutable: once published, version `2.1.0` is `2.1.0` forever.

Why this matters:

* **Reproducible renders.** A Type that pinned to package `2.1.0` always renders against `2.1.0`'s component code, even after you publish `2.2.0`.
* **Instant rollback.** Reverting from `2.2.0` to `2.1.0` is a metadata flip, not a redeploy.
* **Predictable updates.** New tool definitions and component changes ship together as a coherent unit, not as a series of partial states.

The CDN serves package bundles content-addressed by hash. Once a package is requested, every renderer (web iframe, iOS, Android) caches it at the edge.

## Draft and published states

Components and packages each have three states:

| State         | Meaning                                                                                                                        |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| **Draft**     | New, never published. Editable freely. Visible only on the project's draft endpoint.                                           |
| **Published** | Live. Visible on the production endpoint.                                                                                      |
| **Modified**  | Was published, has unpublished edits. Production continues to serve the last published version; draft serves the working copy. |

When you publish the project, modified components and Types are promoted: the package version increments, and the production endpoint switches to the new version.

## Inspector and the visual builder

Components author both *what* they render and *how the editor configures them*. The inspector schema (`inspector` config on each property) tells MCP App Studio what controls to show — single-line fields, multi-line text, sliders, color pickers, asset pickers, dropdowns. This is what lets non-technical teams configure Tools without writing code.

```ts theme={null}
properties: {
  starCount: {
    type: "number",
    title: "Star Count",
    inspector: { control: "slider", step: 1 },
    validation: { min: 0, max: 5 }
  }
}
```

## Where components render

The BindJS authoring layer drives what Claude, ChatGPT, and every other MCP host show your users — the React renderer (`@bindjs/renderer`) runs in a sandboxed iframe inside each host. For embedded experiences, Metabind also provides native iOS and Android renderers and an Assistant SDK that ship as part of the Metabind SDK. See [Native rendering](/guides/concepts/native-rendering) for what runs where.

## What to read next

<CardGroup cols={2}>
  <Card title="Tools and Types" icon="wrench" href="/guides/concepts/types">
    How a component becomes a registered MCP tool.
  </Card>

  <Card title="Native rendering" icon="mobile-screen" href="/guides/concepts/native-rendering">
    How one component compiles to React, SwiftUI, and Jetpack Compose.
  </Card>

  <Card title="Authoring BindJS components" icon="code" href="/guides/building/authoring-components">
    How-to: write components from scratch.
  </Card>

  <Card title="BindJS Reference" icon="book" href="/bindjs/introduction">
    Full BindJS API.
  </Card>
</CardGroup>
