Watch for real-time updates to previewed components or content via a preview token.
Subscriptions are only useful for draft components and unpublished content, as published versions are immutable and will never change.
Subscription
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:
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! | “update” or “delete” |
timestamp | DateTime! | When the update occurred |
ComponentPreview
| Field | Type | Description |
|---|
componentId | ID! | Component ID |
component | Component | Component data (null if exceeds 128KB) |
resolvedRef | ResolvedPackageRef! | Package IDs for caching |
ContentPreview
| Field | Type | Description |
|---|
contentId | ID! | Content ID |
content | Content | Content data (null if exceeds 128KB) |
resolvedRef | ResolvedPackageRef! | Package IDs for caching |
Example
Variables
{
"token": "abc123def456"
}
Component Update Payload
{
"data": {
"previewUpdated": {
"action": "update",
"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
{
"data": {
"previewUpdated": {
"action": "update",
"timestamp": "2024-01-15T10:30:00Z",
"preview": {
"__typename": "ContentPreview",
"contentId": "cont123",
"content": {
"compiled": "const body = () => { ... }"
},
"resolvedRef": {
"package": "draft:proj123:org456",
"dependencies": ["xyz789ghi012..."]
}
}
}
}
}
Client Implementation
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 === 'delete') {
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 128KB, the component or content field will be null:
if (update.preview.__typename === 'ComponentPreview') {
if (!update.preview.component) {
// Component exceeded 128KB - fetch separately
const component = await fetchComponent(update.preview.componentId);
refreshComponentPreview(component, update.preview.resolvedRef);
}
}