---
title: "Chat SDK"
description: "Multi-room chat with presence, typing indicators, message replay, and user mapping."
---

# @nolag/chat

Multi-room chat with presence, typing indicators, message replay, and user mapping.

## Overview

`@nolag/chat` is a high-level SDK that turns any application into a fully-featured chat system. It handles room management, user presence, typing indicators, message history replay, and unread tracking, all on top of `@nolag/js-sdk`. You create a `NoLagChat` instance, connect, join rooms, and start sending messages within minutes.

### Key Features

- Multi-room chat with isolated presence per room
- Typing indicators with automatic timeout
- Message replay to catch up on up to 7 days of history after reconnect
- User mapping to attach names, avatars, and metadata to each actor
- Unread message tracking with per-room badge counts
- Automatic reconnection with state restoration

## How It Works

`NoLagChat` wraps the `@nolag/js-sdk` client and manages a lobby for global user presence. When you call `joinRoom()`, it returns a `ChatRoom` instance that subscribes to two topics: `messages` for durable chat history and `_typing` for ephemeral typing signals. A `MessageStore` inside each room accumulates messages and replayed history, while a `PresenceManager` tracks who is currently online.

| Topic | Purpose | Replay |
| --- | --- | --- |
| `messages` | Chat messages: text, metadata, sender info | 7 days |
| `_typing` | Typing start/stop signals (ephemeral) | None |

## Installation

```bash [Terminal]
npm install @nolag/chat @nolag/js-sdk
```

## Quick Start

```typescript [TypeScript]
import { NoLagChat } from '@nolag/chat'

// Create and connect the client
const chat = new NoLagChat('your-access-token', {
  user: { id: 'user-123', name: 'Alice', avatar: '/img/alice.png' },
})

await chat.connect()

// Join a room
const room = await chat.joinRoom('general')

// Send a message
await room.sendMessage('Hello everyone!')

// Listen for messages
room.on('message', (msg) => {
  console.log(`[${msg.sender.name}]: ${msg.text}`)
  console.log('Sent at:', new Date(msg.timestamp))
})

// Listen for typing indicators
room.on('typing', ({ user, isTyping }) => {
  console.log(`${user.name} is ${isTyping ? 'typing...' : 'no longer typing'}`)
})

// Trigger typing events
room.startTyping()
// ... user stops typing
room.stopTyping()

// Get online users in this room
const users = room.getUsers()
console.log('Online:', users.length)

// Leave when done
await chat.leaveRoom('general')
chat.disconnect()
```

## API Reference

### NoLagChat

The main class. Manages the WebSocket connection, global user presence, and room lifecycle.

| Method | Description |
| --- | --- |
| `connect()` | Establish WebSocket connection and announce presence in the lobby |
| `disconnect()` | Gracefully close the connection and clear all rooms |
| `joinRoom(name)` | Join a chat room; returns a `ChatRoom` instance |
| `leaveRoom(name)` | Leave a room and unsubscribe from its topics |
| `getOnlineUsers()` | Return all users currently online across all rooms |
| `setStatus(status)` | Update your own presence status (e.g. `'away'`, `'busy'`) |
| `updateProfile(profile)` | Update display name, avatar, or other profile fields broadcast to peers |

### Events: NoLagChat

| Event | Payload | Description |
| --- | --- | --- |
| `connected` | none | WebSocket connection established |
| `disconnected` | `reason: string` | Connection closed |
| `reconnected` | none | Reconnection successful; rooms are restored automatically |
| `error` | `error: Error` | Unrecoverable error occurred |
| `userOnline` | `user: ChatUser` | A user has come online in the lobby |
| `userOffline` | `user: ChatUser` | A user has gone offline |
| `userUpdated` | `user: ChatUser` | A user updated their profile or status |

### ChatRoom

Returned by `joinRoom()`. Scoped to a single room; handles messaging, typing, and per-room presence.

| Method | Description |
| --- | --- |
| `sendMessage(text)` | Publish a chat message to the room |
| `getMessages()` | Return all messages currently in the local store (including replayed history) |
| `startTyping()` | Broadcast a typing-start signal to other room members |
| `stopTyping()` | Broadcast a typing-stop signal |
| `getUsers()` | Return users currently present in this room |
| `markRead()` | Mark all messages in this room as read, resetting the unread count |

### Events: ChatRoom

| Event | Payload | Description |
| --- | --- | --- |
| `message` | `ChatMessage` | Incoming message from another user |
| `messageSent` | `ChatMessage` | Confirmation that your own message was delivered |
| `userJoined` | `ChatUser` | A user joined this room |
| `userLeft` | `ChatUser` | A user left this room |
| `typing` | `{ user: ChatUser, isTyping: boolean }` | A user started or stopped typing |
| `replayStart` | `{ count: number }` | Historical message replay is beginning |
| `replayEnd` | `{ replayed: number }` | Historical message replay is complete |
| `unreadChanged` | `{ count: number }` | The unread message count for this room changed |
