Getting started: Chat in JavaScript / TypeScript

This guide will get you started with Ably Chat using TypeScript.

It will take you through the following steps:

  • Create a client and establish a realtime connection to Ably.
  • Create a room and subscribe to its messages.
  • Send a message to the room, and then edit that message.
  • Retrieve historical messages to provide context to new joiners.
  • Set up a typing indicator to see which clients are typing.
  • Display the online status of clients to the room.
  • Subscribe and send reactions to the room.
  • Close a connection to Ably when it is no longer needed.

  • Sign up for an Ably account.
    • Create a new app, and get your first API key.
    • You can use the root API key that is provided by default to get started.
  • Install the Ably CLI:
npm install -g @ably/cli
Copied!
  • Run the following to log in to your Ably account and set the default app and API key:
ably login ably apps switch ably auth keys switch
Copied!
  • Install Node.js version 18 or greater.
  • Install ts-node to execute TypeScript files:
npm install ts-node
Copied!
  • Create a new project in your IDE and install the Ably Chat JavaScript SDK. This will also install the Ably Pub/Sub SDK as it is a dependency:
npm init -y tsc --init npm install @ably/chat
Copied!

Clients establish a connection with Ably when they instantiate an SDK. This enables them to send and receive messages in realtime across channels.

Create an index.ts file in your project and add the following function to instantiate a realtime client with the Pub/Sub SDK and then pass that client into the Chat SDK constructor. Provide an API key and a clientId to identify the client. In production, use token authentication so that your API keys are not exposed publicly.

JavaScript v2.9
import * as Ably from 'ably'; import { ChatClient, AllFeaturesEnabled, MessageEvent, Message } from '@ably/chat'; async function getStarted() { const realtimeClient = new Ably.Realtime({ key: '<loading API key, please wait>', clientId: 'my-first-client' }); const chatClient = new ChatClient(realtimeClient); chatClient.connection.onStatusChange((change) => console.log(`Connection status is currently ${change.current}!`)); }; getStarted();
Demo Only
Copied!

You can monitor the lifecycle of clients’ connections by registering a listener that will emit an event every time the connection state changes. For now, run the function with npx ts-node index.ts to log a message to the console to know that the connection attempt was successful. You’ll see a message saying Connection status is currently connected! printed to your console.

Messages are how your clients interact with one another. Use rooms to separate and organize clients and messages into different topics, or ‘chat rooms’. Rooms are the entry object into Chat, providing access to all of its features, such as messages, presence and reactions.

Add the following lines to your getStarted() function to create an instance of a room, attach to the room instance, and then register a listener to subscribe to messages sent to the room. You then also send your first message. Afterwards, run it with npx ts-node index.ts:

JavaScript v2.9
const room = await chatClient.rooms.get('my-first-room', AllFeaturesEnabled); await room.attach(); room.messages.subscribe((messageEvent: MessageEvent) => { console.log(`Received message: ${ messageEvent.message.text }`); }); const myFirstMessage = await room.messages.send({ text: 'My first message!' });
Copied!

Use the Ably CLI to send a message to your first room. The message will be received by the client you’ve subscribed to the room, and be logged to the console:

ably rooms messages send my-first-room 'Hello!'
Copied!

If your client makes a typo, or needs to update their original message then they can edit it.

Add the following line to your getStarted() function. Now, when you run the function again and send another message, that message will be updated and you should see both in your terminal. Run it with npx ts-node index.ts.

JavaScript v2.9
await room.messages.update(myFirstMessage.copy({ text: 'My 2nd message! (edited)' }));
Copied!

Ably Chat provides a method for retrieving messages that have been previously sent in a room, up until the point that a client joins (attaches) to it. This enables clients joining a room part way through a conversation to receive the context of what has happened, and what is being discussed, without having to ask another client for context.

Use the Ably CLI to send some additional messages to your room, for example:

ably rooms messages send my-first-room 'Old message #1'
Copied!

Create a new clientTwo.ts file in your project, and run the following in a separate terminal instance. It imitates a second client, my-second-client joining the room and receiving the context of the previous 10 messages. Run it with npx ts-node clientTwo.ts

JavaScript v2.9
import * as Ably from 'ably'; import { ChatClient, AllFeaturesEnabled } from '@ably/chat'; async function getStartedLate() { const realtimeClient = new Ably.Realtime({ key: '<loading API key, please wait>', clientId: 'my-second-client' }); const chatClient = new ChatClient(realtimeClient); const room = await chatClient.rooms.get('my-first-room', AllFeaturesEnabled); await room.attach(); const { getPreviousMessages } = room.messages.subscribe(() => { console.log('New message received'); }); const historicalMessages = await getPreviousMessages({ limit: 10 }); console.log(historicalMessages.items.map((message) => `${message.clientId}: ${message.text}`)); }; getStartedLate();
Demo Only
Copied!

Typing indicators enable you to display messages to clients when someone is currently typing. An event is emitted when someone starts typing, when they press a keystroke, and then another event is emitted after a configurable amount of time has passed without a key press.

In practice the typing.start() method would be called on keypress, however for demonstration purposes we will call it and wait for the default period of time to pass for a stop event to be emitted. Using your original client, add the following lines to getStarted() to subscribe to typing events and emit one, then run it with npx ts-node index.ts:

JavaScript v2.9
room.typing.subscribe((typingEvent) => { if (typingEvent.currentlyTyping.size === 0) { console.log('No one is currently typing'); } else { console.log(`${Array.from(typingEvent.currentlyTyping).join(", ")} is typing`); } }); await room.typing.start() // A client types await room.typing.stop()
Copied!

Use the Ably CLI to subscribe to typing events. You will see that the client using the SDK starts to type after re-running getStarted(), with the message my-first-client is typing...:

ably rooms typing subscribe my-first-room
Copied!

Display the online status of clients using the presence feature. This enables clients to be aware of one another if they are present in the same room. You can then show clients who else is online, provide a custom status update for each, and notify the room when someone enters it, or leaves it, such as by going offline.

Add the following lines to your getStarted() function to subscribe to, and join, the presence set of the room. It also sets a short wait before leaving the presence set. Run it with npx ts-node index.ts:

JavaScript v2.9
room.presence.subscribe((member) => { console.log(`Event type: ${ member.action } from ${ member.clientId } with the data ${ JSON.stringify(member.data) }`) }); await room.presence.enter("I'm here!"); setTimeout( () => { room.presence.leave("I'm leaving!"); }, 3000);
Copied!

You can have another client join the presence set using the Ably CLI:

ably rooms presence enter my-first-room --client-id "my-cli" --data '{"status":"learning about Ably!"}'
Copied!

Clients can send an ephemeral reaction to a room to show their sentiment for what is happening, such as a point being scored in a sports game.

Add the following lines to your getStarted() function to subscribe to room reactions. Then run it with npx ts-node index.ts:

JavaScript v2.9
room.reactions.subscribe((reaction) => { console.log(`${ reaction.type } to that!`) });
Copied!

Use the Ably CLI to send some reactions to the room, such as:

ably rooms reactions send my-first-room 👍
Copied!

Connections are automatically closed approximately 2 minutes after no heartbeat is detected by Ably. Explicitly closing connections when they are no longer needed is good practice to help save costs. It will also remove all listeners that were registered by the client.

Connections to Ably are handled by the underlying Pub/Sub SDK. To close the connection you need to call connection.close() on the original realtime client instance.

Add the following to getStarted() to close the connection after a simulated 10 seconds. Run it with npx ts-node index.ts:

JavaScript v2.9
setTimeout(() => realtimeClient.close(), 10000);
Copied!

Continue to explore the documentation with JavaScript as the selected language:

Read more about the concepts covered in this guide:

Explore the Ably CLI further, or visit the Chat API references.

Select...