diff --git a/package.json b/package.json
index 64d36c9b57..730c3cb248 100644
--- a/package.json
+++ b/package.json
@@ -40,7 +40,7 @@
     "validate-llms-txt": "node bin/validate-llms.txt.ts"
   },
   "dependencies": {
-    "@ably/ui": "17.9.16",
+    "@ably/ui": "17.11.4",
     "@codesandbox/sandpack-react": "^2.20.0",
     "@codesandbox/sandpack-themes": "^2.0.21",
     "@gfx/zopfli": "^1.0.15",
diff --git a/src/data/languages/languageData.ts b/src/data/languages/languageData.ts
index 2ac17475ee..20179f34fa 100644
--- a/src/data/languages/languageData.ts
+++ b/src/data/languages/languageData.ts
@@ -39,7 +39,8 @@ export default {
     javascript: '1.1',
     react: '1.1',
     swift: '1.0',
-    kotlin: '1.0',
+    kotlin: '1.1',
+    jetpack: '1.1',
   },
   aiTransport: {
     javascript: '2.11',
diff --git a/src/data/languages/languageInfo.ts b/src/data/languages/languageInfo.ts
index f78ff81a2e..69f589b8ea 100644
--- a/src/data/languages/languageInfo.ts
+++ b/src/data/languages/languageInfo.ts
@@ -86,6 +86,10 @@ export default {
     label: 'Kotlin',
     syntaxHighlighterKey: 'kotlin',
   },
+  jetpack: {
+    label: 'Jetpack Compose',
+    syntaxHighlighterKey: 'kotlin',
+  },
   realtime: {
     label: 'Realtime',
     syntaxHighlighterKey: 'javascript',
diff --git a/src/data/languages/types.ts b/src/data/languages/types.ts
index 879ac741c6..e975fe3265 100644
--- a/src/data/languages/types.ts
+++ b/src/data/languages/types.ts
@@ -26,6 +26,7 @@ export const languageKeys = [
   'css',
   'laravel',
   'typescript',
+  'jetpack',
 ] as const;
 
 export type LanguageKey = (typeof languageKeys)[number];
diff --git a/src/pages/docs/chat/connect.mdx b/src/pages/docs/chat/connect.mdx
index 14739608ce..044d6e3f69 100644
--- a/src/pages/docs/chat/connect.mdx
+++ b/src/pages/docs/chat/connect.mdx
@@ -20,8 +20,8 @@ A connection can have any of the following statuses:
 | closed | The connection has been explicitly closed by the client. In the closed state, no reconnection attempts are made automatically. No connection state is preserved by the service or the library. |
 | failed | This status is entered if the SDK encounters a failure condition that it cannot recover from. This may be a fatal connection error received from the Ably service, such as an attempt to connect with an incorrect API key, or some local terminal error, such as that the token in use has expired and the SDK does not have any way to renew it. |
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`status`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Connection.html#status)</If><If lang="swift">[`status`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/connectionstatus)</If><If lang="kotlin">[`status`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-connection/status.html)</If> property to check which status a connection is currently in:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`status`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Connection.html#status)</If><If lang="swift">[`status`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/connectionstatus)</If><If lang="kotlin,jetpack">[`status`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-connection/status.html)</If> property to check which status a connection is currently in:
 </If>
 
 <If lang="react">
@@ -56,6 +56,10 @@ let status = chatClient.connection.status
 ```kotlin
 val connectionStatus = chatClient.connection.status
 ```
+
+```jetpack
+val connectionStatus = chatClient.connection.status
+```
 </Code>
 
 <If lang="react">
@@ -81,7 +85,11 @@ Listeners can also be registered to monitor the changes in connection status. An
 </If>
 
 <If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`connection.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Connection.html#onStatusChange)</If><If lang="swift">[`connection.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/connection/onstatuschange%28%29-76t7)</If><If lang="kotlin">[`connection.status.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-connection/on-status-change.html)</If> method to register a listener for status change updates:
+Use the <If lang="javascript">[`connection.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Connection.html#onStatusChange)</If><If lang="swift">[`connection.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/connection/onstatuschange%28%29-76t7)</If><If lang="kotlin">[`connection.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-connection/on-status-change.html)</If> method to register a listener for status change updates:
+</If>
+
+<If lang="jetpack">
+Use the [`collectAsStatus()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/jetpack/chat-extensions-compose/com.ably.chat.extensions.compose/collect-as-status.html) composable function to observe the connection status:
 </If>
 
 <Code>
@@ -114,6 +122,24 @@ val (off) = chatClient.connection.onStatusChange { statusChange: ConnectionStatu
     println(statusChange.toString())
 }
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.ChatClient
+import com.ably.chat.extensions.compose.collectAsStatus
+
+@Composable
+fun MyComponent(chatClient: ChatClient) {
+  val connectionStatus by chatClient.connection.collectAsStatus()
+
+  LaunchedEffect(connectionStatus) {
+    println("Connection status changed to: $connectionStatus")
+  }
+
+  Text("Connection status: $connectionStatus")
+}
+```
 </Code>
 
 <If lang="javascript,kotlin">
@@ -148,6 +174,10 @@ The Chat SDK provides an `onDiscontinuity()` handler exposed via the Room object
 Any hooks that take an optional listener to monitor their events, such as typing indicator events in the `useTyping` hook, can also register a listener to be notified of, and handle, periods of discontinuity.
 </If>
 
+<If lang="jetpack">
+Use the [`discontinuityAsFlow()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/discontinuity-as-flow.html) extension function to observe discontinuity events as a Flow in Jetpack Compose:
+</If>
+
 For example, for messages:
 
 <Code>
@@ -184,6 +214,22 @@ val (off) = room.onDiscontinuity { reason: ErrorInfo ->
   // Recover from the discontinuity
 }
 ```
+
+```jetpack
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.discontinuityAsFlow
+
+@Composable
+fun MyComponent(room: Room) {
+  LaunchedEffect(room) {
+    room.discontinuityAsFlow().collect { error ->
+      // Recover from the discontinuity
+      println("Discontinuity detected: $error")
+    }
+  }
+}
+```
 </Code>
 
 <If lang="javascript,kotlin">
diff --git a/src/pages/docs/chat/getting-started/android.mdx b/src/pages/docs/chat/getting-started/android.mdx
index f29424da58..f830241c47 100644
--- a/src/pages/docs/chat/getting-started/android.mdx
+++ b/src/pages/docs/chat/getting-started/android.mdx
@@ -252,8 +252,8 @@ fun ChatBox(room: Room?) {
     var sending by remember { mutableStateOf(false) }
     val messages = remember { mutableStateListOf<Message>() }
 
-    DisposableEffect(room) {
-        val subscription = room?.messages?.subscribe { event ->
+    LaunchedEffect(room) {
+        room?.messages?.asFlow()?.collect { event ->
             when (event.type) {
                 MessageEventType.Created -> {
                     // Check if the incoming message is correctly ordered
@@ -266,10 +266,6 @@ fun ChatBox(room: Room?) {
                 else -> Unit
             }
         }
-
-        onDispose {
-            subscription?.unsubscribe()
-        }
     }
 
     Column(
@@ -445,8 +441,8 @@ var edited: Message? by remember { mutableStateOf(null) }
 
 <Code>
 ```kotlin
-DisposableEffect(room) {
-    val subscription = room?.messages?.subscribe { event ->
+LaunchedEffect(room) {
+    room?.messages?.asFlow()?.collect { event ->
         when (event.type) {
             MessageEventType.Created -> messages.add(0, event.message)
             MessageEventType.Updated -> messages.replaceFirstWith(event.message) {
@@ -455,10 +451,6 @@ DisposableEffect(room) {
             else -> Unit
         }
     }
-
-    onDispose {
-        subscription?.unsubscribe()
-    }
 }
 ```
 </Code>
@@ -543,7 +535,7 @@ When you click on the edit button in the UI, you can modify the text and it will
 
 ## Step 6: Message history and continuity <a id="step-6"/>
 
-Ably Chat enables you to retrieve previously sent messages in a room. This is useful for providing conversational context when a user first joins a room, or when they subsequently rejoin it later on. The message subscription object exposes the [`getPreviousMessages()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/get-previous-messages.html) method to enable this functionality. This method returns a paginated response, which can be queried further to retrieve the next set of messages.
+Ably Chat enables you to retrieve previously sent messages in a room. This is useful for providing conversational context when a user first joins a room, or when they subsequently rejoin it later on. The message subscription object exposes the [`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/history-before-subscribe.html) method to enable this functionality. This method returns a paginated response, which can be queried further to retrieve the next set of messages.
 
 Extend the `ChatBox` component to include a method to retrieve the last 10 messages when the component mounts. In your `MainActivity.kt` file, add the `DisposableEffect` in your `ChatBox` component:
 
@@ -551,9 +543,10 @@ Extend the `ChatBox` component to include a method to retrieve the last 10 messa
 ```kotlin
 fun ChatBox(room: Room?) {
     /* variables declaration */
+    var subscription by remember { mutableStateOf<MessagesSubscription?>(null) }
 
     DisposableEffect(room) {
-      val subscription = room?.messages?.subscribe { event ->
+      subscription = room?.messages?.subscribe { event ->
           when (event.type) {
               MessageEventType.Created -> messages.add(0, event.message)
               MessageEventType.Updated -> messages.replaceFirstWith(event.message) {
@@ -563,16 +556,19 @@ fun ChatBox(room: Room?) {
           }
       }
 
-      scope.launch {
-          val previousMessages = subscription?.historyBeforeSubscribe(10)?.items ?: emptyList()
-          messages.addAll(previousMessages)
-      }
-
       onDispose {
           subscription?.unsubscribe()
       }
-  }
-  /* rest of your code */
+    }
+
+    LaunchedEffect(subscription) {
+        subscription?.let { sub ->
+            val previousMessages = sub.historyBeforeSubscribe(10)?.items ?: emptyList()
+            messages.addAll(previousMessages)
+        }
+    }
+
+    /* rest of your code */
 }
 ```
 </Code>
@@ -709,7 +705,7 @@ fun ChatBox(room: Room?) {
 Do the following to test this out:
 
 1. Use the ably CLI to simulate sending some messages to the room from another client.
-2. Refresh the page, this will cause the `ChatBox` component to mount again and call the `getPreviousMessages()` method.
+2. Refresh the page, this will cause the `ChatBox` component to mount again and call the `historyBeforeSubscribe()` method.
 3. You'll see the last 10 messages appear in the chat box.
 
 ## Step 7: Display who is present in the room <a id="step-7"/>
@@ -722,14 +718,15 @@ In your `MainActivity.kt` file, create a new component called `PresenceStatusUi`
 ```kotlin
 @Composable
 fun PresenceStatusUi(room: Room?) {
-    val members = room?.collectAsPresenceMembers()
+    val membersState = room?.collectAsPresenceMembers()
+    val members = membersState?.value ?: emptyList()
 
     LaunchedEffect(room) {
         room?.presence?.enter()
     }
 
     Text(
-        text = "Online: ${members?.size ?: 0}",
+        text = "Online: ${members.size}",
         style = MaterialTheme.typography.bodyMedium,
         modifier = Modifier.padding(start = 8.dp)
     )
diff --git a/src/pages/docs/chat/rooms/history.mdx b/src/pages/docs/chat/rooms/history.mdx
index 74d1507ece..378c907732 100644
--- a/src/pages/docs/chat/rooms/history.mdx
+++ b/src/pages/docs/chat/rooms/history.mdx
@@ -7,8 +7,8 @@ The history feature enables users to retrieve messages that have been previously
 
 ## Retrieve previously sent messages <a id="history"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`messages.history()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#history)</If><If lang="swift">[`messages.history()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/history(withparams:))</If><If lang="kotlin">[`messages.history()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/history.html)</If> method to retrieve messages that have been previously sent to a room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`messages.history()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#history)</If><If lang="swift">[`messages.history()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/history(withparams:))</If><If lang="kotlin,jetpack">[`messages.history()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/history.html)</If> method to retrieve messages that have been previously sent to a room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
 </If>
 
 <If lang="react">
@@ -69,6 +69,19 @@ while (historicalMessages.hasNext()) {
     println(historicalMessages.items.toString())
 }
 
+println("End of messages")
+```
+
+```jetpack
+var historicalMessages = room.messages.history(orderBy = OrderBy.NewestFirst)
+println(historicalMessages.items.toString())
+
+// historical messages are paginated, so we can iterate through
+while (historicalMessages.hasNext()) {
+    historicalMessages = historicalMessages.next()
+    println(historicalMessages.items.toString())
+}
+
 println("End of messages")
 ```
 </Code>
@@ -87,7 +100,11 @@ The following optional parameters can be passed when retrieving previously sent
 Users can also retrieve historical messages that were sent to a room before the point that they registered a listener by [subscribing](/docs/chat/rooms/messages#subscribe). The order of messages returned is from most recent, to oldest. This is useful for providing conversational context when a user first joins a room, or when they subsequently rejoin it later on. It also ensures that the message history they see is continuous, without any overlap of messages being returned between their subscription and their history call.
 
 <If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.MessageSubscriptionResponse.html#historyBeforeSubscribe)</If><If lang="swift">[`historyBeforeSubscribe(withParams:)`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messagesubscriptionresponse/historybeforesubscribe%28withparams%3A%29))</If><If lang="kotlin">[`getPreviousMessages()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/get-previous-messages.html)</If> function returned as part of a [message subscription](/docs/chat/rooms/messages#subscribe) response to only retrieve messages that were received before the listener was subscribed to the room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
+Use the <If lang="javascript">[`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.MessageSubscriptionResponse.html#historyBeforeSubscribe)</If><If lang="swift">[`historyBeforeSubscribe(withParams:)`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messagesubscriptionresponse/historybeforesubscribe%28withparams%3A%29))</If><If lang="kotlin">[`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/history-before-subscribe.html)</If> function returned as part of a [message subscription](/docs/chat/rooms/messages#subscribe) response to only retrieve messages that were received before the listener was subscribed to the room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
+</If>
+
+<If lang="jetpack">
+Use the [`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/history-before-subscribe.html) function returned as part of a [message subscription](/docs/chat/rooms/messages#subscribe) response to only retrieve messages that were received before the listener was subscribed to the room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
 </If>
 
 <If lang="react">
@@ -167,6 +184,53 @@ while (historicalMessages.hasNext()) {
 
 println("End of messages")
 ```
+
+```jetpack
+import androidx.compose.foundation.layout.*
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.MessagesSubscription
+import com.ably.chat.Room
+
+@Composable
+fun HistoryBeforeSubscribeComponent(room: Room) {
+  var messages by remember { mutableStateOf<List<String>>(emptyList()) }
+  var subscription by remember { mutableStateOf<MessagesSubscription?>(null) }
+
+  DisposableEffect(room) {
+    subscription = room.messages.subscribe {
+      println("New message received")
+    }
+
+    onDispose {
+      subscription?.unsubscribe()
+    }
+  }
+
+  LaunchedEffect(subscription) {
+    subscription?.let { sub ->
+      var historicalMessages = sub.historyBeforeSubscribe(limit = 50)
+      println(historicalMessages.items.toString())
+      messages = historicalMessages.items.map { it.text }
+
+      while (historicalMessages.hasNext()) {
+        historicalMessages = historicalMessages.next()
+        println(historicalMessages.items.toString())
+        messages = messages + historicalMessages.items.map { it.text }
+      }
+
+      println("End of messages")
+    }
+  }
+
+  // Display messages in UI
+  Column {
+    messages.forEach { message ->
+      Text(message)
+    }
+  }
+}
+```
 </Code>
 
 The following parameters can be passed when retrieving previously sent messages:
@@ -176,3 +240,79 @@ The following parameters can be passed when retrieving previously sent messages:
 | start | Earliest time to retrieve messages from, as a unix timestamp in milliseconds. Messages with a timestamp equal to, or greater than, this value will be returned. |
 | end | Latest time to retrieve messages from, as a unix timestamp in milliseconds. Messages with a timestamp less than this value will be returned. |
 | limit | Maximum number of messages to be retrieved per page, up to 1,000. |
+
+<If lang="jetpack">
+
+## Messages pagination <a id="messages-pagination"/>
+
+Alternatively, you can use the [`collectAsPagingMessagesState()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat-extensions-compose/com.ably.chat.extensions.compose/collect-as-paging-messages-state.html) composable function to observe messages with automatic pagination support.
+
+This function provides a complete solution for displaying chat messages in Jetpack Compose by:
+- Subscribing to new messages in real-time and adding them to the list
+- Handling message updates and deletions automatically
+- Listening to [message reaction](/docs/chat/rooms/message-reactions) events and updating messages with reaction summaries
+- Managing pagination when scrolling near the end of the list using `historyBeforeSubscribe()`
+- Handling [discontinuities](/docs/chat/rooms/messages#discontinuity) by clearing and reloading messages
+- Only fetching messages when the room is in the attached state
+- Cleaning up resources when the composable leaves the composition
+
+The function accepts two optional parameters:
+- `scrollThreshold`: The number of items remaining before reaching the last item at which fetching the next page is triggered (default: 10)
+- `fetchSize`: The number of messages to load per page (default: 100)
+
+The returned [`PagingMessagesState`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat-extensions-compose/com.ably.chat.extensions.compose/-paging-messages-state/index.html) provides:
+- `loaded`: A list of messages in reverse chronological order (newest first)
+- `listState`: A `LazyListState` for controlling the scroll position and triggering automatic pagination
+- `loading`: Whether a loading operation is in progress
+- `hasMore`: Whether there are more messages to load (returns `false` before the first page is fetched)
+- `error`: Any error encountered during loading (of type `ErrorInfo`)
+- `refresh()`: A function to clear the error state and retry loading
+
+<Code>
+```jetpack
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material.Button
+import androidx.compose.material.CircularProgressIndicator
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import com.ably.chat.Room
+import com.ably.chat.annotations.ExperimentalChatApi
+import com.ably.chat.extensions.compose.collectAsPagingMessagesState
+
+@OptIn(ExperimentalChatApi::class)
+@Composable
+fun MessagesComponent(room: Room) {
+  val pagingMessagesState = room.collectAsPagingMessagesState(
+    scrollThreshold = 10,
+    fetchSize = 50,
+  )
+
+  // Handle error state
+  pagingMessagesState.error?.let { error ->
+    Text("Error: ${error.message}")
+    Button(onClick = { pagingMessagesState.refresh() }) {
+      Text("Retry")
+    }
+  }
+
+  LazyColumn(
+    reverseLayout = true,
+    state = pagingMessagesState.listState,
+  ) {
+    items(
+      items = pagingMessagesState.loaded,
+      key = { it.serial },
+    ) { message ->
+      Text("${message.clientId}: ${message.text}")
+    }
+
+    // Show loading indicator when fetching messages
+    if (pagingMessagesState.loading) {
+      item { CircularProgressIndicator() }
+    }
+  }
+}
+```
+</Code>
+</If>
diff --git a/src/pages/docs/chat/rooms/index.mdx b/src/pages/docs/chat/rooms/index.mdx
index 4e8a3bdfc0..0257ac84f7 100644
--- a/src/pages/docs/chat/rooms/index.mdx
+++ b/src/pages/docs/chat/rooms/index.mdx
@@ -21,8 +21,8 @@ The default 30-day retention period can be extended up to 365 days by [contactin
 
 Users send messages to a room and subscribe to the room in order to receive messages.
 
-<If lang="javascript,swift,kotlin">
-To get an instance of a chat room, use the <If lang="javascript">[`rooms.get()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Rooms.html#get)</If><If lang="swift">[`rooms.get()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/rooms/get%28named%3Aoptions%3A%29)</If><If lang="kotlin">[`rooms.get()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-rooms/get.html)</If> method. It will create a new room instance if one doesn't already exist, or return the existing one if it does.
+<If lang="javascript,swift,kotlin,jetpack">
+To get an instance of a chat room, use the <If lang="javascript">[`rooms.get()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Rooms.html#get)</If><If lang="swift">[`rooms.get()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/rooms/get%28named%3Aoptions%3A%29)</If><If lang="kotlin,jetpack">[`rooms.get()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-rooms/get.html)</If> method. It will create a new room instance if one doesn't already exist, or return the existing one if it does.
 </If>
 
 <If lang="react">
@@ -70,6 +70,10 @@ let room = try await chatClient.rooms.get(named: "basketball-stream", options: .
 ```kotlin
 val room = chatClient.rooms.get(roomId = "basketball-stream")
 ```
+
+```jetpack
+val room = chatClient.rooms.get(roomId = "basketball-stream")
+```
 </Code>
 
 <If lang="react">
@@ -79,9 +83,9 @@ If the value changes between re-renders then the room will be discarded and recr
 </Aside>
 </If>
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 
-When you create or retrieve a room using `rooms.get()`, you can provide custom configuration for some features for that room by passing a <If lang="javascript">[`RoomOptions`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.RoomOptions.html)</If><If lang="swift">[`RoomOptions`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomoptions)</If><If lang="kotlin">[`RoomOptions`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room-options/index.html)</If> object as the second argument. If you do not provide a `RoomOptions` object, the default settings will be used.
+When you create or retrieve a room using `rooms.get()`, you can provide custom configuration for some features for that room by passing a <If lang="javascript">[`RoomOptions`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.RoomOptions.html)</If><If lang="swift">[`RoomOptions`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomoptions)</If><If lang="kotlin,jetpack">[`RoomOptions`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room-options/index.html)</If> object as the second argument. If you do not provide a `RoomOptions` object, the default settings will be used.
 
 <Code>
 ```javascript
@@ -120,6 +124,20 @@ val room = chatClient.rooms.get(roomId = "basketball-stream") {
   }
 }
 ```
+
+```jetpack
+val room = chatClient.rooms.get(roomId = "basketball-stream") {
+  typing {
+    heartbeatThrottle = 5.seconds
+  }
+  presence {
+    enableEvents = true
+  }
+  occupancy {
+    enableEvents = true
+  }
+}
+```
 </Code>
 
 The details of the options available to each feature are documented on their respective pages:
@@ -138,8 +156,8 @@ Releasing a room allows the underlying resources to be garbage collected or rele
 
 Releasing a room may be optional for many applications. If you have multiple transient rooms, such as in the case of a 1:1 support chat, then it may be more beneficial. Also, proactively disconnecting rather than waiting for the standard two-minute timeout can help reduce costs and improve performance.
 
-<If lang="javascript,swift,kotlin">
-Once <If lang="javascript">[`rooms.release()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Rooms.html#release)</If><If lang="swift">[`rooms.release()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/rooms/release%28named%3A%29)</If><If lang="kotlin">[`rooms.release()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-rooms/release.html)</If> has been called, the room will be unusable and a new instance will need to be created using [`rooms.get()`](#create) if you want to reuse it.
+<If lang="javascript,swift,kotlin,jetpack">
+Once <If lang="javascript">[`rooms.release()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Rooms.html#release)</If><If lang="swift">[`rooms.release()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/rooms/release%28named%3A%29)</If><If lang="kotlin,jetpack">[`rooms.release()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-rooms/release.html)</If> has been called, the room will be unusable and a new instance will need to be created using [`rooms.get()`](#create) if you want to reuse it.
 
 <Code>
 ```javascript
@@ -153,6 +171,10 @@ try await rooms.release(named: "basketball-stream")
 ```kotlin
 rooms.release("basketball-stream")
 ```
+
+```jetpack
+rooms.release("basketball-stream")
+```
 </Code>
 </If>
 
@@ -168,10 +190,10 @@ By default the `ChatRoomProvider` will automatically call [`release()`](https://
 
 To start receiving messages and events from a room, you need to attach to it. Attaching to a room tells Ably to start streaming messages to the client, and ensures that events are not missed in case of temporary network interruptions.
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 Once an instance of a room has been created using `rooms.get()`, clients attach to it to start receiving messages and events from the room.
 
-Use the <If lang="javascript">[`attach()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Room.html#attach)</If><If lang="swift">[`attach()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/room/attach%28%29)</If><If lang="kotlin">[`attach()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room/attach.html)</If> method on a room to attach to it:
+Use the <If lang="javascript">[`attach()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Room.html#attach)</If><If lang="swift">[`attach()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/room/attach%28%29)</If><If lang="kotlin,jetpack">[`attach()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room/attach.html)</If> method on a room to attach to it:
 </If>
 
 <If lang="react">
@@ -203,6 +225,10 @@ try await room.attach()
 ```kotlin
 room.attach()
 ```
+
+```jetpack
+room.attach()
+```
 </Code>
 
 As soon as a client is attached to a room, Ably will begin streaming messages and events to them. To receive the messages and events in your application code, you need to add listeners to the events that you are interested in by subscribing, for example using the [`messages.subscribe()`](/docs/chat/rooms/messages#subscribe) method. Add listeners before attaching to avoid missing any messages or events.
@@ -215,8 +241,8 @@ As soon as a client is attached to a room, Ably will begin streaming messages an
 
 ### Detach from a room <a id="detach"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`detach()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Room.html#detach)</If><If lang="swift">[`detach()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/room/detach%28%29)</If><If lang="kotlin">[`detach()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room/detach.html)</If> method on a room to detach from it and stop receiving messages and events:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`detach()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Room.html#detach)</If><If lang="swift">[`detach()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/room/detach%28%29)</If><If lang="kotlin,jetpack">[`detach()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room/detach.html)</If> method on a room to detach from it and stop receiving messages and events:
 
 <Code>
 ```javascript
@@ -230,6 +256,10 @@ try await room.detach()
 ```kotlin
 room.detach()
 ```
+
+```jetpack
+room.detach()
+```
 </Code>
 </If>
 
@@ -258,8 +288,8 @@ A room can have any of the following statuses:
 | suspended | The room, having previously been attached, has lost continuity. This is normally due to the client being disconnected from Ably for more than two minutes. The client will automatically attempt to reattach as soon as connectivity is restored. |
 | failed | An indefinite failure condition. This status is entered if an error has been received from Ably, such as an attempt to attach without the necessary access rights. |
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`status`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.RoomStatus.html#status)</If><If lang="swift">[`status`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomstatus)</If><If lang="kotlin">[`status`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room/status.html)</If> property to check which status a room is currently in:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`status`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.RoomStatus.html#status)</If><If lang="swift">[`status`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomstatus)</If><If lang="kotlin,jetpack">[`status`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room/status.html)</If> property to check which status a room is currently in:
 </If>
 
 <If lang="react">
@@ -300,12 +330,21 @@ let status = room.status
 ```kotlin
 val status = room.status
 ```
+
+```jetpack
+val status = room.status
+```
 </Code>
 
 <If lang="javascript,swift,kotlin">
 You can also subscribe to room status updates by registering a listener. An event will be emitted whenever the status of the room changes.
 
 Use the <If lang="javascript">[`room.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Room.html#onStatusChange)</If><If lang="swift">[`room.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/room/onstatuschange%28%29-s9g)</If><If lang="kotlin">[`room.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room/on-status-change.html)</If> method in a room to register a listener for status change updates:
+</If>
+
+<If lang="jetpack">
+Use the [`collectAsStatus()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/jetpack/chat-extensions-compose/com.ably.chat.extensions.compose/collect-as-status.html) extension function to observe room status changes reactively in Jetpack Compose:
+</If>
 
 <Code>
 ```javascript
@@ -325,8 +364,25 @@ val (off) = room.onStatusChange { statusChange: RoomStatusChange ->
     println(statusChange.toString())
 }
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.extensions.compose.collectAsStatus
+
+@Composable
+fun MyComponent(room: Room) {
+  val roomStatus by room.collectAsStatus()
+
+  LaunchedEffect(roomStatus) {
+    println("Room status changed to: $roomStatus")
+  }
+
+  Text("Room status: $roomStatus")
+}
+```
 </Code>
-</If>
 
 <If lang="javascript,kotlin">
 Use the `off()` function returned in the `onStatusChange()` response to remove a room status listener:
diff --git a/src/pages/docs/chat/rooms/message-reactions.mdx b/src/pages/docs/chat/rooms/message-reactions.mdx
index 961e129af3..cc4a81f0d4 100644
--- a/src/pages/docs/chat/rooms/message-reactions.mdx
+++ b/src/pages/docs/chat/rooms/message-reactions.mdx
@@ -23,7 +23,7 @@ Note that if sending two identical reactions of type `Distinct`, the second one
 
 ### Configure the default reaction type <a id="default-type"/>
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 The default reaction type can be configured at room-level by passing `RoomOptions` when calling `rooms.get`. If nothing is set, the default is `Distinct`.
 </If>
 
@@ -59,6 +59,14 @@ val room = ablyChatClient.rooms.get("room1") {
 }
 ```
 
+```jetpack
+val room = ablyChatClient.rooms.get("room1") {
+    messages {
+        defaultMessageReactionType = MessageReactionType.Unique
+    }
+}
+```
+
 ```react
 import { MessageReactionType } from '@ably/chat';
 import { ChatRoomProvider } from '@ably/chat/react';
@@ -81,7 +89,7 @@ const MyComponent = () => {
 
 ## Sending a message reaction <a id="sending-reactions"/>
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 To send a message reaction use `room.messages.reactions.send(message, params)`. This method takes the following parameters:
 * `message` - The message to send the reaction to. Can be either a Message object or a string containing the message serial.
 * `params` - Set the `name`, and optionally override the `type` or set a `count`.
@@ -145,8 +153,8 @@ await room.messages.reactions.send(forMessageWithSerial: message.serial, params:
 room.messages.reactions.send(message, name = "👍")
 
 // The reaction can be anything, not just UTF-8 emojis:
-room.messages.reactions.send(message, name = ":like:"))
-room.messages.reactions.send(message, name = "+1"))
+room.messages.reactions.send(message, name = ":like:")
+room.messages.reactions.send(message, name = "+1")
 
 // Send a :love: reaction using the Unique type
 room.messages.reactions.send(message,
@@ -162,6 +170,43 @@ room.messages.reactions.send(message,
 )
 ```
 
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Message
+import com.ably.chat.MessageReactionType
+import com.ably.chat.Room
+import kotlinx.coroutines.launch
+
+@Composable
+fun SendMessageReactionComponent(room: Room, message: Message) {
+  val coroutineScope = rememberCoroutineScope()
+
+  Button(onClick = {
+    coroutineScope.launch {
+      // Send a 👍 reaction using the default type
+      room.messages.reactions.send(message, name = "👍")
+    }
+  }) {
+    Text("Send 👍")
+  }
+
+  Button(onClick = {
+    coroutineScope.launch {
+      // Send a ❤️ reaction with count 100 using the Multiple type
+      room.messages.reactions.send(
+        message,
+        name = "❤️",
+        type = MessageReactionType.Multiple,
+        count = 100,
+      )
+    }
+  }) {
+    Text("Send ❤️ x100")
+  }
+}
+```
+
 ```react
 import { MessageReactionType } from '@ably/chat';
 import { useMessages } from '@ably/chat/react';
@@ -210,7 +255,7 @@ The `annotation-publish` capability is required for sending reactions.
 
 ## Removing a message reaction <a id="removing-reactions"/>
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 To remove a message reaction use `room.messages.reactions.delete(message, params)`. This method takes the following parameters:
 * `message` - The message to remove the reaction from. This can be a Message object, or just the string serial.
 * `params` - Set the `name`, and optionally override the `type` or set a `count`.
@@ -277,6 +322,43 @@ const MyComponent = () => {
   );
 };
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Message
+import com.ably.chat.MessageReactionType
+import com.ably.chat.Room
+import kotlinx.coroutines.launch
+
+@Composable
+fun RemoveMessageReactionComponent(room: Room, message: Message) {
+  val coroutineScope = rememberCoroutineScope()
+
+  Button(onClick = {
+    coroutineScope.launch {
+      // Remove a 👍 reaction using the default type
+      room.messages.reactions.delete(message, name = "👍")
+    }
+  }) {
+    Text("Remove 👍")
+  }
+
+  Button(onClick = {
+    coroutineScope.launch {
+      // Remove a ❤️ reaction with count 50 using the Multiple type
+      room.messages.reactions.delete(
+        message,
+        name = "❤️",
+        type = MessageReactionType.Multiple,
+        count = 50,
+      )
+    }
+  }) {
+    Text("Remove ❤️ x50")
+  }
+}
+```
 </Code>
 
 ## Messages and reactions <a id="messages-and-reactions"/>
@@ -343,6 +425,96 @@ interface Message {
     }
 }
 ```
+
+```swift
+struct Message {
+    // ... (other fields omitted)
+    var reactions: MessageReactionSummary
+}
+
+struct MessageReactionSummary {
+    var unique: [String: ClientIDList]
+    var distinct: [String: ClientIDList]
+    var multiple: [String: ClientIDCounts]
+}
+
+// example (in real use, it is unlikely that all reaction types are present):
+// ... other message fields omitted
+reactions: MessageReactionSummary(
+    unique: [
+        "👍": ClientIDList(total: 2, clientIDs: ["clientA", "clientB"], clipped: false),
+        "❤️": ClientIDList(total: 1, clientIDs: ["clientC"], clipped: false),
+    ],
+    distinct: [
+        "👍": ClientIDList(total: 2, clientIDs: ["clientA", "clientB"], clipped: false),
+        "❤️": ClientIDList(total: 1, clientIDs: ["clientA"], clipped: false),
+    ],
+    multiple: [
+        "👍": ClientIDCounts(total: 10, clientIDs: ["clientA": 7, "clientB": 3], totalUnidentified: 0, clipped: false, totalClientIDs: 2),
+        "❤️": ClientIDCounts(total: 100, clientIDs: ["clientA": 100], totalUnidentified: 0, clipped: false, totalClientIDs: 1),
+    ]
+)
+```
+
+```kotlin
+interface Message {
+    // ... (other fields omitted)
+    val reactions: MessageReactionSummary
+}
+
+interface MessageReactionSummary {
+    val unique: Map<String, SummaryClientIdList>
+    val distinct: Map<String, SummaryClientIdList>
+    val multiple: Map<String, SummaryClientIdCounts>
+}
+
+// example (in real use, it is unlikely that all reaction types are present):
+// ... other message fields omitted
+reactions = MessageReactionSummary(
+    unique = mapOf(
+        "👍" to SummaryClientIdList(total = 2, clientIds = listOf("clientA", "clientB"), clipped = false),
+        "❤️" to SummaryClientIdList(total = 1, clientIds = listOf("clientC"), clipped = false),
+    ),
+    distinct = mapOf(
+        "👍" to SummaryClientIdList(total = 2, clientIds = listOf("clientA", "clientB"), clipped = false),
+        "❤️" to SummaryClientIdList(total = 1, clientIds = listOf("clientA"), clipped = false),
+    ),
+    multiple = mapOf(
+        "👍" to SummaryClientIdCounts(total = 10, clientIds = mapOf("clientA" to 7, "clientB" to 3), totalUnidentified = 0, clipped = false, totalClientIds = 2),
+        "❤️" to SummaryClientIdCounts(total = 100, clientIds = mapOf("clientA" to 100), totalUnidentified = 0, clipped = false, totalClientIds = 1),
+    )
+)
+```
+
+```jetpack
+interface Message {
+    // ... (other fields omitted)
+    val reactions: MessageReactionSummary
+}
+
+interface MessageReactionSummary {
+    val unique: Map<String, SummaryClientIdList>
+    val distinct: Map<String, SummaryClientIdList>
+    val multiple: Map<String, SummaryClientIdCounts>
+}
+
+// example (in real use, it is unlikely that all reaction types are present):
+// ... other message fields omitted
+reactions = MessageReactionSummary(
+    unique = mapOf(
+        "👍" to SummaryClientIdList(total = 2, clientIds = listOf("clientA", "clientB"), clipped = false),
+        "❤️" to SummaryClientIdList(total = 1, clientIds = listOf("clientC"), clipped = false),
+    ),
+    distinct = mapOf(
+        "👍" to SummaryClientIdList(total = 2, clientIds = listOf("clientA", "clientB"), clipped = false),
+        "❤️" to SummaryClientIdList(total = 1, clientIds = listOf("clientA"), clipped = false),
+    ),
+    multiple = mapOf(
+        "👍" to SummaryClientIdCounts(total = 10, clientIds = mapOf("clientA" to 7, "clientB" to 3), totalUnidentified = 0, clipped = false, totalClientIds = 2),
+        "❤️" to SummaryClientIdCounts(total = 100, clientIds = mapOf("clientA" to 100), totalUnidentified = 0, clipped = false, totalClientIds = 1),
+    )
+)
+```
 </Code>
 
 All reaction types are always available via `Message.reactions`, regardless of the default reaction type configured via room options.
@@ -354,10 +526,14 @@ Always call `Message.with(event)` when applying message events and reaction even
 
 ## Subscribing to message reactions <a id="subscribe"/>
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 Ably generates a summary (aggregate) of the reactions for each message and for each reaction type. For displaying accurate counts for message reactions, subscribe to changes in the message summary.
 </If>
 
+<If lang="jetpack">
+Use the [`reactions.asFlow()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/as-flow.html) to receive new message reactions:
+</If>
+
 <If lang="react">
 Subscribe to message reactions with the [`useMessages`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/functions/chat-react.useMessages.html) hook. Supply a `reactionsListener` to receive message reaction summary events. Ably generates a summary (aggregate) of the reactions for each message and for each reaction type. For displaying accurate counts for message reactions, subscribe to changes in the message summary.
 </If>
@@ -381,6 +557,20 @@ room.messages.reactions.subscribe { event ->
 }
 ```
 
+```jetpack
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+
+@Composable
+fun SubscribeToReactionsComponent(room: Room) {
+  LaunchedEffect(room) {
+    room.messages.reactions.asFlow().collect { event ->
+      println("received reactions summary event: $event")
+    }
+  }
+}
+```
+
 ```react
 import { useMessages } from '@ably/chat/react';
 
@@ -454,6 +644,36 @@ room.messages.reactions.subscribe { event ->
 }
 ```
 
+```jetpack
+import androidx.compose.runtime.*
+import com.ably.chat.Message
+import com.ably.chat.Room
+
+@Composable
+fun ReactionsWithMessagesComponent(room: Room) {
+  var messages by remember { mutableStateOf<List<Message>>(emptyList()) }
+
+  LaunchedEffect(room) {
+    // init messages
+    messages = room.messages.history(limit = 50).items
+  }
+
+  LaunchedEffect(room) {
+    // subscribe to message reactions summary events
+    room.messages.reactions.asFlow().collect { event ->
+      // find the relevant message (in practice: use binary search or a map for lookups)
+      val idx = messages.indexOfLast { msg -> msg.serial == event.messageSerial }
+      if (idx != -1) {
+        // update message
+        messages = messages.toMutableList().apply {
+          this[idx] = this[idx].with(event)
+        }
+      }
+    }
+  }
+}
+```
+
 ```react
 import { useState, useEffect } from 'react';
 import { useMessages, Message } from '@ably/chat/react';
@@ -549,6 +769,14 @@ val room = ablyChatClient.rooms.get("room1") {
 }
 ```
 
+```jetpack
+val room = ablyChatClient.rooms.get("room1") {
+    messages {
+        rawMessageReactions = true
+    }
+}
+```
+
 ```react
 import { ChatRoomProvider } from '@ably/chat/react';
 
@@ -568,7 +796,7 @@ const MyComponent = () => {
 ```
 </Code>
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 Then you can receive raw reactions using the `room.messages.reactions.subscribeRaw()` method:
 </If>
 
@@ -607,6 +835,29 @@ room.messages.reactions.subscribeRaw { event ->
 }
 ```
 
+```jetpack
+import androidx.compose.runtime.*
+import com.ably.chat.MessageReactionEventType
+import com.ably.chat.Room
+
+@Composable
+fun SubscribeToRawReactionsComponent(room: Room) {
+  DisposableEffect(room) {
+    val (unsubscribe) = room.messages.reactions.subscribeRaw { event ->
+      if (event.type == MessageReactionEventType.Create) {
+        println("new reaction: ${event.reaction}")
+      } else if (event.type == MessageReactionEventType.Delete) {
+        println("reaction removed: ${event.reaction}")
+      }
+    }
+
+    onDispose {
+      unsubscribe()
+    }
+  }
+}
+```
+
 ```react
 import { useMessages } from '@ably/chat/react';
 import { MessageReactionEventType } from '@ably/chat';
diff --git a/src/pages/docs/chat/rooms/messages.mdx b/src/pages/docs/chat/rooms/messages.mdx
index 1b85ca775c..3f19022a5f 100644
--- a/src/pages/docs/chat/rooms/messages.mdx
+++ b/src/pages/docs/chat/rooms/messages.mdx
@@ -17,6 +17,10 @@ A user can also update or delete a message, all users that are subscribed to the
 Subscribe to receive messages in a room by registering a listener. Use the <If lang="javascript">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#subscribe)</If><If lang="swift">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/subscribe%28%29-360z1)</If><If lang="kotlin">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/subscribe.html)</If> method in a room to receive all messages that are sent to it:
 </If>
 
+<If lang="jetpack">
+You can use [`messages.asFlow()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/as-flow.html) to receive new messages:
+</If>
+
 <If lang="react">
 Subscribe to messages with the [`useMessages`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/functions/chat-react.useMessages.html) hook. Supply a listener and the hook will automatically subscribe to message events sent to the room. As long as a defined value is provided, the subscription will persist across renders. If the listener value is undefined, the subscription will be removed until it becomes defined again.
 
@@ -57,6 +61,21 @@ val subscription = room.messages.subscribe { messageEvent: ChatMessageEvent ->
     println(messageEvent.message.toString())
 }
 ```
+
+```jetpack
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.asFlow
+
+@Composable
+fun SimpleMessagesComponent(room: Room) {
+  LaunchedEffect(room) {
+    room.messages.asFlow().collect { event ->
+      println("Received message: ${event.message}")
+    }
+  }
+}
+```
 </Code>
 
 ### Message structure <a id="structure"/>
@@ -107,6 +126,10 @@ See [below](#global-ordering) for more information on how to apply deterministic
 Use the `unsubscribe()` function returned in the `subscribe()` response to remove a chat message listener:
 </If>
 
+<If lang="jetpack">
+`messages.asFlow()` handles lifecycle and cleanup automatically.
+</If>
+
 <If lang="swift">
 You don't need to handle removing listeners, as this is done automatically by the SDK.
 </If>
@@ -145,8 +168,8 @@ The [`detach()`](/docs/chat/rooms#detach) method detaches a user from the room.
 
 ## Send a message <a id="send"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`messages.send()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#send)</If><If lang="swift">[`messages.send()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomreactions/send%28withparams%3A%29)</If><If lang="kotlin">[`messages.send()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/send.html)</If> method to send a message in a chat room. All users that are "subscribed](subscribe to messages on that room will receive it:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`messages.send()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#send)</If><If lang="swift">[`messages.send()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomreactions/send%28withparams%3A%29)</If><If lang="kotlin,jetpack">[`messages.send()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/send.html)</If> method to send a message in a chat room. All users that are [subscribed](#subscribe) to messages on that room will receive it:
 </If>
 
 <If lang="react">
@@ -183,12 +206,32 @@ let message = try await room.messages.send(params: .init(text: "hello"))
 ```kotlin
 room.messages.send(text = "hello")
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import kotlinx.coroutines.launch
+
+@Composable
+fun MyComponent(room: Room) {
+  val coroutineScope = rememberCoroutineScope()
+
+  Button(onClick = {
+    coroutineScope.launch {
+      room.messages.send(text = "hello")
+    }
+  }) {
+    Text("Send Message")
+  }
+}
+```
 </Code>
 
 ## Get a single message <a id="get-by-serial"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`messages.get()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#get)</If><If lang="swift">[`messages.get()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/get%28withserial:%29)</If><If lang="kotlin">[`messages.get()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/get.html)</If> method to get a message in a chat room.
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`messages.get()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#get)</If><If lang="swift">[`messages.get()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/get%28withserial:%29)</If><If lang="kotlin,jetpack">[`messages.get()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/get.html)</If> method to get a message in a chat room using message serial.
 </If>
 
 <If lang="react">
@@ -200,14 +243,6 @@ Use the [`getMessage()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/type
 await room.messages.get('01726232498871-001@abcdefghij:001');
 ```
 
-```kotlin
-val message = room.messages.get("01726232498871-001@abcdefghij:001")
-```
-
-```swift
-let message = try await room.messages.get(withSerial: "01726232498871-001@abcdefghij:001")
-```
-
 ```react
 import { useMessages } from '@ably/chat/react';
 
@@ -225,14 +260,26 @@ const MyComponent = () => {
   );
 };
 ```
+
+```swift
+let message = try await room.messages.get(withSerial: "01726232498871-001@abcdefghij:001")
+```
+
+```kotlin
+val message = room.messages.get("01726232498871-001@abcdefghij:001")
+```
+
+```jetpack
+val message = room.messages.get("01726232498871-001@abcdefghij:001")
+```
 </Code>
 
 
 
 ## Update a message <a id="update"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`messages.update()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#update)</If><If lang="swift">[`messages.update()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/update%28withserial:params:details:%29)</If><If lang="kotlin">[`messages.update()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/update.html)</If> method to update a message in a chat room. All users that are [subscribed](#subscribe) to messages on that room will receive the update:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`messages.update()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#update)</If><If lang="swift">[`messages.update()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/update%28withserial:params:details:%29)</If><If lang="kotlin,jetpack">[`messages.update()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/update.html)</If> method to update a message in a chat room. All users that are [subscribed](#subscribe) to messages on that room will receive the update:
 </If>
 
 <If lang="react">
@@ -288,12 +335,39 @@ val updatedMessage = room.messages.update(
   operationDescription = "Message update by user",
 )
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Message
+import com.ably.chat.Room
+import com.ably.chat.copy
+import com.ably.chat.update
+import kotlinx.coroutines.launch
+
+@Composable
+fun MyComponent(room: Room) {
+  val coroutineScope = rememberCoroutineScope()
+  val originalMessage: Message // assume this is available
+
+  Button(onClick = {
+    coroutineScope.launch {
+      room.messages.update(
+        originalMessage.copy(text = "my updated text"),
+        operationDescription = "Message update by user",
+      )
+    }
+  }) {
+    Text("Update Message")
+  }
+}
+```
 </Code>
 
 ### Filter for updates <a id="filter-updates"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#subscribe)</If><If lang="swift">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/subscribe%28%29-8jolq)</If><If lang="kotlin">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/subscribe.html)</If> method to receive messages in a room. To filter for updated messages, provide a listener that checks the <If lang="javascript,kotlin">`type`</If><If lang="swift">`action`</If> property of the message event:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#subscribe)</If><If lang="swift">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/subscribe%28%29-8jolq)</If><If lang="kotlin,jetpack">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/subscribe.html)</If> method to receive messages in a room. To filter for updated messages, provide a listener that checks the <If lang="javascript,kotlin,jetpack">`type`</If><If lang="swift">`action`</If> property of the message event:
 </If>
 
 <If lang="react">
@@ -383,6 +457,40 @@ val messagesSubscription = room.messages.subscribe { event ->
   }
 }
 ```
+
+```jetpack
+import androidx.compose.runtime.*
+import com.ably.chat.ChatMessageEventType
+import com.ably.chat.Message
+import com.ably.chat.Room
+import com.ably.chat.asFlow
+
+@Composable
+fun MyComponent(room: Room) {
+  var myMessageList by remember { mutableStateOf<List<Message>>(emptyList()) }
+
+  LaunchedEffect(room) {
+    room.messages.asFlow().collect { event ->
+      when (event.type) {
+        ChatMessageEventType.Created -> {
+          myMessageList = myMessageList + event.message
+        }
+        ChatMessageEventType.Updated -> {
+          myMessageList = myMessageList.map { message ->
+            if (message.serial == event.message.serial &&
+                event.message.version.serial > message.version.serial) {
+              event.message
+            } else {
+              message
+            }
+          }
+        }
+        else -> {}
+      }
+    }
+  }
+}
+```
 </Code>
 
 See [below](#global-ordering) for more information on how to deterministically apply ordering to update events in your application.
@@ -426,8 +534,8 @@ The updated message response is identical to the structure of a message, with th
 
 ## Delete a message <a id="delete"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`messages.delete()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#delete)</If><If lang="swift">[`messages.delete()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/delete%28withserial:details:%29)</If><If lang="kotlin">[`messages.delete()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/delete.html)</If> method to delete a message in a chat room. All users that are [subscribed](#subscribe) to messages on that room will receive the deletion:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`messages.delete()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#delete)</If><If lang="swift">[`messages.delete()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/delete%28withserial:details:%29)</If><If lang="kotlin,jetpack">[`messages.delete()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/delete.html)</If> method to delete a message in a chat room. All users that are [subscribed](#subscribe) to messages on that room will receive the deletion:
 </If>
 
 <If lang="react">
@@ -477,17 +585,43 @@ let deletedMessage = try await room.messages.delete(
 
 ```kotlin
 val messageToDelete: Message
-val deletedMessage = room().messages.delete(
+val deletedMessage = room.messages.delete(
   messageToDelete,
   operationDescription = "Message deleted by user",
 )
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Message
+import com.ably.chat.Room
+import com.ably.chat.delete
+import kotlinx.coroutines.launch
+
+@Composable
+fun MyComponent(room: Room) {
+  val coroutineScope = rememberCoroutineScope()
+  val messageToDelete: Message // assume this is available
+
+  Button(onClick = {
+    coroutineScope.launch {
+      room.messages.delete(
+        messageToDelete,
+        operationDescription = "Message deleted by user",
+      )
+    }
+  }) {
+    Text("Delete Message")
+  }
+}
+```
 </Code>
 
 ### Filter for deletes <a id="filter-deletes"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#subscribe)</If><If lang="swift">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/subscribe%28%29-8jolq)</If><If lang="kotlin">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/subscribe.html)</If> method to receive messages in a room. To filter for deleted messages, provide a listener that checks the <If lang="javascript,kotlin">`type`</If><If lang="swift">`action`</If> property of the message event:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#subscribe)</If><If lang="swift">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/subscribe%28%29-8jolq)</If><If lang="kotlin,jetpack">[`messages.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/subscribe.html)</If> method to receive messages in a room. To filter for deleted messages, provide a listener that checks the <If lang="javascript,kotlin,jetpack">`type`</If><If lang="swift">`action`</If> property of the message event:
 </If>
 
 <If lang="react">
@@ -577,6 +711,36 @@ val messagesSubscription = room.messages.subscribe { event ->
   }
 }
 ```
+
+```jetpack
+import androidx.compose.runtime.*
+import com.ably.chat.ChatMessageEventType
+import com.ably.chat.Message
+import com.ably.chat.Room
+import com.ably.chat.asFlow
+
+@Composable
+fun MyComponent(room: Room) {
+  var myMessageList by remember { mutableStateOf<List<Message>>(emptyList()) }
+
+  LaunchedEffect(room) {
+    room.messages.asFlow().collect { event ->
+      when (event.type) {
+        ChatMessageEventType.Created -> {
+          myMessageList = myMessageList + event.message
+        }
+        ChatMessageEventType.Deleted -> {
+          myMessageList = myMessageList.filterNot { message ->
+            message.serial == event.message.serial &&
+            event.message.version.serial > message.version.serial
+          }
+        }
+        else -> {}
+      }
+    }
+  }
+}
+```
 </Code>
 
 See [below](#global-ordering) for more information on how to deterministically apply ordering to delete events in your application.
diff --git a/src/pages/docs/chat/rooms/occupancy.mdx b/src/pages/docs/chat/rooms/occupancy.mdx
index fe7017b6ce..b789286436 100644
--- a/src/pages/docs/chat/rooms/occupancy.mdx
+++ b/src/pages/docs/chat/rooms/occupancy.mdx
@@ -15,6 +15,10 @@ Occupancy generates messages on any client entering/leaving a room, and so incre
 Subscribe to a room's occupancy by registering a listener. Occupancy events are emitted whenever the number of online users within a room changes. Use the <If lang="javascript">[`occupancy.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Occupancy.html#subscribe)</If><If lang="swift">[`occupancy.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/occupancy/subscribe%28%29-3loon)</If><If lang="kotlin">[`occupancy.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-occupancy/subscribe.html)</If> method in a room to receive updates:
 </If>
 
+<If lang="jetpack">
+Use the [`collectAsOccupancy()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/jetpack/chat-extensions-compose/com.ably.chat.extensions.compose/collect-as-occupancy.html) extension function to observe occupancy changes reactively in Jetpack Compose:
+</If>
+
 <If lang="react">
 Subscribe to a room's occupancy with the [`useOccupancy`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/functions/chat-react.useOccupancy.html) hook.
 </If>
@@ -58,6 +62,21 @@ val subscription = room.occupancy.subscribe { event: OccupancyEvent ->
     println("Number of members present is: ${event.occupancy.presenceMembers}")
 }
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.extensions.compose.collectAsOccupancy
+
+@Composable
+fun OccupancyComponent(room: Room) {
+  val occupancy by room.collectAsOccupancy()
+
+  Text("Number of users connected: ${occupancy.connections}")
+  Text("Number of members present: ${occupancy.presenceMembers}")
+}
+```
 </Code>
 
 <Aside data-type='note'>
@@ -82,7 +101,7 @@ The following is the structure of an occupancy event:
 </Code>
 </If>
 
-<If lang="swift,kotlin">
+<If lang="kotlin,swift,jetpack">
 <Code>
 ```json
 {
@@ -107,7 +126,7 @@ The following are the properties of an occupancy event:
 
 </If>
 
-<If lang="kotlin,swift">
+<If lang="kotlin,swift,jetpack">
 
 | Property | Description | Type |
 | -------- | ----------- | ---- |
@@ -127,6 +146,10 @@ A user is counted for every device that they are in the room with. For example,
 Use the `unsubscribe()` function returned in the `subscribe()` response to remove a room occupancy listener:
 </If>
 
+<If lang="jetpack">
+Jetpack Compose automatically handles lifecycle and cleanup when using `collectAsOccupancy()`.
+</If>
+
 <If lang="swift">
 You don't need to handle removing listeners, as this is done automatically by the SDK.
 </If>
@@ -163,9 +186,9 @@ unsubscribe()
 
 The latest occupancy received in realtime (the same mechanism that powers occupancy subscriptions) can be retrieved in a one-off call.
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 
-Use the <If lang="javascript">[`occupancy.current`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Occupancy.html#current)</If><If lang="swift">[`occupancy.current`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/occupancy/current)</If><If lang="kotlin">[`occupancy.current`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-occupancy/current.html)</If> property to retrieve the most recently received room occupancy:
+Use the <If lang="javascript">[`occupancy.current`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Occupancy.html#current)</If><If lang="swift">[`occupancy.current`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/occupancy/current)</If><If lang="kotlin,jetpack">[`occupancy.current`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-occupancy/current.html)</If> property to retrieve the most recently received room occupancy:
 
 <Code>
 ```javascript
@@ -179,6 +202,10 @@ let occupancy = room.occupancy.current
 ```kotlin
 val occupancy = room.occupancy.current
 ```
+
+```jetpack
+val occupancy = room.occupancy.current
+```
 </Code>
 </If>
 
@@ -207,10 +234,10 @@ The following are the properties of the occupancy data:
 
 ## Retrieve room occupancy
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 The occupancy of a room can be retrieved in one-off calls instead of subscribing to updates.
 
-Use the <If lang="javascript">[`occupancy.get()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Occupancy.html#get)</If><If lang="swift">[`occupancy.get()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/occupancy/get%28%29)</If><If lang="kotlin">[`occupancy.get()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-occupancy/get.html)</If> method to retrieve the occupancy of a room:
+Use the <If lang="javascript">[`occupancy.get()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Occupancy.html#get)</If><If lang="swift">[`occupancy.get()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/occupancy/get%28%29)</If><If lang="kotlin,jetpack">[`occupancy.get()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-occupancy/get.html)</If> method to retrieve the occupancy of a room:
 
 <Code>
 ```javascript
@@ -224,6 +251,10 @@ let occupancy = try await room.occupancy.get()
 ```kotlin
 val occupancy = room.occupancy.get()
 ```
+
+```jetpack
+val occupancy = room.occupancy.get()
+```
 </Code>
 </If>
 
diff --git a/src/pages/docs/chat/rooms/presence.mdx b/src/pages/docs/chat/rooms/presence.mdx
index 5af6cdece7..0380ac11b4 100644
--- a/src/pages/docs/chat/rooms/presence.mdx
+++ b/src/pages/docs/chat/rooms/presence.mdx
@@ -11,6 +11,10 @@ The presence feature of a chat room enables online users to advertise to others
 Subscribe to users' presence status by registering a listener. Presence events are emitted whenever a member enters or leaves the presence set, or updates their user data. Use the <If lang="javascript">[`presence.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#subscribe)</If><If lang="swift">[`presence.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/subscribe%28_%3A%29)</If><If lang="kotlin">[`presence.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/subscribe.html)</If> method in a room to receive updates:
 </If>
 
+<If lang="jetpack">
+Use the [`collectAsPresenceMembers()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/jetpack/chat-extensions-compose/com.ably.chat.extensions.compose/collect-as-presence-members.html) extension function to observe user presence changes reactively in Jetpack Compose:
+</If>
+
 <If lang="react">
 Subscribe to users' presence status with the [`usePresenceListener`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/functions/chat-react.usePresenceListener.html) hook. Supply an optional listener to receive presence status updates, or use the [`presenceData`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-react.UsePresenceListenerResponse.html#presenceData) property returned by the hook.
 
@@ -60,8 +64,33 @@ for await event in presenceSubscription {
 ```
 
 ```kotlin
+import com.ably.chat.PresenceEventType
+import com.ably.chat.PresenceEvent
+
 val subscription = room.presence.subscribe { event: PresenceEvent ->
-    println("Presence event ${event.type} from ${event.member.clientId} with data: ${event.member.data}")
+    when (event.type) {
+        PresenceEventType.Enter -> println("${event.member.clientId} entered")
+        PresenceEventType.Leave -> println("${event.member.clientId} left")
+        PresenceEventType.Update -> println("${event.member.clientId} updated: ${event.member.data}")
+        PresenceEventType.Present -> println("${event.member.clientId} already present")
+    }
+}
+```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.extensions.compose.collectAsPresenceMembers
+
+@Composable
+fun PresenceComponent(room: Room) {
+  val presenceMembers by room.collectAsPresenceMembers()
+
+  Text("Present members: ${presenceMembers.size}")
+  presenceMembers.forEach { member ->
+    Text("${member.clientId} is present with data: ${member.data}")
+  }
 }
 ```
 </Code>
@@ -86,6 +115,10 @@ The following are the properties of a presence event:
 Use the `unsubscribe()` function returned in the `subscribe()` response to remove a presence listener:
 </If>
 
+<If lang="jetpack">
+Jetpack Compose automatically handles lifecycle and cleanup when using `collectAsPresenceMembers()`.
+</If>
+
 <If lang="swift">
 You don't need to handle removing listeners, as this is done automatically by the SDK.
 </If>
@@ -126,8 +159,8 @@ Users can enter and leave the presence set of a room to indicate when they are o
 Users must be identified to enter into the presence set. This means that they must set a `clientId` when [instantiating their client](/docs/chat/setup#instantiate).
 </Aside>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`presence.enter()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#enter)</If><If lang="swift">[`presence.enter()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/enter%28withdata%3A%29)</If><If lang="kotlin">[`presence.enter()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/enter.html)</If> method to indicate when a user joins a room. This will send a presence event to all users subscribed to presence indicating that a new member has joined the chat. You can also set an optional data field with information such as the status of a user:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`presence.enter()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#enter)</If><If lang="swift">[`presence.enter()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/enter%28withdata%3A%29)</If><If lang="kotlin,jetpack">[`presence.enter()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/enter.html)</If> method to indicate when a user joins a room. This will send a presence event to all users subscribed to presence indicating that a new member has joined the chat. You can also set an optional data field with information such as the status of a user:
 </If>
 
 <If lang="react">
@@ -176,10 +209,41 @@ room.presence.enter(
     },
 )
 ```
+
+```jetpack
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.RoomStatus
+import com.ably.chat.json.*
+
+@Composable
+fun EnterPresenceComponent(room: Room) {
+  LaunchedEffect(room) {
+    // Ensure room is attached before entering presence
+    if (room.status != RoomStatus.Attached) {
+      room.attach()
+    }
+
+    room.presence.enter(
+      jsonObject {
+        put("status", "Online")
+      }
+    )
+  }
+
+  // Leave presence when component is disposed
+  DisposableEffect(room) {
+    onDispose {
+      // Note: Consider using a coroutine scope for leave()
+      // as DisposableEffect doesn't support suspend functions directly
+    }
+  }
+}
+```
 </Code>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`presence.update()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#update)</If><If lang="swift">[`presence.update()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/update%28withdata%3A%29)</If><If lang="kotlin">[`presence.update()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/update.html)</If> method when a user wants to update their data, such as an update to their status, or to indicate that they're raising their hand. Updates will send a presence event to all users subscribed to presence:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`presence.update()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#update)</If><If lang="swift">[`presence.update()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/update%28withdata%3A%29)</If><If lang="kotlin,jetpack">[`presence.update()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/update.html)</If> method when a user wants to update their data, such as an update to their status, or to indicate that they're raising their hand. Updates will send a presence event to all users subscribed to presence:
 </If>
 
 <If lang="react">
@@ -227,10 +291,35 @@ room.presence.update(
     },
 )
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.json.*
+import kotlinx.coroutines.launch
+
+@Composable
+fun UpdatePresenceComponent(room: Room) {
+  val coroutineScope = rememberCoroutineScope()
+
+  Button(onClick = {
+    coroutineScope.launch {
+      room.presence.update(
+        jsonObject {
+          put("status", "Busy")
+        }
+      )
+    }
+  }) {
+    Text("Set Status to Busy")
+  }
+}
+```
 </Code>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`presence.leave()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#leave)</If><If lang="swift">[`presence.leave()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/leave%28withdata%3A%29)</If><If lang="kotlin">[`presence.leave()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/leave.html)</If> method to explicitly remove a user from the presence set. This will send a presence event to all users subscribed to presence. You can also set an optional data field such as setting a status of 'Back later'.
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`presence.leave()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#leave)</If><If lang="swift">[`presence.leave()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/leave%28withdata%3A%29)</If><If lang="kotlin,jetpack">[`presence.leave()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/leave.html)</If> method to explicitly remove a user from the presence set. This will send a presence event to all users subscribed to presence. You can also set an optional data field such as setting a status of 'Back later'.
 </If>
 
 <If lang="react">
@@ -278,6 +367,31 @@ room.presence.leave(
     },
 )
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.json.*
+import kotlinx.coroutines.launch
+
+@Composable
+fun LeavePresenceComponent(room: Room) {
+  val coroutineScope = rememberCoroutineScope()
+
+  Button(onClick = {
+    coroutineScope.launch {
+      room.presence.leave(
+        jsonObject {
+          put("status", "Be back later!")
+        }
+      )
+    }
+  }) {
+    Text("Leave Presence")
+  }
+}
+```
 </Code>
 
 When a user goes offline or closes their [connection](/docs/chat/connect), a leave event is also emitted and they are removed from the presence set.
@@ -350,10 +464,11 @@ The following options can be set when [creating a room](/docs/chat/rooms#create)
 
 ## Retrieve the presence set <a id="retrieve"/>
 
-<If lang="javascript,swift,kotlin">
+<If lang="javascript,swift,kotlin,jetpack">
 The online presence of users can be retrieved in one-off calls. This can be used to check the status of an individual user, or return the entire presence set as an array.
+The `presence.get()` method may return multiple entries for the same `clientId` if the user has multiple active connections or has reconnected. When displaying presence members in UI, consider deduplicating by unique `clientId` to avoid showing duplicate users.
 
-Use the <If lang="javascript">[`presence.get()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#get)</If><If lang="swift">[`presence.get()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/get%28%29)</If><If lang="kotlin">[`presence.get()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/get.html)</If> method to retrieve an array of all users currently entered into the presence set, or individual users:
+Use the <If lang="javascript">[`presence.get()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#get)</If><If lang="swift">[`presence.get()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/get%28%29)</If><If lang="kotlin,jetpack">[`presence.get()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/get.html)</If> method to retrieve an array of all users currently entered into the presence set, or individual users:
 
 <Code>
 ```javascript
@@ -376,12 +491,20 @@ let presentMember = try await room.presence.get(withParams: .init(clientID: "cle
 // Retrieve all users entered into presence as an array:
 val presentMembers = room.presence.get()
 
+// Retrieve the status of specific users by their clientId:
+val presentMember = room.presence.get(clientId = "clemons123")
+```
+
+```jetpack
+// Retrieve all users entered into presence as an array:
+val presentMembers = room.presence.get()
+
 // Retrieve the status of specific users by their clientId:
 val presentMember = room.presence.get(clientId = "clemons123")
 ```
 </Code>
 
-Alternatively, use the <If lang="javascript">[`presence.isUserPresent()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#isUserPresent)</If><If lang="swift">[`presence.isUserPresent()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/isuserpresent%28withclientid%3A%29)</If><If lang="kotlin">[`presence.isUserPresent()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/is-user-present.html)</If> method and pass in a user's `clientId` to check whether they are online or not. This will return a boolean:
+Alternatively, use the <If lang="javascript">[`presence.isUserPresent()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Presence.html#isUserPresent)</If><If lang="swift">[`presence.isUserPresent()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/presence/isuserpresent%28withclientid%3A%29)</If><If lang="kotlin,jetpack">[`presence.isUserPresent()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-presence/is-user-present.html)</If> method and pass in a user's `clientId` to check whether they are online or not. This will return a boolean:
 
 <Code>
 ```javascript
@@ -395,6 +518,10 @@ let isPresent = try await room.presence.isUserPresent(withClientID: "clemons123"
 ```kotlin
 val isPresent = room.presence.isUserPresent("client-id")
 ```
+
+```jetpack
+val isPresent = room.presence.isUserPresent("client-id")
+```
 </Code>
 </If>
 
diff --git a/src/pages/docs/chat/rooms/reactions.mdx b/src/pages/docs/chat/rooms/reactions.mdx
index e494ebc5e6..d33540480b 100644
--- a/src/pages/docs/chat/rooms/reactions.mdx
+++ b/src/pages/docs/chat/rooms/reactions.mdx
@@ -13,6 +13,10 @@ Room reactions are ephemeral and not stored or aggregated by Ably. The intention
 Subscribe to room reactions by registering a listener. Use the <If lang="javascript">[`reactions.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.RoomReactions.html#subscribe)</If><If lang="swift">[`reactions.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomreactions/subscribe%28%29-64gdf)</If><If lang="kotlin">[`reactions.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room-reactions/subscribe.html)</If> method in a room to receive reactions:
 </If>
 
+<If lang="jetpack">
+Use the [`reactions.asFlow()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/as-flow.html) to receive new room reactions:
+</If>
+
 <If lang="react">
 Subscribe to room reactions with the [`useRoomReactions`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/functions/chat-react.useRoomReactions.html) hook. Supply an optional listener to receive the room reactions.
 </If>
@@ -47,7 +51,22 @@ for await event in reactionSubscription {
 
 ```kotlin
 val subscription = room.reactions.subscribe { event: RoomReactionEvent ->
-    println("Received a reaciton of name ${event.reaction.name} with metadata ${event.reaction.metadata}")
+    println("Received a reaction of name ${event.reaction.name} with metadata ${event.reaction.metadata}")
+}
+```
+
+```jetpack
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.RoomReactionEvent
+
+@Composable
+fun RoomReactionsComponent(room: Room) {
+  LaunchedEffect(room) {
+    room.reactions.asFlow().collect { event: RoomReactionEvent ->
+      println("Received a reaction of name ${event.reaction.name} with metadata ${event.reaction.metadata}")
+    }
+  }
 }
 ```
 </Code>
@@ -73,6 +92,10 @@ The following are the properties of a room reaction event:
 Use the `unsubscribe()` function returned in the `subscribe()` response to remove a room reaction listener:
 </If>
 
+<If lang="jetpack">
+Jetpack Compose automatically handles lifecycle and cleanup when using `LaunchedEffect` with `asFlow`.
+</If>
+
 <If lang="swift">
 You don't need to handle removing listeners, as this is done automatically by the SDK.
 </If>
@@ -107,8 +130,8 @@ unsubscribe()
 
 ## Send a room reaction <a id="send"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`reactions.send()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.RoomReactions.html#send)</If><If lang="swift">[`reactions.send()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomreactions/send%28withparams%3A%29)</If><If lang="kotlin">[`reactions.send()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room-reactions/send.html)</If> method to send a room-level reaction. The most common way of using this method is to trigger it whenever a user clicks an emoji button in a room:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`reactions.send()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.RoomReactions.html#send)</If><If lang="swift">[`reactions.send()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomreactions/send%28withparams%3A%29)</If><If lang="kotlin,jetpack">[`reactions.send()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room-reactions/send.html)</If> method to send a room-level reaction. The most common way of using this method is to trigger it whenever a user clicks an emoji button in a room:
 </If>
 
 <If lang="react">
@@ -154,4 +177,38 @@ room.reactions.send(name = "heart", metadata = jsonObject {
   put("effect", "fireworks")
 })
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.json.*
+import kotlinx.coroutines.launch
+
+@Composable
+fun SendReactionComponent(room: Room) {
+  val coroutineScope = rememberCoroutineScope()
+
+  Button(onClick = {
+    coroutineScope.launch {
+      room.reactions.send(name = "like")
+    }
+  }) {
+    Text("Send Like")
+  }
+
+  Button(onClick = {
+    coroutineScope.launch {
+      room.reactions.send(
+        name = "heart",
+        metadata = jsonObject {
+          put("effect", "fireworks")
+        }
+      )
+    }
+  }) {
+    Text("Send Heart with Effect")
+  }
+}
+```
 </Code>
diff --git a/src/pages/docs/chat/rooms/typing.mdx b/src/pages/docs/chat/rooms/typing.mdx
index ec6b07adfd..428c605672 100644
--- a/src/pages/docs/chat/rooms/typing.mdx
+++ b/src/pages/docs/chat/rooms/typing.mdx
@@ -11,6 +11,10 @@ Typing indicators enable you to display which users are currently writing a mess
 Subscribe to typing events by registering a listener. Typing events can be emitted when a user starts typing, and when they stop typing. Use the <If lang="javascript">[`typing.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Typing.html#subscribe)</If><If lang="swift">[`typing.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/typing/subscribe%28%29-7uox7)</If><If lang="kotlin">[`typing.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-typing/subscribe.html)</If> method in a room to receive these updates:
 </If>
 
+<If lang="jetpack">
+Use the [`collectAsCurrentlyTyping()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/jetpack/chat-extensions-compose/com.ably.chat.extensions.compose/collect-as-currently-typing.html) extension function to observe typing changes reactively in Jetpack Compose:
+</If>
+
 <If lang="react">
 Subscribe to typing events with the [`useTyping`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/functions/chat-react.useTyping.html) hook. Supply an optional listener to receive the typing events, or use the [`currentlyTyping`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-react.UseTypingResponse.html#currentlyTyping) property returned by the hook to access the list of those users that are currently typing.
 </If>
@@ -55,6 +59,20 @@ val subscription = room.typing.subscribe { event: TypingSetEvent ->
     println("currently typing: ${event.currentlyTyping}")
 }
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import com.ably.chat.extensions.compose.collectAsCurrentlyTyping
+
+@Composable
+fun TypingComponent(room: Room) {
+  val currentlyTyping by room.collectAsCurrentlyTyping()
+
+  Text("Currently typing: ${currentlyTyping.joinToString(", ")}")
+}
+```
 </Code>
 
 ### Typing event structure <a id="structure"/>
@@ -95,6 +113,10 @@ You can use the size of the `currentlyTyping` set to decide whether to display i
 Use the `unsubscribe()` function returned in the `subscribe()` response to remove a typing listener:
 </If>
 
+<If lang="jetpack">
+Jetpack Compose automatically handles lifecycle and cleanup when using `collectAsCurrentlyTyping()`.
+</If>
+
 <If lang="swift">
 You don't need to handle removing listeners, as this is done automatically by the SDK.
 </If>
@@ -130,8 +152,8 @@ unsubscribe()
 
 ## Set typing status <a id="set"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`typing.keystroke()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Typing.html#keystroke)</If><If lang="swift">[`typing.keystroke()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/typing/keystroke%28%29)</If><If lang="kotlin">[`typing.keystroke()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-typing/keystroke.html)</If> method to emit a typing event with `type` set to `typing.started`.
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`typing.keystroke()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Typing.html#keystroke)</If><If lang="swift">[`typing.keystroke()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/typing/keystroke%28%29)</If><If lang="kotlin,jetpack">[`typing.keystroke()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-typing/keystroke.html)</If> method to emit a typing event with `type` set to `typing.started`.
 </If>
 
 <If lang="react">
@@ -169,10 +191,34 @@ try await room.typing.keystroke()
 ```kotlin
 room.typing.keystroke()
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import kotlinx.coroutines.launch
+
+@Composable
+fun TypingKeystrokeComponent(room: Room) {
+  val coroutineScope = rememberCoroutineScope()
+  var text by remember { mutableStateOf("") }
+
+  TextField(
+    value = text,
+    onValueChange = { newText ->
+      text = newText
+      coroutineScope.launch {
+        room.typing.keystroke()
+      }
+    },
+    label = { Text("Type a message") }
+  )
+}
+```
 </Code>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`stop()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Typing.html#stop)</If><If lang="swift">[`stop()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/typing/stop%28%29)</If><If lang="kotlin">[`stop()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-typing/stop.html)</If> method to emit a typing event with `type` set to `typing.stopped`.
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`stop()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Typing.html#stop)</If><If lang="swift">[`stop()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/typing/stop%28%29)</If><If lang="kotlin,jetpack">[`stop()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-typing/stop.html)</If> method to emit a typing event with `type` set to `typing.stopped`.
 </If>
 
 <If lang="react">
@@ -209,6 +255,26 @@ try await room.typing.stop()
 ```kotlin
 room.typing.stop()
 ```
+
+```jetpack
+import androidx.compose.material.*
+import androidx.compose.runtime.*
+import com.ably.chat.Room
+import kotlinx.coroutines.launch
+
+@Composable
+fun StopTypingComponent(room: Room) {
+  val coroutineScope = rememberCoroutineScope()
+
+  Button(onClick = {
+    coroutineScope.launch {
+      room.typing.stop()
+    }
+  }) {
+    Text("Stop Typing")
+  }
+}
+```
 </Code>
 
 ### Typing Event Frequency <a id="frequency"/>
@@ -249,8 +315,8 @@ All clients in a room must have the same timeout value configured. If not, typin
 
 ## Retrieve a list of users that are currently typing <a id="retrieve"/>
 
-<If lang="javascript,swift,kotlin">
-Use the <If lang="javascript">[`typing.current`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Typing.html#current)</If><If lang="swift">[`typing.current`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/typing/current)</If><If lang="kotlin">[`typing.current`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-typing/current.html)</If> property to retrieve a set of `clientId`s for all users that are currently typing in the room:
+<If lang="javascript,swift,kotlin,jetpack">
+Use the <If lang="javascript">[`typing.current`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Typing.html#current)</If><If lang="swift">[`typing.current`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/typing/current)</If><If lang="kotlin,jetpack">[`typing.current`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-typing/current.html)</If> property to retrieve a set of `clientId`s for all users that are currently typing in the room:
 </If>
 
 <Code>
@@ -265,6 +331,10 @@ let currentlyTypingClientIds = room.typing.current
 ```kotlin
 val currentlyTypingClientIds = room.typing.current
 ```
+
+```jetpack
+val currentlyTypingClientIds = room.typing.current
+```
 </Code>
 
 <If lang="react">
diff --git a/src/pages/docs/chat/setup.mdx b/src/pages/docs/chat/setup.mdx
index fdb0aafdaf..f5191b4706 100644
--- a/src/pages/docs/chat/setup.mdx
+++ b/src/pages/docs/chat/setup.mdx
@@ -115,14 +115,19 @@ import AblyChat
 </Code>
 </If>
 
-<If lang="kotlin">
+<If lang="kotlin,jetpack">
 ### Gradle <a id="gradle"/>
 
 The Ably Chat SDK is available on the Maven Central Repository. To include the dependency in your project, add the following to your `build.gradle.kts` file:
 
 <Code>
 ```kotlin
-  implementation("com.ably.chat:chat:1.0.0")
+  implementation("com.ably.chat:chat:1.1.0")
+```
+
+```jetpack
+implementation("com.ably.chat:chat:1.1.0")
+implementation("com.ably.chat:chat-extensions-compose:1.1.0")
 ```
 </Code>
 
@@ -130,7 +135,12 @@ For groovy:
 
 <Code>
 ```kotlin
-  implementation 'com.ably.chat:chat:1.0.0'
+  implementation 'com.ably.chat:chat:1.1.0'
+```
+
+```jetpack
+implementation 'com.ably.chat:chat:1.1.0'
+implementation 'com.ably.chat:chat-extensions-compose:1.1.0'
 ```
 </Code>
 </If>
@@ -186,6 +196,21 @@ val realtimeClient = AblyRealtime(
     },
 )
 
+val chatClient = ChatClient(realtimeClient)
+```
+
+```jetpack
+import com.ably.chat.ChatClient
+import io.ably.lib.realtime.AblyRealtime
+import io.ably.lib.types.ClientOptions
+
+val realtimeClient = AblyRealtime(
+    ClientOptions().apply {
+        key = "{{API_KEY}}"
+        clientId = "<clientId>"
+    },
+)
+
 val chatClient = ChatClient(realtimeClient)
 ```
 </Code>
@@ -214,7 +239,7 @@ Additional options can also be passed to the Chat client to customize the follow
 
 </If>
 
-<If lang="kotlin">
+<If lang="kotlin,jetpack">
 
 | Property | Description |
 | -------- | ----------- |
@@ -271,13 +296,26 @@ val chatClient = ChatClient(realtimeClient) {
   logLevel = LogLevel.Debug
 }
 ```
+
+```jetpack
+val realtimeClient = AblyRealtime(
+    ClientOptions().apply {
+        key = "{{API_KEY}}"
+        clientId = "<clientId>"
+    },
+)
+val chatClient = ChatClient(realtimeClient) {
+    logHandler = CustomLogHandler() // Implements com.ably.chat.LogHandler interface
+    logLevel = LogLevel.Debug
+}
+```
 </Code>
 
 <If lang="javascript,react">
 The `logHandler` property is your own function that will be called for each line of log output generated by the Chat SDK.
 </If>
 
-<If lang="swift,kotlin">
+<If lang="swift,kotlin,jetpack">
 The `logHandler` property is your custom `LogHandler` implementation that will be called for each line of log output generated by the Chat SDK.
 </If>
 
diff --git a/yarn.lock b/yarn.lock
index 5bcab424cf..77f3982a0d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7,10 +7,10 @@
   resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"
   integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
 
-"@ably/ui@17.9.16":
-  version "17.9.16"
-  resolved "https://registry.yarnpkg.com/@ably/ui/-/ui-17.9.16.tgz#609550308d65081e43ffe19787db4a2a10079dc9"
-  integrity sha512-Me3ywixw2VvYbw/PexPIRHKgL89AzPgDE4KzfFseMYK9DuFV/4plmsnWYWRb08pXKwYrna7JtqmaYYZA8zYVXQ==
+"@ably/ui@17.11.4":
+  version "17.11.4"
+  resolved "https://registry.yarnpkg.com/@ably/ui/-/ui-17.11.4.tgz#a2b763b201d0bbfae51dab90ee1d8797d3772536"
+  integrity sha512-0d+sdGW+wiRdNDWBKqk7eea1efstku5Mwu03pN0Ej7jNJEMAh4e1rDBirJvq1MENDzGloTxF62GNbrSAXD9NVw==
   dependencies:
     "@heroicons/react" "^2.2.0"
     "@radix-ui/react-accordion" "^1.2.1"
@@ -26,7 +26,7 @@
     embla-carousel "^8.6.0"
     embla-carousel-autoplay "^8.6.0"
     embla-carousel-react "^8.6.0"
-    es-toolkit "^1.39.10"
+    es-toolkit "^1.43.0"
     highlight.js "^11.11.1"
     highlightjs-curl "^1.3.0"
     js-cookie "^3.0.5"
@@ -7783,10 +7783,10 @@ es-to-primitive@^1.3.0:
     is-date-object "^1.0.5"
     is-symbol "^1.0.4"
 
-es-toolkit@^1.39.10:
-  version "1.39.10"
-  resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.39.10.tgz#513407af73e79f9940e7ec7650f2e6dceeaf1d81"
-  integrity sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w==
+es-toolkit@^1.43.0:
+  version "1.43.0"
+  resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.43.0.tgz#2c278d55ffeb30421e6e73a009738ed37b10ef61"
+  integrity sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA==
 
 es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14, es5-ext@~0.10.2:
   version "0.10.64"
