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

# Preview Updates

> Subscribe to preview link updates

Watch for real-time updates to previewed components or content via a preview token.

<Note>
  Subscriptions are only useful for draft components and unpublished content, as published versions are immutable and will never change.
</Note>

## Subscription

```graphql theme={null}
subscription WatchPreview($token: String!) {
  previewUpdated(token: $token) {
    action
    timestamp
    preview {
      ... on ComponentPreview {
        componentId
        component {
          compiled
        }
        resolvedRef {
          package
          dependencies
        }
      }
      ... on ContentPreview {
        contentId
        content {
          compiled
        }
        resolvedRef {
          package
          dependencies
        }
      }
    }
  }
}
```

## Parameters

| Parameter | Type    | Required | Description        |
| --------- | ------- | -------- | ------------------ |
| `token`   | String! | Yes      | Preview link token |

## Authentication

Use `previewToken` in connection params instead of `x-api-key`:

```javascript theme={null}
const client = createClient({
  url: 'wss://api.metabind.ai/graphql',
  connectionParams: {
    previewToken: 'YOUR_PREVIEW_TOKEN'
  }
});
```

## Response: PreviewUpdate

| Field       | Type           | Description                        |
| ----------- | -------------- | ---------------------------------- |
| `preview`   | PreviewResult! | ComponentPreview or ContentPreview |
| `action`    | String!        | "UPDATED" or "DELETED"             |
| `timestamp` | DateTime!      | When the update occurred           |

### ComponentPreview

| Field           | Type                | Description                            |
| --------------- | ------------------- | -------------------------------------- |
| `componentId`   | ID!                 | Component ID                           |
| `componentName` | String!             | Component name for display/recents     |
| `component`     | Component           | Component data (null if exceeds 100KB) |
| `resolvedRef`   | ResolvedPackageRef! | Package IDs for caching                |

### ContentPreview

| Field             | Type                | Description                           |
| ----------------- | ------------------- | ------------------------------------- |
| `contentId`       | ID!                 | Content ID                            |
| `contentName`     | String!             | Content name for display/recents      |
| `contentTypeName` | String!             | Content type name for display/recents |
| `content`         | Content             | Content data (null if exceeds 100KB)  |
| `resolvedRef`     | ResolvedPackageRef! | Package IDs for caching               |

## Example

### Variables

```json theme={null}
{
  "token": "abc123def456"
}
```

### Component Update Payload

```json theme={null}
{
  "data": {
    "previewUpdated": {
      "action": "UPDATED",
      "timestamp": "2024-01-15T10:30:00Z",
      "preview": {
        "__typename": "ComponentPreview",
        "componentId": "comp123",
        "component": {
          "compiled": "const body = (props) => { ... }"
        },
        "resolvedRef": {
          "package": "draft:proj123:org456",
          "dependencies": []
        }
      }
    }
  }
}
```

### Content Update Payload

```json theme={null}
{
  "data": {
    "previewUpdated": {
      "action": "UPDATED",
      "timestamp": "2024-01-15T10:30:00Z",
      "preview": {
        "__typename": "ContentPreview",
        "contentId": "cont123",
        "content": {
          "compiled": "const body = () => { ... }"
        },
        "resolvedRef": {
          "package": "draft:proj123:org456",
          "dependencies": ["xyz789ghi012..."]
        }
      }
    }
  }
}
```

## Client Implementation

```javascript theme={null}
import { createClient } from 'graphql-ws';

const client = createClient({
  url: 'wss://api.metabind.ai/graphql',
  connectionParams: {
    previewToken: 'abc123def456'
  }
});

const unsubscribe = client.subscribe({
  query: `
    subscription WatchPreview($token: String!) {
      previewUpdated(token: $token) {
        action
        timestamp
        preview {
          ... on ComponentPreview {
            componentId
            component {
              compiled
            }
            resolvedRef {
              package
              dependencies
            }
          }
          ... on ContentPreview {
            contentId
            content {
              compiled
            }
            resolvedRef {
              package
              dependencies
            }
          }
        }
      }
    }
  `,
  variables: { token: 'abc123def456' }
}, {
  next: (data) => {
    const update = data.data.previewUpdated;

    if (update.action === 'DELETED') {
      if (update.preview.__typename === 'ComponentPreview') {
        removeComponentPreview(update.preview.componentId);
      } else {
        removeContentPreview(update.preview.contentId);
      }
      return;
    }

    // Handle updates based on type
    if (update.preview.__typename === 'ComponentPreview') {
      if (update.preview.component) {
        refreshComponentPreview(update.preview.component, update.preview.resolvedRef);
      } else {
        fetchComponent(update.preview.componentId).then(component => {
          refreshComponentPreview(component, update.preview.resolvedRef);
        });
      }
    } else if (update.preview.__typename === 'ContentPreview') {
      if (update.preview.content) {
        refreshContentPreview(update.preview.content, update.preview.resolvedRef);
      } else {
        fetchContent(update.preview.contentId).then(content => {
          refreshContentPreview(content, update.preview.resolvedRef);
        });
      }
    }

    // Fetch missing package data
    fetchMissingPackages([
      update.preview.resolvedRef.package,
      ...update.preview.resolvedRef.dependencies
    ]);
  },
  error: (err) => console.error('Subscription error:', err)
});
```

## Handling Large Payloads

When data exceeds 100KB, the `component` or `content` field will be `null`:

```javascript theme={null}
if (update.preview.__typename === 'ComponentPreview') {
  if (!update.preview.component) {
    // Component exceeded 100KB - fetch separately
    const component = await fetchComponent(update.preview.componentId);
    refreshComponentPreview(component, update.preview.resolvedRef);
  }
}
```

## Related

* [Preview Query](/graphql/queries/preview) - Initial preview data fetch
* [Subscription Types](/graphql/types/subscription-types) - PreviewUpdate type details
* [Previews](/graphql/previews) - Preview links overview
