Building a Chat App

Build a real-time P2P chat experience with channels, message envelopes, basic presence, and production-ready guardrails.

Prerequisites

Complete Quick Integration and skim Security Best Practices for auth and abuse protection.

1) Define a message envelope

Use an explicit envelope so you can version your protocol and add metadata later.

// Example envelope (pseudo)
{
  "v": 1,
  "type": "chat.message",
  "room": "general",
  "id": "uuid",
  "ts": 1734567890000,
  "from": "user:123",
  "body": "hello"
}

2) Route by channel

Use a logical channel to separate chat from other app traffic (sync, telemetry, file offers).

p2p.onMessage { msg ->
    if (msg.channel != "chat") return@onMessage

    // msg.payload -> decode envelope
}

See Message for fields you can rely on.

3) Sending messages safely

  • Bound message size.
  • Retry with backoff only for transient errors.
  • Log correlation IDs (trace IDs) for debugging.
p2p.sendMessage(peerId, payload) { result ->
    if (!result.ok) {
        log("send failed", result.traceId, result.error)
    }
}

See SendResult.

4) Basic presence

Presence is an application feature. A common pattern:

  • On connect: broadcast chat.presence (online)
  • On background/exit: broadcast chat.presence (offline)
  • Expire presence with TTL (avoid permanent “online”)

5) Production hardening checklist

  • Enable encryption in PeerConfig and consider end-to-end encryption.
  • Authenticate peers; never trust peer IDs as identities.
  • Rate limit sends, joins, and message parses.
  • Store message history locally; treat remote history as untrusted.