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

# iOS SDK

> Fetch and render Metabind content in your iOS, macOS, and visionOS apps with SwiftUI

The Metabind iOS content SDK is the `MetabindContent` library in the `metabind-apple` Swift package. It fetches content from Metabind and renders it as native SwiftUI, so you can update layouts and experiences over the air without an App Store release.

<Card title="View on GitHub" icon="github" href="https://github.com/metabindai/metabind-apple">
  `metabind-apple` — source code, issues, and releases.
</Card>

## Requirements

| Requirement | Version |
| - | - |
| iOS | 17.0 or later |
| macOS | 14.0 or later |
| visionOS | 1.0 or later |
| Swift | 6.0 or later |

## Installation

Add the `metabind-apple` package to your project using Swift Package Manager, and choose the `MetabindContent` library. The package ships two other libraries — `MetabindAI` and `MCPAppsHost`, for embedding a governed agent in your app — that you don't need for content rendering.

<Tabs>
  <Tab title="Xcode">
    1. Open your project in Xcode
    2. Go to **File → Add Package Dependencies**
    3. Enter the repository URL:

    ```
    https://github.com/metabindai/metabind-apple
    ```

    4. Select the version, then add the **MetabindContent** library to your target
  </Tab>

  <Tab title="Package.swift">
    Add the package to your dependencies:

    ```swift theme={null}
    dependencies: [
        .package(url: "https://github.com/metabindai/metabind-apple", from: "1.3.0")
    ]
    ```

    Then add the `MetabindContent` library to your target:

    ```swift theme={null}
    .target(
        name: "YourApp",
        dependencies: [
            .product(name: "MetabindContent", package: "metabind-apple")
        ]
    )
    ```
  </Tab>
</Tabs>

## Quick start

### 1. Initialize the client

Create a `MetabindClient` with your API credentials from the [Metabind dashboard](https://metabind.ai):

```swift theme={null}
import SwiftUI
import MetabindContent

@main
struct MyApp: App {

    @State var client = MetabindClient(
        url: URL(string: "https://api.metabind.ai/graphql")!,
        ws: URL(string: "wss://ws-api.metabind.ai")!,
        apiKey: "your-api-key",
        organizationId: "your-org-id",
        projectId: "your-project-id"
    )

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(client)
        }
    }
}
```

### 2. Display content

Use `MetabindView` to render content by its ID:

```swift theme={null}
struct ContentView: View {

    var body: some View {
        MetabindView(contentId: "your-content-id")
    }
}
```

To receive live updates when the content changes in Metabind, opt in to the WebSocket subscription:

```swift theme={null}
MetabindView(contentId: "your-content-id", enableSubscription: true)
```

### 3. Handle actions

Listen for actions triggered by user interactions:

```swift theme={null}
MetabindView(contentId: "your-content-id")
    .onMetabindAction { action in
        switch action.name {
        case "metabind.content":
            // Navigate to another content page
            if let contentId = action.props["contentId"] as? String {
                navigateTo(contentId)
            }
        case "custom.action":
            // Handle your custom actions
            handleCustomAction(action.props)
        default:
            break
        }
    }
```

## Core concepts

### MetabindClient

The client manages the connection to Metabind's API and handles:

* **Authentication** — API key validation and request signing
* **Content fetching** — GraphQL queries for content and components
* **Real-time updates** — WebSocket subscriptions for live content changes
* **Caching** — a local SQLite-backed cache of fetched content and components

Inject the client into the SwiftUI environment so all views can access it:

```swift theme={null}
.environment(client)
```

For direct access, `MetabindClient` exposes `async` fetchers — `fetchContent(id:)`, `fetchContents(typeId:limit:)` — along with `streamContent(id:)` and `subscribeToContent(id:)` for cache-then-network and real-time streams.

### MetabindView

`MetabindView` is the primary way to display content. It automatically:

* Fetches the content and its required components
* Renders the UI based on your design system
* Subscribes to real-time updates when `enableSubscription` is `true`
* Handles loading and error states

```swift theme={null}
MetabindView(contentId: "content-id", enableSubscription: false)
```

### Actions

Actions are events triggered by user interactions with your content. Handle them with the `onMetabindAction` modifier, which delivers a `MetabindContentAction` (a `name` and a `props` dictionary):

An action's `name` is whatever string the component author emits — there's no fixed platform vocabulary. One convention the Metabind samples use:

| Action | Description |
| - | - |
| `metabind.content` | Navigate to another content page — `props` carries the target content id (see the [Retail sample](https://github.com/metabindai/metabind-apple/tree/1.5.0/Samples/MetabindContent/Retail)) |
| Custom actions | Any name you define in your components; handle it by matching `action.name` |

## Real-time updates

For live content, either pass `enableSubscription: true` to `MetabindView` or subscribe directly. `subscribeToContent(id:)` opens a GraphQL WebSocket subscription and yields the content each time it changes in Metabind:

```swift theme={null}
for await result in client.subscribeToContent(id: "your-content-id") {
    if case .success(let content) = result {
        // Re-render or update state with the new content
    }
}
```

The client pauses the subscription when the app enters the background and resumes it on return. For cache-then-network delivery without a live subscription, use `streamContent(id:)`.

## Direct GraphQL access

Beyond `MetabindView`, `MetabindClient` exposes the underlying GraphQL operations directly, all following the same shape:

* **`fetch*`** — a single `async` request.
* **`stream*`** — an `AsyncStream` that yields cached data first, then network updates.
* **`subscribeTo*`** — a real-time WebSocket subscription (content only).

These cover content, components, content types, assets, tags, packages, and saved searches. For the full method catalog and parameters, see the [client API reference in the repository README](https://github.com/metabindai/metabind-apple#work-with-the-api-directly); for the GraphQL API itself, see the [GraphQL docs](/graphql/overview).

## Navigation

For apps with multiple content pages, integrate with SwiftUI's navigation system:

```swift theme={null}
struct ContentView: View {

    @State private var path = NavigationPath()

    private enum Destination: Hashable {
        case content(id: String)
    }

    var body: some View {
        NavigationStack(path: $path) {
            MetabindView(contentId: "home")
                .onMetabindAction { action in
                    if action.name == "metabind.content",
                       let contentId = action.props["contentId"] as? String
                    {
                        path.append(Destination.content(id: contentId))
                    }
                }
                .navigationDestination(for: Destination.self) { destination in
                    switch destination {
                    case .content(let id):
                        MetabindView(contentId: id)
                    }
                }
        }
    }
}
```

## Platform support

| Platform | Minimum version |
| - | - |
| iOS | 17.0 |
| macOS | 14.0 |
| visionOS | 1.0 |

## Next steps

<CardGroup cols={2}>
  <Card title="Sample app" icon="mobile" href="/samples/retail-app-ios">
    See a complete example of the SDK in action.
  </Card>

  <Card title="Build components" icon="puzzle-piece" href="/guides/building/authoring-components">
    Create custom components for your app.
  </Card>

  <Card title="BindJS reference" icon="code" href="/bindjs/introduction">
    Learn the component authoring language.
  </Card>

  <Card title="Managing content" icon="file-lines" href="/content/overview">
    Understand how to structure content.
  </Card>
</CardGroup>


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