Sign in

How to add private commenting to your app

Some apps have comments that only certain people should see—internal notes, moderation discussions, or team-only annotations. With Liveblocks Comments you can add these alongside your normal public comments, for example with a separate “Leave note” button next to the regular comment button.

Private threads are only available on Team and Enterprise plans.

What we’re building

This guide shows how to give two different thread permissions to two different groups of users, admins and regular users. Admins will be able to view both public and private threads, whereas regular users will only be able to view public threads.

Looking for a full reference?

This guide focuses on building a private commenting UI. For the complete visibility and permissions reference, see How to use public and private threads and Permissions.

How private threads work

A thread’s visibility is set when it’s created, and every comment inside it shares the same visibility. Thread visibility is public by default, but a private thread can be created by passing the visibility="private" option. Liveblocks then only delivers private threads to users who have permission to read them.

There are three pieces to building this:

  1. Authenticate users, and give admins and regular users different room permissions.
  2. Create private threads with Composer or useCreateThread.
  3. Render threads differently depending on their visibility property.

Authenticate users

Before we get started, we need to decide on permissions for each group. Admin users will have full access to all threads, whereas regular users will only be able to see public threads.

GroupPermissionsDescription
"admin"["*:write"]Full access, including all threads.
"regular"["*:write", "comments:private:none"]Full access, but hide private threads.

When creating a room, you can set these permissions for each group under groupAccesses.

const room = await liveblocks.createRoom("my-room-id", {  groupAccesses: {    admin: ["*:write"],    regular: ["*:write", "comments:private:none"],  },});

To assign users to these groups, use groupIds in identifyUser, inside your authentication endpoint.

// `marc` is an admin userconst { body, status } = await liveblocks.identifyUser({  userId: "marc",  groupIds: ["admin"],});
// `olivier` is a regular userconst { body, status } = await liveblocks.identifyUser({ userId: "olivier", groupIds: ["regular"],});

Permissions and authentication are now set up!

Using ID tokens

Liveblocks recommends ID token authentication by default, which we’ve used in these code snippets. If you’re using access tokens, you must set permissions in prepareSession instead of on the room.

Create a private thread

To create a private thread, pass the visibility="private" option to the Composer. In your app, you may wish to hide this behind a button that only admins can see.

import { Composer } from "@liveblocks/react-ui";
function PrivateCommentComposer() { return ( <Composer visibility="private" /> );}

For more complex use cases, you can use the useCreateThread hook to create a private thread.

Render threads in your app

To render threads in your app, use useThreads as usual, and each will only see the threads they are allowed to read. Check for the visibility property to render different UI for public and private threads.

Public threads only
import { Thread } from "@liveblocks/react-ui";import { useThreads } from "@liveblocks/react/suspense";
function ThreadList() { const { threads } = useThreads();
return ( <> {threads.map((thread) => ( <div key={thread.id}> {thread.visibility === "private" && ( <div>Private, only your team can see this</div> )} <Thread thread={thread} /> </div> ))} </> );}

Filtering private threads

If you’d like for admin users to only see public or private threads, you can use the query option to filter threads by visibility.

Public threads only
const { threads } = useThreads({  query: {    visibility: "private",  },});

Next steps

You now have public and private comments living side by side in the same room. Here’s where to learn more: