Share your app's context
Read the resource and document the Dashboard has in focus, and publish your own app's context so panels and agents can follow along.
Every app in the Dashboard can say what it currently has in focus: which resource, and which document. Panels, agents, and other apps read that context to follow along, which is how a side panel knows which document you are looking at. Read it with the applications.context topic, and publish it with useApplicationContext. Both come from @sanity/sdk-react/dashboard.
Read what the user is looking at
import {useTopic} from '@sanity/sdk-react/dashboard'
import {Suspense} from 'react'
function FocusedDocument() {
const context = useTopic('applications.context')
if (!context?.document) {
return <p>No document in focus</p>
}
return (
<p>
Viewing {context.document.id} in {context.resource.id}, published by {context.appId}
</p>
)
}
export function Panel() {
return (
<Suspense fallback={<p>Waiting for the Dashboard</p>}>
<FocusedDocument />
</Suspense>
)
}The topic carries the context of the foreground application, or null when no app has published one. A value has the shape {resource: {id, type}, document: {id} | null, appId}, where resource.type is dataset, media-library, or canvas, and appId identifies the app that published it. Like the other state topics, it suspends until the first value arrives, so render it inside Suspense. To track only which app is in front, read applications.foreground instead.
Publish context from your own app
If your app has its own notion of an open document, publish it so panels and agents can react. useApplicationContext sends the value to the Dashboard on the applications.context.update event topic for you.
import {useApplicationContext} from '@sanity/sdk-react/dashboard'
import {useMemo} from 'react'
export function DocumentView({documentId}: {documentId: string | null}) {
const context = useMemo(
() =>
documentId
? {
resource: {id: 'my-project.production', type: 'dataset' as const},
document: {id: documentId},
}
: null,
[documentId],
)
useApplicationContext(context)
return <article>{/* your app */}</article>
}Memoize the context value
The hook compares values by reference. A fresh object literal on every render republishes the context on every render, so wrap it in useMemo or hold it in state.
Two more things to know. Pass null when nothing is open: the hook publishes on mount, emits null before each new value, and clears the context when the component unmounts. And leave appId out of what you publish, because the Dashboard fills it in from the message metadata.
How the two sides meet
- Your app publishes its context whenever the focused document changes. The Studio does this already, so a panel sees Studio documents without any extra work.
- The Dashboard tracks which app is in the foreground and forwards that app's context to everyone listening.
- Panels read
applications.contextand re-render. Agents use the same topic to work out which document you are asking about.