Skip to main content

RealtimeChat

A realtime chat component with live message updates and connection status.

Props

roomName
string
required
Unique identifier for the chat room
username
string
required
Display name for the current user
className
string
Additional CSS classes to apply to the component

Hook: useRealtimeChat

The component uses the useRealtimeChat hook for managing chat state.

Hook Props

roomName
string
required
Unique identifier for the chat room
username
string
required
Display name for the current user

Hook Return Values

messages
ChatMessage[]
Array of chat messages in the room
sendMessage
(content: string) => Promise<void>
Function to send a new message
isConnected
boolean
Connection status to the realtime backend

Types

interface UseRealtimeChatProps {
  roomName: string;
  username: string;
}

interface ChatMessage {
  id: string;
  content: string;
  user: {
    name: string;
  };
  createdAt: string;
}

Example

import { RealtimeChat } from "@/components/realtime-chat";

export default function ChatRoom() {
  return (
    <RealtimeChat
      roomName="general"
      username="John Doe"
      className="h-[600px]"
    />
  );
}

Direct Hook Usage

import { useRealtimeChat } from "@/hooks/use-realtime-chat";

export default function CustomChat() {
  const { messages, sendMessage, isConnected } = useRealtimeChat({
    roomName: "general",
    username: "John Doe",
  });

  return (
    <div>
      <div>Connected: {isConnected ? "Yes" : "No"}</div>
      {messages.map((msg) => (
        <div key={msg.id}>
          {msg.user.name}: {msg.content}
        </div>
      ))}
      <button onClick={() => sendMessage("Hello!")}>
        Send
      </button>
    </div>
  );
}

RealtimeCursors

A component for displaying realtime cursor positions of multiple users.

Props

roomName
string
required
Unique identifier for the cursor room
username
string
required
Display name for the current user’s cursor
userColor
string
default:"#3b82f6"
Color for the current user’s cursor (hex color)
children
React.ReactNode
Content to render inside the cursor tracking area
className
string
Additional CSS classes to apply to the component

Hook: useRealtimeCursors

The component uses the useRealtimeCursors hook for managing cursor state.

Hook Props

roomName
string
required
Unique identifier for the cursor room
username
string
required
Display name for the current user’s cursor
userColor
string
default:"#3b82f6"
Color for the current user’s cursor (hex color)
throttleMs
number
default:"100"
Throttle interval in milliseconds for cursor position updates

Hook Return Values

cursors
Cursor[]
Array of other users’ cursor positions (excludes current user)
updateCursor
(position: CursorPosition) => void
Function to update the current user’s cursor position
createMouseMoveHandler
(container: HTMLElement) => (e: MouseEvent) => void
Creates a mouse move event handler that calculates container-relative positions
setContainer
(container: HTMLElement | null) => void
Sets the container reference for coordinate calculations
isConnected
boolean
Connection status to the realtime backend
sessionId
string
Unique session identifier for the current user

Types

interface CursorPosition {
  x: number;
  y: number;
}

interface Cursor {
  id: string;
  name: string;
  color: string;
  position: CursorPosition;
}

interface CursorData {
  position: CursorPosition;
  name: string;
  color: string;
}

interface UseRealtimeCursorsProps {
  roomName: string;
  username: string;
  userColor?: string;
  throttleMs?: number;
}

Example

import { RealtimeCursors } from "@/components/realtime-cursors";

export default function CollaborativeCanvas() {
  return (
    <RealtimeCursors
      roomName="canvas-room"
      username="John Doe"
      userColor="#ff6b6b"
      className="w-full h-screen"
    >
      <div>Your canvas content here</div>
    </RealtimeCursors>
  );
}

Direct Hook Usage

import { useRealtimeCursors } from "@/hooks/use-realtime-cursors";
import { useEffect, useRef } from "react";

export default function CustomCursors() {
  const containerRef = useRef<HTMLDivElement>(null);
  const { cursors, createMouseMoveHandler, setContainer, isConnected } =
    useRealtimeCursors({
      roomName: "canvas-room",
      username: "John Doe",
      userColor: "#ff6b6b",
      throttleMs: 50,
    });

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;

    setContainer(container);
    const handleMove = createMouseMoveHandler(container);
    container.addEventListener("mousemove", handleMove);

    return () => {
      container.removeEventListener("mousemove", handleMove);
      setContainer(null);
    };
  }, [createMouseMoveHandler, setContainer]);

  return (
    <div ref={containerRef}>
      {cursors.map((cursor) => (
        <div
          key={cursor.id}
          style={{
            position: "absolute",
            left: cursor.position.x,
            top: cursor.position.y,
            color: cursor.color,
          }}
        >
          {cursor.name}
        </div>
      ))}
    </div>
  );
}

RealtimeAvatarStack

A component that displays avatars of users currently present in a room.

Props

roomName
string
required
Unique identifier for the presence room
user
object
required
Current user information
maxVisible
number
default:"5"
Maximum number of avatars to display before showing count
size
'sm' | 'md' | 'lg'
default:"md"
Size of the avatar stack
className
string
Additional CSS classes to apply to the component

Hook: useRealtimePresenceRoom

The component uses the useRealtimePresenceRoom hook for managing presence state.

Hook Props

roomName
string
required
Unique identifier for the presence room
user
UserPresence
required
Current user information
heartbeatMs
number
default:"10000"
Interval in milliseconds for sending presence heartbeats

Hook Return Values

users
PresenceUser[]
Array of users currently present in the room
isConnected
boolean
Connection status to the realtime backend
userCount
number
Total number of users in the room

Types

interface UserPresence {
  name: string;
  image?: string;
  color?: string;
}

interface PresenceUser {
  id: string;
  name: string;
  image?: string;
  color?: string;
}

interface UseRealtimePresenceRoomProps {
  roomName: string;
  user: UserPresence;
  heartbeatMs?: number;
}

Example

import { RealtimeAvatarStack } from "@/components/realtime-avatar-stack";

export default function DocumentHeader() {
  return (
    <RealtimeAvatarStack
      roomName="document-123"
      user={{
        name: "John Doe",
        image: "https://example.com/avatar.jpg",
        color: "#3b82f6",
      }}
      maxVisible={3}
      size="sm"
    />
  );
}

Direct Hook Usage

import { useRealtimePresenceRoom } from "@/hooks/use-realtime-presence-room";

export default function CustomPresence() {
  const { users, isConnected, userCount } = useRealtimePresenceRoom({
    roomName: "document-123",
    user: {
      name: "John Doe",
      image: "https://example.com/avatar.jpg",
      color: "#3b82f6",
    },
    heartbeatMs: 5000,
  });

  return (
    <div>
      <div>Connected: {isConnected ? "Yes" : "No"}</div>
      <div>Users online: {userCount}</div>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
}

Notes

  • The component automatically joins the room on mount and leaves on unmount
  • Presence heartbeats are sent periodically to maintain user presence
  • Session IDs are generated uniquely per component instance to avoid conflicts in iframes/tabs

Build docs developers (and LLMs) love