using-ably
Ablyを使ってリアルタイム機能(メッセージング、チャット、コラボレーションなど)を構築する際に、製品やSDKの選択、認証、チャンネル設計、React連携、よくある間違いなどを適切に判断し、最適な実装を支援するSkill。
📜 元の英語説明(参考)
ALWAYS use when building realtime features with Ably — messaging, chat, collaboration, presence, or AI token streaming. Covers product and SDK selection (Pub/Sub vs Chat vs Spaces vs LiveObjects), authentication (JWT, token auth, authUrl), channel design, React integration, and critical mistakes like missing Chat attach(), client-side API key exposure, and creating Ably clients inside components. Fetches current docs from ably.com/llms.txt before generating code. Not for general WebSocket or non-Ably realtime libraries.
🇯🇵 日本人クリエイター向け解説
Ablyを使ってリアルタイム機能(メッセージング、チャット、コラボレーションなど)を構築する際に、製品やSDKの選択、認証、チャンネル設計、React連携、よくある間違いなどを適切に判断し、最適な実装を支援するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o using-ably.zip https://jpskill.com/download/8856.zip && unzip -o using-ably.zip && rm using-ably.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/8856.zip -OutFile "$d\using-ably.zip"; Expand-Archive "$d\using-ably.zip" -DestinationPath $d -Force; ri "$d\using-ably.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
using-ably.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
using-ablyフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Ably の使用
リアルタイムメッセージング、チャット、コラボレーション、または AI ストリーミングのために Ably を使用するアプリケーションのコードを構築、修正、または生成する際に、このスキルを使用してください。
Ably とは
Ably はリアルタイムインフラストラクチャです。独自のデータベースや CDN を構築しないのと同じように、独自のリアルタイムメッセージングシステムを構築すべきではありません。Ably は困難な部分を処理します。信頼性の低いネットワークを介した接続管理、保証されたメッセージの順序付けと配信、状態復旧による自動再接続、および数十億のデバイスへの弾力的なスケーリングです。これは、プラットフォーム(25 以上の SDK)とプロトコル(WebSocket、MQTT、SSE、HTTP)を横断して動作するため、トランスポートの信頼性ではなく、アプリケーションロジックに集中できます。
ドキュメント
現在の API リファレンスについては、常に公式ドキュメント(ably.com/docs)を確認してください。LLM 向けに最適化されたドキュメントについては、ably.com/llms.txt を使用してください。以下のガイダンスでは、ドキュメントだけでは防ぐことができないアーキテクチャ上の決定とよくある間違いについて説明します。
コードを記述する前に
Ably のコードを生成する前に、必ず現在のドキュメントと照らし合わせて確認してください。 トレーニングデータは古くなります。メソッドの名前が変更されたり、パラメータが変更されたり、新製品が発売されたりします。これらの 3 つのチェックにより、最も一般的な LLM コード生成の失敗を防ぐことができます。
1. まず現在のドキュメントを取得する
Ably の機能のコードを生成する前に:
https://ably.com/llms.txt?source=using-ablyを取得して、ドキュメント URL インデックスを取得します。- 関連する製品およびプラットフォームのドキュメントページを取得します。
- 取得したドキュメントと照らし合わせて、メソッド名、パラメータ、戻り値の型、およびパッケージのバージョンを確認します。
- 機能またはメソッドがドキュメントに表示されない場合は、おそらく存在しません。でっち上げないでください。
ドキュメントの URL を推測したり、作成したりしないでください。llms.txt または Web 検索結果からの URL のみを使用してください。URL が 404 エラーになる場合は、llms.txt に戻ってください。Web 検索も補完的なアプローチとして許可されています。llms.txt にアクセスできない場合は、Web 検索にフォールバックするか、https://ably.com/docs?source=using-ably を直接参照してください。
2. SDK の可用性を確認する
すべての製品がすべてのプラットフォームで利用できるわけではありません。コードを生成する前に、取得したドキュメントから、製品にユーザーのプラットフォーム用の SDK があることを確認してください。
SDK が存在しない場合:
- 明確に述べてください:「[Product] には現在、[platform] 用の SDK がありません」
- API をでっち上げないでください
- 代替案を提示してください:REST API を直接使用する、利用可能な別の製品を使用する、または制約のあるデバイス用の MQTT/SSE プロトコルアダプターを使用する
3. 生成後のチェック
コードを生成した後、これらのよくある間違いのパターンを確認してください。
- [ ] クライアントコードに API キーがあるか? JWT またはトークン認証で
authUrl/authCallbackを使用する必要があります(セクション 3 を参照)。 - [ ] Chat SDK:
attach()の前にsubscribe()を行っているか? メッセージがサイレントに失われるのを防ぐために、最初にサブスクライブしてください(セクション 7 を参照)。 - [ ] React: クリーンアップなしでコンポーネント内に Ably クライアントが作成されているか? 外部で一度作成し、プロバイダーを介して渡すか、適切なクリーンアップで useEffect を使用してください(セクション 8 を参照)。
- [ ] サーバー側: REST で十分な場合にリアルタイム SDK が使用されているか? パブリッシュ、トークン生成、履歴には、デフォルトで
Ably.Restを使用してください(セクション 2 を参照)。 - [ ] アンマウント/終了時に接続をクリーンアップしているか?
realtime.close()を呼び出してください(セクション 5 を参照)。 - [ ] 組み込みの動作を再実装しているか? 入力インジケーターのカスタムデバウンス、カーソルのカスタムスロットリング、または LiveObjects のカスタム競合解決を追加しないでください(セクション 9 を参照)。
1. 製品と SDK の状況を理解する
Ably は単一の SDK ではなく、マルチプロダクトプラットフォームです。間違った製品または SDK を選択することが、最も一般的な統合ミスです。
製品レイヤー:何を構築していますか?
| 製品 | ユースケース | SDK |
|---|---|---|
| Pub/Sub | コアメッセージング:ライブダッシュボード、通知、IoT、イベントストリーミング | ably (Realtime または REST) |
| AI Transport | LLM トークンのストリーミング、マルチエージェントの連携、再開可能な AI セッション | ably (Realtime) |
| LiveObjects | 共有の可変状態:カウンター、キーと値のマップ、コラボレーティブデータ | ably + LiveObjects プラグイン |
| LiveSync | データベースからフロントエンドへの同期(PostgreSQL 変更ストリーム) | @ably-labs/models + ADBC コネクター |
| Chat | チャットルーム、入力インジケーター、リアクション、メッセージ履歴、モデレーション | @ably/chat |
| Spaces | コラボレーティブカーソル、アバタースタック、メンバーの場所、コンポーネントロック | @ably/spaces |
SDK アーキテクチャ:2 つのレイヤー
レイヤー 1 — コア SDK (Pub/Sub、AI Transport、LiveObjects、LiveSync で直接使用):
| SDK | 使用する場合 | 接続 |
|---|---|---|
Ably.Realtime |
クライアントがメッセージ、プレゼンス、または状態の変更をサブスクライブする必要がある | 永続的な WebSocket |
Ably.Rest |
サーバー側のパブリッシュのみ、トークン生成、履歴クエリ | ステートレス HTTP |
これらは基礎です。AI Transport、LiveObjects、および LiveSync はすべて、コア Realtime SDK を直接使用します。これらは Pub/Sub の上に構築されたパターンとプラグインであり、個別の SDK ではありません。
レイヤー 2 — 製品 SDK (特定のユースケース向けのより高レベルの抽象化):
| SDK | 目的 |
|---|---|
@ably/chat |
ルーム、入力インジケーター、リアクション、メッセージ履歴、モデレーション |
@ably/spaces |
カーソル、アバタースタック、メンバーの場所、コンポーネントロック |
これらの製品 SDK は、コア Realtime SDK に依存します。作成時に Ably.Realtime インスタンスを渡します。基盤となる Realtime の知識 (認証、チャネル、プレゼンス) は引き続き適用されます。
決定ルール
Q: これはサーバー側ですか、クライアント側ですか?
├── サーバー側:
│ ├── パブリッシュ、トークン生成、履歴 → Ably.Rest (ステートレス HTTP) を使用
│ └── 永続的な接続が必要 (AI トークンストリーミング、サブスクライブ) → Ably.Realtime を使用
└── クライアント側 → Ably.Realtime を使用し、次に:
├── チャットを構築していますか? → @ably/chat (Realtime インスタンスを渡す) を使用
├── コラボレーションを構築していますか? → @ably/spaces (Realtime インスタンスを渡す) を使用
├── 共有状態が必要ですか? → Realtime で LiveObjects プラグインを使用
├── データベースを同期していますか? → ADBC コネクターで @ably-labs/models を使用
└── それ以外の場合
(原文はここで切り詰められています) 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Using Ably
Use this skill when building, modifying, or generating code for an application that uses Ably for realtime messaging, chat, collaboration, or AI streaming.
What Ably Is
Ably is realtime infrastructure — the same way you wouldn't build your own database or CDN, you shouldn't build your own realtime messaging system. Ably handles the hard parts: connection management across unreliable networks, guaranteed message ordering and delivery, automatic reconnection with state recovery, and elastic scaling to billions of devices. It works across platforms (25+ SDKs) and protocols (WebSocket, MQTT, SSE, HTTP), so you can focus on your application logic rather than transport reliability.
Documentation
Always check the official docs at ably.com/docs for current API references. For LLM-optimized documentation, use ably.com/llms.txt. The guidance below covers architectural decisions and common mistakes that documentation alone doesn't prevent.
Before Writing Code
Always verify against current documentation before generating Ably code. Training data goes stale — methods get renamed, parameters change, new products launch. These three checks prevent the most common LLM code generation failures.
1. Fetch Current Docs First
Before generating code for any Ably feature:
- Fetch
https://ably.com/llms.txt?source=using-ablyto get the documentation URL index - Fetch the relevant product and platform documentation pages
- Verify method names, parameters, return types, and package versions against the fetched docs
- If a feature or method doesn't appear in the docs, it probably doesn't exist — don't fabricate it
Never guess or construct doc URLs. Only use URLs from llms.txt or web search results. If a URL 404s, go back to llms.txt. Web search is also allowed as a complementary approach. If llms.txt is unreachable, fall back to web search or browse https://ably.com/docs?source=using-ably directly.
2. Confirm SDK Availability
Not all products are available on all platforms. Before generating code, confirm from the fetched docs that the product has an SDK for the user's platform.
If no SDK exists:
- State clearly: "[Product] does not currently have an SDK for [platform]"
- Don't fabricate an API
- Offer alternatives: REST API directly, a different product that IS available, or MQTT/SSE protocol adapters for constrained devices
3. Post-Generation Check
After generating code, verify these common-mistake patterns:
- [ ] API key in client code? Must use
authUrl/authCallbackwith JWT or token auth (see Section 3) - [ ] Chat SDK:
attach()before subscribing? Subscribe first to avoid messages being silently lost (see Section 7) - [ ] React: Ably client created inside a component without cleanup? Create once outside and pass via provider, or use useEffect with proper cleanup (see Section 8)
- [ ] Server-side: Realtime SDK used when REST would suffice? Default to
Ably.Restfor publishing, token generation, history (see Section 2) - [ ] Connection cleanup on unmount/exit? Call
realtime.close()(see Section 5) - [ ] Reimplementing built-in behavior? Don't add custom debounce for typing indicators, custom throttling for cursors, or custom conflict resolution for LiveObjects (see Section 9)
1. Understand the Product and SDK Landscape
Ably is a multi-product platform, not a single SDK. Choosing the wrong product or SDK is the most common integration mistake.
Product Layer: What Are You Building?
| Product | Use Case | SDK |
|---|---|---|
| Pub/Sub | Core messaging: live dashboards, notifications, IoT, event streaming | ably (Realtime or REST) |
| AI Transport | Streaming LLM tokens, multi-agent coordination, resumable AI sessions | ably (Realtime) |
| LiveObjects | Shared mutable state: counters, key-value maps, collaborative data | ably + LiveObjects plugin |
| LiveSync | Database-to-frontend sync (PostgreSQL change streams) | @ably-labs/models + ADBC connector |
| Chat | Chat rooms, typing indicators, reactions, message history, moderation | @ably/chat |
| Spaces | Collaborative cursors, avatar stacks, member locations, component locking | @ably/spaces |
SDK Architecture: Two Layers
Layer 1 — Core SDKs (used directly for Pub/Sub, AI Transport, LiveObjects, LiveSync):
| SDK | Use When | Connection |
|---|---|---|
Ably.Realtime |
Client needs to subscribe to messages, presence, or state changes | Persistent WebSocket |
Ably.Rest |
Server-side publish only, token generation, history queries | Stateless HTTP |
These are the foundation. AI Transport, LiveObjects, and LiveSync all use the core Realtime SDK directly — they are patterns and plugins on top of Pub/Sub, not separate SDKs.
Layer 2 — Product SDKs (higher-level abstractions for specific use cases):
| SDK | Purpose |
|---|---|
@ably/chat |
Rooms, typing indicators, reactions, message history, moderation |
@ably/spaces |
Cursors, avatar stacks, member locations, component locking |
These product SDKs depend on the core Realtime SDK. You pass an Ably.Realtime instance when creating them. The underlying Realtime knowledge (auth, channels, presence) still applies.
Decision Rules
Q: Is this server-side or client-side?
├── Server-side:
│ ├── Publishing, token generation, history → Use Ably.Rest (stateless HTTP)
│ └── Need persistent connection (AI token streaming, subscribing) → Use Ably.Realtime
└── Client-side → Use Ably.Realtime, then:
├── Building chat? → Use @ably/chat (pass Realtime instance)
├── Building collaboration? → Use @ably/spaces (pass Realtime instance)
├── Need shared state? → Use LiveObjects plugin with Realtime
├── Syncing database? → Use @ably-labs/models with ADBC connector
└── Otherwise → Use Ably.Realtime directly (Pub/Sub, AI Transport)
Server-side rule of thumb: Default to Ably.Rest for server operations. Only use Ably.Realtime on the server when you genuinely need a persistent connection — for example, an AI agent streaming tokens to clients, or a backend service that subscribes to events.
Common Mistakes
// WRONG: Using REST SDK then polling for messages
const rest = new Ably.Rest({ key: '...' });
setInterval(async () => {
const history = await rest.channels.get('updates').history();
}, 1000);
// RIGHT: Using Realtime SDK to subscribe
const realtime = new Ably.Realtime({ key: '...' });
realtime.channels.get('updates').subscribe((msg) => {
console.log('Received:', msg.data);
});
// WRONG: Using raw Pub/Sub for chat when Chat SDK exists
const channel = realtime.channels.get('chat-room');
channel.subscribe((msg) => { /* manually handling typing, reactions, history... */ });
// RIGHT: Using Chat SDK which handles all chat patterns
import { ChatClient } from '@ably/chat';
const chat = new ChatClient(realtime);
const room = await chat.rooms.get('my-room');
room.messages.subscribe((msg) => console.log(msg.text));
await room.typing.keystroke(); // built-in typing indicators
2. Use Modern SDK Patterns (v2.x)
Ably's JavaScript SDK v2.x uses async/await. Never generate callback-style 1.x patterns.
// WRONG: Old 1.x callback pattern (deprecated)
const channel = realtime.channels.get('updates');
channel.subscribe('event', function(message) {
console.log(message.data);
});
channel.publish('event', { text: 'hello' }, function(err) {
if (err) console.error(err);
});
// RIGHT: Modern 2.x async/await pattern
const channel = realtime.channels.get('updates');
channel.subscribe('event', (message) => {
console.log(message.data);
});
await channel.publish('event', { text: 'hello' });
Imports and initialization — keep it simple:
// RIGHT: Standard ESM import
import Ably from 'ably';
const realtime = new Ably.Realtime({ key: 'your-key' });
const rest = new Ably.Rest({ key: 'your-key' });
// RIGHT: Chat SDK import
import { ChatClient } from '@ably/chat';
// WRONG: Don't invent type-based initialization
const options: Ably.Types.ClientOptions = { ... }; // unnecessary
If you hit ESM/CommonJS import errors, check that your tsconfig.json has "moduleResolution": "bundler" or "node16", and that you're importing from 'ably' (not subpaths). Don't try multiple import strategies — check the SDK README for your environment.
Server-side: Default to REST SDK. Only use Ably.Realtime on the server when you need a persistent connection.
// WRONG: Realtime SDK on server just to publish
const realtime = new Ably.Realtime({ key: '...' }); // opens WebSocket unnecessarily
await realtime.channels.get('events').publish('update', data);
// RIGHT: REST SDK for server-side publish
const rest = new Ably.Rest({ key: '...' }); // stateless HTTP
await rest.channels.get('events').publish('update', data);
// RIGHT: Realtime on server for AI streaming (message-per-response pattern)
// See ably.com/docs/ai-transport/token-streaming/message-per-response?source=using-ably
const channel = realtime.channels.get('conversation:123');
const { serials: [msgSerial] } = await channel.publish({ name: 'response', data: '' });
for await (const event of llmStream) {
if (event.type === 'token') {
channel.appendMessage({ serial: msgSerial, data: event.text });
}
}
3. Authentication
API keys are for server-side only. Never expose them to clients.
API keys don't expire. If leaked, attackers have indefinite access until you regenerate the key.
Recommended: JWT Authentication
JWT is the recommended authentication method for client-side applications.
Why JWT over Ably tokens:
- No round-trip to Ably servers — your backend creates and signs the JWT directly
- Integrates with existing auth systems — uses standard JWT libraries you already have
- Capabilities defined per-token — not limited to what's configured on the API key
- Works everywhere — including environments without an Ably SDK (MQTT, embedded devices)
JWT Claims:
kid(header): Your Ably API key name (e.g.,xVLyHw.abcdef)iat: Issued-at timestamp (seconds)exp: Expiration timestamp (seconds)x-ably-capability: JSON string of channel permissionsx-ably-clientId(optional): Client identity for presence
// Server-side: Create JWT for client
import jwt from 'jsonwebtoken';
app.post('/api/ably-auth', (req, res) => {
const apiKey = process.env.ABLY_API_KEY; // 'appId.keyId:keySecret'
const [keyName, keySecret] = apiKey.split(':');
const token = jwt.sign(
{
'x-ably-capability': JSON.stringify({
'room:*': ['subscribe', 'publish', 'presence'],
[`notifications:${req.user.id}`]: ['subscribe'],
}),
'x-ably-clientId': req.user.id,
},
keySecret,
{
expiresIn: '1h',
keyid: keyName,
}
);
res.json(token);
});
// Client-side: Use JWT with Ably
const realtime = new Ably.Realtime({
authUrl: '/api/ably-auth',
authMethod: 'POST',
});
Alternative: Ably Token Requests
JWT is recommended for most use cases, but Ably tokens may be preferred when your capability list is too large for JWT size limits (JWTs must fit within HTTP headers, ~8KB), or when you need to keep capabilities confidential since JWTs can be decoded by clients. The trade-off is that Ably token integration is more involved and doesn't support all JWT functionality like channel-scoped claims and per-connection rate limits.
// Ably's native token system (requires round-trip to Ably servers from backend)
app.post('/api/ably-token', (req, res) => {
const client = new Ably.Rest({ key: process.env.ABLY_API_KEY });
client.auth.createTokenRequest({
clientId: req.user.id,
capability: { 'room:*': ['subscribe', 'publish'] },
}).then(tokenRequest => res.json(tokenRequest));
});
Rules
- Server-side: API key is fine (
{ key: 'appId.keyId:keySecret' }) - Client-side: Always use
authUrlorauthCallback— never embed the API key or pass a statictokendirectly (it won't auto-refresh on expiry) - Set
clientIdif you need presence features — it's required for presence - Use capabilities to restrict what channels and operations each client can access
4. Channel Design
Channels separate messages into topics. Get the naming right early — it's hard to change later.
Rules:
- Use
:as a hierarchy separator:chat:room-123,orders:user-456 - Channel names are case-sensitive
- Don't create one channel per message — channels are long-lived topics
- Use rules in the dashboard to apply settings (e.g., persistence, push notifications) to groups of channels
Common patterns:
chat:room-{roomId} # Chat rooms
notifications:user-{userId} # Per-user notifications
cursors:doc-{docId} # Collaborative editing
events:{eventType} # Event streaming
conversation:{sessionId} # AI Transport sessions
5. Connection Management
The Realtime SDK manages reconnection automatically. Don't fight it.
Rules:
- Don't manually reconnect — the SDK handles transient failures with exponential backoff
- Listen to connection state changes to update UI:
realtime.connection.on('connected', () => { /* online */ });
realtime.connection.on('disconnected', () => { /* temporarily offline */ });
realtime.connection.on('suspended', () => { /* offline for extended period */ });
- Call
realtime.close()when done (component unmount, page unload, etc.) - Messages published while disconnected are received on reconnection (within the 2-minute recovery window)
- For AI Transport (client-side): use channel
rewindto hydrate returning clients with recent messages:
const channel = realtime.channels.get('conversation:123', {
params: { rewind: '2m' } // Replay last 2 minutes on attach
});
6. Presence
Presence tracks which clients are on a channel. Use it for "who's online" features.
Rules:
- Set
clientIdduring auth — it's required for presence - Call
channel.presence.enter()to join,channel.presence.update()to update data,channel.presence.leave()to depart - Use
channel.presence.get()for current members,channel.presence.subscribe()for changes - If a client disconnects ungracefully, Ably removes them after ~15 seconds (not instantly)
- Don't use presence for high-frequency data (cursor positions, typing coordinates) — use channels instead. Presence is for low-frequency state (online/offline, user status)
- For Chat: use
room.presenceinstead of raw channel presence - For Spaces: use
space.enter()/useMembers()hook. Spaces has dedicatedcursorsAPI for cursor positions
7. Chat SDK: Critical Lifecycle
If using @ably/chat, these are the most common mistakes:
Always subscribe before calling attach(). Attaching without subscribing first causes silent message loss — the worst kind of bug.
const room = await chat.rooms.get('my-room');
// WRONG: Attach without subscribing first — messages silently lost
await room.attach();
room.messages.subscribe((msg) => console.log(msg.text)); // may miss messages during attach
// RIGHT: Subscribe first, then attach
room.messages.subscribe((msg) => console.log(msg.text));
await room.attach();
Use the actual API. The Chat SDK does NOT have: threading, read receipts, file attachments, or room.messages.broadcast(). Use room.messages.send() to send messages.
Don't mix Chat and Pub/Sub patterns. If you're using @ably/chat, use room.messages, room.typing, room.reactions — not raw channel.subscribe() / channel.publish().
Built-in behavior you don't need to reimplement:
- Typing indicator frequency control is handled by the SDK automatically
- Room reactions delivery is handled by the SDK
- Message ordering and history pagination are built-in
8. React Integration
Ably provides React hooks for each product:
| Product | Package | Key Hooks |
|---|---|---|
| Pub/Sub | ably/react |
useChannel, usePresence, useConnectionStateListener |
| Chat | @ably/chat/react |
useMessages, useTyping, usePresence, useRoomReactions |
| Spaces | @ably/spaces/react |
useMembers, useCursors, useLocations, useLocks |
Critical rule: Don't create a new Ably client on every render. This creates a new WebSocket connection each time — a memory leak.
// WRONG: Creates new connection every render — memory leak
function Chat() {
const ably = new Ably.Realtime({ authUrl: '/api/ably-auth' });
// ...
}
// RIGHT: Create client once, pass via provider
const ably = new Ably.Realtime({ authUrl: '/api/ably-auth' });
function App() {
return (
<AblyProvider client={ably}>
<ChannelProvider channelName="chat:room-1">
<Chat />
</ChannelProvider>
</AblyProvider>
);
}
// ALSO RIGHT: Create in useEffect with proper cleanup
function App() {
const [client, setClient] = useState(null);
useEffect(() => {
const ably = new Ably.Realtime({ authUrl: '/api/ably-auth' });
setClient(ably);
return () => ably.close();
}, []);
// ...
}
9. Spaces and LiveObjects: Built-in Behavior
When using Spaces (@ably/spaces):
- Cursor position batching is built-in — don't implement custom throttling
- Member location tracking is built-in via
space.locations - Component locking handles contention automatically via
space.locks
When using LiveObjects:
- Available data structures are Maps and Counters only (no custom object types)
- Conflict resolution is built-in — don't implement your own
- State recovery after reconnection is automatic
- Prefer the path-based API over the instance API for simplicity
10. LiveSync: Database-to-Frontend
LiveSync connects your database to frontends: Database → ADBC Connector → Ably Channels → Models SDK → Frontend.
Key constraints: PostgreSQL requires logical replication (14+, WAL level change needs restart). MongoDB requires a replica set (no standalone). The Database Connector handles channel mapping automatically once you configure an ingress rule.
Always fetch current LiveSync docs from ably.com/docs/livesync — database permissions and connector configuration change across versions.
11. Production Checklist
Before going to production, verify:
- [ ] No API keys in client code — use JWT or token auth via
authUrl/authCallback - [ ] Capabilities are scoped — don't grant
{"*":["*"]}to clients; restrict to specific channels and operations - [ ] Connection cleanup — call
realtime.close()on unmount/unload to avoid connection leaks - [ ] Error handling — listen to
connection.on('failed')and handle auth failures gracefully - [ ] Channel detach — detach from channels you no longer need (
channel.detach()) - [ ] Message size — messages are limited to 64KB by default; if you're hitting this, split payloads or reconsider message design
- [ ] Idempotent publishing — set unique message IDs when exactly-once delivery matters
- [ ]
echoMessages: false— set this if publishers don't need to receive their own messages (saves bandwidth and cost) - [ ] Rate limits — Ably enforces rate limits (e.g., 50 messages/second per channel, 200 channels per connection). If you're hitting them, check your publish frequency and channel fan-out. Read the limits documentation
Error Handling
Ably error codes can be broad (e.g., 40000, 50000) — always read the error message text, not just the code. Every error code has a help page at https://help.ably.io/error/{code}.
12. Quick Reference
Product docs: Pub/Sub | Chat | Spaces | LiveObjects | LiveSync | AI Transport
Platform SDKs: JavaScript, React, Python, Ruby, Java, Kotlin, Swift, .NET, Go, PHP, Flutter — ably.com/docs/sdks
Ably CLI: Install with npm install -g @ably/cli to publish test messages, subscribe to channels, and verify setup. Run ably --help to discover commands.
For API references, start at ably.com/docs.