> ## 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 `apiKey`:

```javascript theme={null}
const client = createClient({
  url: 'wss://ws-api.metabind.ai?protocol=graphql-transport-ws',
  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://ws-api.metabind.ai?protocol=graphql-transport-ws',
  connectionParams: {
    previewToken: 'abc123def456'
  }
});

const unsubscribe = client.subscribe({
  query: `
    subscription WatchPreview($token: String!) {
      previewUpdated(token: $token) {
        action
        timestamp
        preview {
          __typename
          ... 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


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