Collaboration (Beta)

Get started with comments

Install @sanity/collaboration, connect it to the Sanity App SDK, and render a working comments panel on one document.

@sanity/collaboration renders comment threads from data the Sanity SDK gives you. This guide takes you from an empty React app to a working comments panel on one document, with threads, replies, reactions, resolve, and a composer for new comments.

This is a paid feature

This feature is available in the Growth plan.

Prerequisites:

  • A Sanity project you can read and write. Comments are scoped to the organization that owns it.
  • A React 19.2 app. The components peer on react and react-dom ^19.2.
  • Basic experience with the Sanity App SDK. If you haven't built an App SDK app before, start with the App SDK Quickstart Guide.
  • The peer dependencies listed in Requirements: @sanity/ui ^4.0.6, styled-components ^6.1, @sanity/icons ^5.2.1, @portabletext/editor ^8.2.4, and @sanity/sdk and @sanity/sdk-react ^3.11.0, installed in Step 1.
  • A document to comment on. This guide uses post-123 of type post.

Step 1: Install the package

The package is in beta, on 0.x. A 0.x minor can carry breaking changes, so read the changelog before moving to a new minor.

npm install @sanity/collaboration

Every comment read and write on this page comes from @sanity/sdk-react/collaboration, which ships in @sanity/sdk-react 3.11.0 and later. Install @sanity/sdk-react and @sanity/sdk at that version:

npm install @sanity/sdk-react@^3.11.0 @sanity/sdk@^3.11.0

Install @sanity/sdk too: the SDK components import it directly, and as an optional peer it isn't installed automatically.

Sanity UI v4 ships its static styles as a plain stylesheet. Import it once, wherever your app loads global CSS:

import '@sanity/ui/styles.css'

Step 2: Configure the SDK

The project and dataset are all SanityApp needs. Comments are scoped to an organization, and the SDK uses the one that owns the project; there's nothing to configure. AuthBoundary handles signing in.

The components render below Sanity UI's ThemeProvider, so App wraps everything in one. If your app already has a ThemeProvider, leave this one out.

import {AuthBoundary, SanityApp} from '@sanity/sdk-react'
import {ThemeProvider} from '@sanity/ui'
import {buildTheme} from '@sanity/ui/theme'

import {Comments} from './Comments'

export function App() {
  return (
    <ThemeProvider theme={buildTheme()}>
      <SanityApp
        config={{
          projectId: '',
          dataset: 'production',
        }}
        fallback={<p>Starting…</p>}
      >
        <AuthBoundary>
          <Comments />
        </AuthBoundary>
      </SanityApp>
    </ThemeProvider>
  )
}

Replace with your project ID from sanity.io/manage.

Step 3: Render the panel

Two components. SDKCommentsProvider resolves who you are from the SDK and holds the selection, and SDKCommentsPanel is the panel: the document's threads, a status filter, every write a card offers, and an Add a new comment thread button under each field heading.

A field with no threads yet has no heading to hang a composer off, so compose adds a composer at the top of the panel, and its fieldPath names the field that composer writes to. Leave it off and the panel can only add to fields that already have comments.

Both reads suspend on first load, so the Suspense boundaries are yours.

import {SDKCommentsProvider, SDKCommentsPanel} from '@sanity/collaboration/sdk'
import {Suspense} from 'react'

export function Comments() {
  return (
    <Suspense fallback={<p>Resolving your identity…</p>}>
      {/* Keeps the selection in React state. To make pasted links work, see
          "Link to a comment". */}
      <SDKCommentsProvider>
        <Suspense fallback={<p>Loading comments…</p>}>
          <SDKCommentsPanel
            documentId="post-123"
            documentType="post"
            compose={{fieldPath: 'title'}}
          />
        </Suspense>
      </SDKCommentsProvider>
    </Suspense>
  )
}

With no navigation props, SDKCommentsProvider keeps the selection in React state. To make a pasted link open the panel on one comment, hand it your router. See Link to a comment.

Step 4: Check that it worked

Load the page and write a comment in the composer at the top of the panel.

Two things happen:

  • The comment appears under a title heading straight away, before the request has settled. Writes apply optimistically.
  • Hovering the comment reveals its actions. Resolve, edit, and delete are all there, because the panel wires every write a card offers.

A thread with more than three replies shows the three most recent and collapses the older ones behind a Show N more button. Resolving the parent resolves the thread and moves it out of the Open view; switch the filter at the top of the panel to Resolved to see it again.

Troubleshooting

The app throws Comment components must be rendered inside a <CommentsProvider>. A comment component is mounted outside the provider. Check that SDKCommentsProvider is above every one of them, including anything rendered into a portal or a dialog.

The comments flash unstyled on first paint. @sanity/ui/styles.css is not imported, or is imported after your own global CSS.

Next steps

Was this page helpful?

Sanity logosanity.ioAll Systems Operational© Sanity 2026
Change site theme