---
title: Building a Chat App
description: Step-by-step guide to building a real-time chat application with NoLag.
---

# Building a Chat App

Learn how to build a real-time chat application with NoLag, including messaging, presence tracking, and typing indicators.

## Overview

In this guide, you'll learn how to:

- Set up real-time messaging between users
- Show who's online with presence tracking
- Implement typing indicators
- Handle message history with hydration webhooks

## Basic Setup

```typescript [TypeScript]
import { NoLag } from '@nolag/js-sdk'

const client = NoLag('your_access_token')
await client.connect()

const chatRoom = client.setApp('chat-app').setRoom('general')

// Subscribe to messages
chatRoom.subscribe('messages')

// Listen for new messages
chatRoom.on('messages', (message, meta) => {
  displayMessage(message)
})

// Send a message
function sendMessage(text: string) {
  chatRoom.emit('messages', {
    text,
    sender: currentUser.name,
    timestamp: Date.now()
  })
}
```
```python [Python]
from nolag import NoLag

client = NoLag('your_access_token')
await client.connect()

chat_room = client.set_app('chat-app').set_room('general')

# Subscribe to messages
await chat_room.subscribe('messages')

# Listen for new messages
def on_message(message, meta):
    display_message(message)

chat_room.on('messages', on_message)

# Send a message
async def send_message(text: str):
    await chat_room.emit('messages', {
        'text': text,
        'sender': current_user.name,
        'timestamp': time.time()
    })
```
```go [Go]
package main

import (
    "fmt"
    "time"

    nolag "github.com/NoLagApp/nolag-go"
)

func main() {
    client := nolag.New("your_access_token")
    client.Connect()

    chatRoom := client.SetApp("chat-app").SetRoom("general")

    // Subscribe to messages with handler
    chatRoom.Subscribe("messages", func(data any, meta nolag.MessageMeta) {
        displayMessage(data)
    })
}

// Send a message
func sendMessage(text string) {
    chatRoom.Emit("messages", map[string]any{
        "text":      text,
        "sender":    currentUser.Name,
        "timestamp": time.Now().Unix(),
    })
}
```

## Adding Presence

Show who's currently in the chat room:

```typescript [TypeScript]
// Set your presence (project-level) after connecting
client.setPresence({
  username: currentUser.name,
  status: 'online',
  avatar: currentUser.avatar
})

// Handle presence events on the client
client.on('presence:join', (actor) => {
  addUserToList(actor.presence)
  showNotification(`${actor.presence.username} joined`)
})

client.on('presence:leave', (actor) => {
  removeUserFromList(actor.actorTokenId)
  showNotification(`${actor.presence.username} left`)
})

// Get list of online users
const onlineUsers = client.getPresence()
```
```python [Python]
# Set your presence (project-level) after connecting
await client.set_presence({
    'username': current_user.name,
    'status': 'online',
    'avatar': current_user.avatar
})

# Handle presence events on the client
def on_join(actor):
    add_user_to_list(actor.presence)
    show_notification(f"{actor.presence['username']} joined")

def on_leave(actor):
    remove_user_from_list(actor.actor_token_id)
    show_notification(f"{actor.presence['username']} left")

client.on('presence:join', on_join)
client.on('presence:leave', on_leave)

# Get list of online users
online_users = client.get_all_presence()
```
```go [Go]
// Set your presence (project-level) after connecting
client.SetPresence(map[string]any{
    "username": currentUser.Name,
    "status":   "online",
    "avatar":   currentUser.Avatar,
})

// Listen for presence events
client.On("presence", func(args ...any) {
    data, _ := args[1].(map[string]any)
    fmt.Printf("Presence event: %v\n", data)
})
```

## Message History

Use [per-topic webhooks](/docs/concepts/webhooks) to load message history when users join:

1. Configure an On Subscribe webhook for the `messages` topic in your app's topic settings
2. Your server returns recent messages when called (payload includes `scope` for tenant isolation)
3. Messages are delivered to the client on subscribe

## Next Steps

- [Presence Tracking](/docs/concepts/presence)
- [Webhooks](/docs/concepts/webhooks)
- [Quality of Service](/docs/concepts/qos)
