Skip to main content
This guide shows you how to build a complete commenting system with threaded replies, emoji reactions, and user mentions — all synced in real time.

What You’ll Build

  • A threaded comment feed with replies
  • Emoji reactions on comments and replies
  • User tagging with notifications
  • Real-time sync across all participants

Prerequisites

  • A CollabKit server running with a room and users created
  • @collab-kit/client and @collab-kit/utils installed

Step 1: Set Up the Client

import CollabKitClient from '@collab-kit/client';

const client = new CollabKitClient({
  serverUrl: 'https://api.collab-kit.com',
  authToken: '<jwt-token>',
});

await client.connect();
await client.join();

Step 2: Load Existing Comments

const comments = await client.comments.getAll();
comments.forEach(renderComment);

Step 3: Add a Comment

async function addComment(text: string, taggedUserIds?: string[]) {
  const comment = await client.comments.add(text, {
    tags: taggedUserIds,
  });

  // Set up per-comment listener
  comment.on('update', (updated) => {
    rerenderComment(updated);
  });

  renderComment(comment);
  return comment;
}

Step 4: Reply to a Comment

Comments support one level of nesting:
async function replyToComment(comment, text: string) {
  const reply = await comment.reply(text);
  renderReply(comment.id, reply);
  return reply;
}

Step 5: Add Reactions

async function addReaction(comment, emoji: string) {
  await comment.addReaction(emoji);
}

async function removeReaction(comment, emoji: string) {
  await comment.deleteReaction(emoji);
}

Step 6: Tag Users

async function tagUser(comment, userId: string) {
  await comment.addTag(userId);
}

// Listen for being tagged
client.currentUser?.on('commentTagged', (comment) => {
  showNotification(`You were tagged in: "${comment.text}"`);
});

Step 7: Listen for Real-Time Updates

// New comment from another user
client.comments.on('add', (comment) => {
  renderComment(comment);
  comment.on('update', (updated) => rerenderComment(updated));
});

// Comment deleted by another user
client.comments.on('delete', (commentId) => {
  removeCommentFromUI(commentId);
});

// Comment updated (new reaction, reply, or tag)
client.comments.on('update', (comment) => {
  rerenderComment(comment);
});

Next Steps

  • Anchor comments to specific UI elements or text selections
  • Add user @mention autocomplete using client.users.all
  • Combine with stores to attach comments to specific entities
  • Use webhooks to send email notifications for tagged users