diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/AddForumDialog.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/AddForumDialog.kt
index d078c9026591778db9208c8c5b2f342de8a63f29..529e80f028af236e5efd9cd133c19a7693c075ac 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/AddForumDialog.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/AddForumDialog.kt
@@ -20,6 +20,7 @@ package org.briarproject.briar.desktop.forums
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.text.KeyboardOptions
@@ -39,7 +40,6 @@ import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.ui.Alignment
-import androidx.compose.ui.Alignment.Companion.CenterEnd
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
@@ -148,21 +148,20 @@ fun OkCancelBottomBar(
     onOkButtonClicked: () -> Unit,
     onCancelButtonClicked: () -> Unit,
 ) {
-    Box(Modifier.fillMaxWidth()) {
-        Row(Modifier.align(CenterEnd)) {
-            TextButton(
-                onClick = onCancelButtonClicked,
-                colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colors.error)
-            ) {
-                Text(i18n("cancel"))
-            }
-            Button(
-                onClick = onOkButtonClicked,
-                enabled = okButtonEnabled,
-                modifier = Modifier.padding(start = 8.dp)
-            ) {
-                Text(okButtonLabel)
-            }
+    Row(Modifier.fillMaxWidth()) {
+        Spacer(Modifier.weight(1f))
+        TextButton(
+            onClick = onCancelButtonClicked,
+            colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colors.error)
+        ) {
+            Text(i18n("cancel"))
+        }
+        Button(
+            onClick = onOkButtonClicked,
+            enabled = okButtonEnabled,
+            modifier = Modifier.padding(start = 8.dp)
+        ) {
+            Text(okButtonLabel)
         }
     }
 }
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumItem.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumItem.kt
index b3b4820f949ae91d285faed21e3ef3141f2a169d..83a8b4e19795f6e1fd46a2f41ec28d66c00546e4 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumItem.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumItem.kt
@@ -18,16 +18,9 @@
 
 package org.briarproject.briar.desktop.forums
 
-import androidx.compose.ui.text.AnnotatedString
 import org.briarproject.bramble.api.sync.GroupId
 import org.briarproject.briar.api.client.MessageTracker
 import org.briarproject.briar.api.forum.Forum
-import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
-import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18nF
-import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18nP
-import org.briarproject.briar.desktop.utils.TimeUtils.getFormattedTimestamp
-import org.briarproject.briar.desktop.utils.appendCommaSeparated
-import org.briarproject.briar.desktop.utils.buildBlankAnnotatedString
 
 interface GroupItem {
     val id: GroupId
@@ -35,7 +28,6 @@ interface GroupItem {
     val msgCount: Int
     val unread: Int
     val timestamp: Long
-    val description: AnnotatedString
 }
 
 data class ForumItem(
@@ -55,19 +47,6 @@ data class ForumItem(
     override val id: GroupId get() = forum.id
     override val name: String get() = forum.name
 
-    override val description: AnnotatedString
-        get() = buildBlankAnnotatedString {
-            append(name)
-            if (unread > 0) appendCommaSeparated(i18nP("access.forums.unread_count", unread))
-            if (msgCount == 0) appendCommaSeparated(i18n("group.card.no_posts"))
-            else appendCommaSeparated(
-                i18nF(
-                    "access.forums.last_message_timestamp",
-                    getFormattedTimestamp(timestamp)
-                )
-            )
-        }
-
     override fun equals(other: Any?): Boolean {
         return other is ForumItem && other.id == id
     }
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumViewModel.kt
index 7b70e4b40c4a64615b31a1f09b7815d7ea352a82..cb766dfa208f97579271f1ddaf59a84eea44293f 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumViewModel.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumViewModel.kt
@@ -31,12 +31,14 @@ import org.briarproject.bramble.api.db.TransactionManager
 import org.briarproject.bramble.api.event.Event
 import org.briarproject.bramble.api.event.EventBus
 import org.briarproject.bramble.api.identity.IdentityManager
+import org.briarproject.bramble.api.identity.LocalAuthor
 import org.briarproject.bramble.api.lifecycle.LifecycleManager
 import org.briarproject.bramble.api.sync.GroupId
 import org.briarproject.bramble.api.sync.MessageId
 import org.briarproject.bramble.api.sync.event.GroupAddedEvent
 import org.briarproject.bramble.api.sync.event.GroupRemovedEvent
 import org.briarproject.bramble.api.system.Clock
+import org.briarproject.briar.api.client.MessageTracker.GroupCount
 import org.briarproject.briar.api.forum.ForumManager
 import org.briarproject.briar.client.MessageTreeImpl
 import org.briarproject.briar.desktop.threading.BriarExecutors
@@ -144,17 +146,17 @@ class ForumViewModel @Inject constructor(
 
     @OptIn(DelicateCoroutinesApi::class)
     fun createPost(groupItem: GroupItem, text: String, parentId: MessageId?) = GlobalScope.launch {
-        val author = runOnDbThread(false) { txn ->
+        val author = runOnDbThreadWithTransaction<LocalAuthor>(false) { txn ->
             identityManager.getLocalAuthor(txn)
         }
-        val count = runOnDbThread(false) { txn ->
+        val count = runOnDbThreadWithTransaction<GroupCount>(false) { txn ->
             forumManager.getGroupCount(txn, groupItem.id)
         }
         val timestamp = max(count.latestMsgTime + 1, clock.currentTimeMillis())
         val post = withContext(cryptoDispatcher) {
             forumManager.createLocalPost(groupItem.id, text, timestamp, parentId, author)
         }
-        runOnDbThread(false) { txn ->
+        runOnDbThreadWithTransaction(false) { txn ->
             val header = forumManager.addLocalPost(txn, post)
             txn.attach {
                 val item = ForumPostItem(header, text)
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupCard.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupCard.kt
index 7ef6bb884bcbe7ccd2ac242956a2f7a0d24dc0b0..33ec050a50efe6fca248cd3161d28bf761f00f56 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupCard.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupCard.kt
@@ -19,10 +19,12 @@
 package org.briarproject.briar.desktop.forums
 
 import androidx.compose.foundation.layout.Arrangement.SpaceBetween
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.defaultMinSize
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.selection.selectable
 import androidx.compose.foundation.selection.selectableGroup
@@ -39,16 +41,18 @@ import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.contentDescription
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.semantics.text
-import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.unit.dp
 import org.briarproject.bramble.api.sync.GroupId
 import org.briarproject.briar.desktop.theme.selectedCard
 import org.briarproject.briar.desktop.theme.surfaceVariant
 import org.briarproject.briar.desktop.ui.Constants.HEADER_SIZE
+import org.briarproject.briar.desktop.ui.NumberBadge
+import org.briarproject.briar.desktop.utils.InternationalizationUtils
 import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
 import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18nP
 import org.briarproject.briar.desktop.utils.PreviewUtils.preview
 import org.briarproject.briar.desktop.utils.TimeUtils.getFormattedTimestamp
+import org.briarproject.briar.desktop.utils.appendCommaSeparated
 import org.briarproject.briar.desktop.utils.buildBlankAnnotatedString
 
 @Suppress("HardCodedStringLiteral")
@@ -62,7 +66,6 @@ fun main() = preview {
                 override val msgCount: Int = 42
                 override val unread: Int = 23
                 override val timestamp: Long = System.currentTimeMillis()
-                override val description: AnnotatedString = buildBlankAnnotatedString { }
             },
             onGroupItemSelected = {},
             selected = false,
@@ -94,14 +97,23 @@ fun GroupCard(
         },
         contentColor = MaterialTheme.colors.onSurface,
     ) {
+        val itemDescription = getItemDescription(item)
         Row(
             modifier = Modifier
                 .padding(horizontal = 8.dp, vertical = 4.dp)
                 .semantics {
-                    text = item.description
+                    text = itemDescription
                 },
         ) {
-            GroupCircle(item, modifier = Modifier.align(Alignment.Top).padding(vertical = 12.dp))
+            Box(
+                modifier = Modifier.align(Alignment.Top).padding(vertical = 12.dp),
+            ) {
+                GroupCircle(item)
+                NumberBadge(
+                    num = item.unread,
+                    modifier = Modifier.align(Alignment.TopEnd).offset(8.dp, (-6).dp)
+                )
+            }
             Column(
                 verticalArrangement = SpaceBetween,
                 modifier = Modifier.align(CenterVertically).padding(start = 16.dp)
@@ -134,3 +146,16 @@ fun GroupCard(
         }
     }
 }
+
+@Composable
+private fun getItemDescription(item: GroupItem) = buildBlankAnnotatedString {
+    append(item.name)
+    if (item.unread > 0) appendCommaSeparated(i18nP("access.forums.unread_count", item.unread))
+    if (item.msgCount == 0) appendCommaSeparated(i18n("group.card.no_posts"))
+    else appendCommaSeparated(
+        InternationalizationUtils.i18nF(
+            "access.forums.last_post_timestamp",
+            getFormattedTimestamp(item.timestamp)
+        )
+    )
+}
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupCircle.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupCircle.kt
index c3b244d2598b87e7ad8f6a216c11f4448a404934..1a41ac1f4dd732c1a4cabde33c2943d0de611b6e 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupCircle.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupCircle.kt
@@ -21,14 +21,12 @@ package org.briarproject.briar.desktop.forums
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.material.MaterialTheme
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment.Companion.Center
-import androidx.compose.ui.Alignment.Companion.TopEnd
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.geometry.Offset
@@ -38,38 +36,29 @@ import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import org.briarproject.bramble.api.sync.GroupId
 import org.briarproject.briar.desktop.theme.outline
-import org.briarproject.briar.desktop.ui.NumberBadge
 import org.briarproject.briar.desktop.utils.InternationalizationUtils.locale
 
 @Composable
-fun GroupCircle(item: GroupItem, showMessageCount: Boolean = true, modifier: Modifier = Modifier) {
+fun GroupCircle(item: GroupItem, modifier: Modifier = Modifier) {
     Box(
+        contentAlignment = Center,
         modifier = modifier
+            .size(36.dp)
+            .clip(CircleShape)
+            .border(1.dp, MaterialTheme.colors.outline, CircleShape)
+            .background(item.id.getBackgroundColor()),
     ) {
-        Box(
-            contentAlignment = Center,
-            modifier = Modifier
-                .size(36.dp)
-                .clip(CircleShape)
-                .border(1.dp, MaterialTheme.colors.outline, CircleShape)
-                .background(item.id.getBackgroundColor()),
-        ) {
-            Text(
-                text = item.name.substring(0..0).uppercase(locale),
-                color = Color.White,
-                style = MaterialTheme.typography.body1.copy(
-                    fontSize = 24.sp,
-                    shadow = Shadow(
-                        color = Color.Black.copy(alpha = 0.4f),
-                        offset = Offset(4f, 4f),
-                        blurRadius = 8f
-                    )
+        Text(
+            text = item.name.substring(0..0).uppercase(locale),
+            color = Color.White,
+            style = MaterialTheme.typography.body1.copy(
+                fontSize = 24.sp,
+                shadow = Shadow(
+                    color = Color.Black.copy(alpha = 0.4f),
+                    offset = Offset(4f, 4f),
+                    blurRadius = 8f
                 )
             )
-        }
-        if (showMessageCount) NumberBadge(
-            num = item.unread,
-            modifier = Modifier.align(TopEnd).offset(8.dp, (-6).dp)
         )
     }
 }
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupConversationScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupConversationScreen.kt
index 600b8fbd17cb4d12172027e2edbb4e0ee33e1ce3..6540ceec2f0998784cc40f562a68a5620379fcd9 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupConversationScreen.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupConversationScreen.kt
@@ -103,7 +103,6 @@ private fun GroupConversationHeader(
             ) {
                 GroupCircle(
                     item = groupItem,
-                    showMessageCount = false,
                     modifier = Modifier.align(CenterVertically),
                 )
                 Text(
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadItem.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadItem.kt
index ee751e90dd109bf6c4b54e350e227bce82a7a046..a751f18fbd566521e3bf639ab027539adf4b32bb 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadItem.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadItem.kt
@@ -37,6 +37,8 @@ class ForumPostItem(h: ForumPostHeader, text: String?) : ThreadItem(
     isRead = h.isRead
 )
 
+// TODO the mutable state here might need to be made immutable later
+//  and copy on data classes used to trigger recompositions when items update
 @NotThreadSafe
 abstract class ThreadItem(
     private val messageId: MessageId,
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threading/BriarExecutors.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threading/BriarExecutors.kt
index e18685288a955c709acdd84e74bd37d5ec2c67b2..d1affd5700904b60e0c2a6bb9e6768400ab3f50d 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threading/BriarExecutors.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threading/BriarExecutors.kt
@@ -30,7 +30,7 @@ interface BriarExecutors {
         @DatabaseExecutor task: (Transaction) -> Unit,
     )
 
-    suspend fun <T> runOnDbThread(
+    suspend fun <T> runOnDbThreadWithTransaction(
         readOnly: Boolean,
         @DatabaseExecutor task: (Transaction) -> T,
     ): T
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threading/BriarExecutorsImpl.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threading/BriarExecutorsImpl.kt
index 0700aa2092aefa6bd9f67e23ca8818b28ee197a6..28f36dbf3182386c2fbd8adbbca3dfaf9e1a8339 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threading/BriarExecutorsImpl.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threading/BriarExecutorsImpl.kt
@@ -78,7 +78,7 @@ constructor(
         }
     }
 
-    override suspend fun <T> runOnDbThread(
+    override suspend fun <T> runOnDbThreadWithTransaction(
         readOnly: Boolean,
         @DatabaseExecutor task: (Transaction) -> T
     ) = suspendCoroutine<T> { cont ->
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/DbViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/DbViewModel.kt
index 8547165856fb888d493aec9fd1cd1524b39d764c..e3b97b9c3178eee70b8657db20de4559d8a4e907 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/DbViewModel.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/DbViewModel.kt
@@ -53,8 +53,8 @@ abstract class DbViewModel(
      * Waits for the DB to open and runs the given [task] on the [DatabaseExecutor],
      * returning its result.
      */
-    protected suspend fun <T> runOnDbThread(
+    protected suspend fun <T> runOnDbThreadWithTransaction(
         readOnly: Boolean,
         @DatabaseExecutor task: (Transaction) -> T,
-    ): T = briarExecutors.runOnDbThread(readOnly, task)
+    ): T = briarExecutors.runOnDbThreadWithTransaction(readOnly, task)
 }
diff --git a/briar-desktop/src/main/resources/strings/BriarDesktop.properties b/briar-desktop/src/main/resources/strings/BriarDesktop.properties
index 0ccafe4e803b7f07a32ba9acceb40809e9f65661..13b4b15c13c7620499288eb5b4aa5ab30e25ba52 100644
--- a/briar-desktop/src/main/resources/strings/BriarDesktop.properties
+++ b/briar-desktop/src/main/resources/strings/BriarDesktop.properties
@@ -62,7 +62,7 @@ access.menu=Show menu
 access.forums.add=Add forum
 access.forums.list=forum list
 access.forums.unread_count={0, plural, one {one unread posts} other {{0} unread posts}}
-access.forums.last_message_timestamp=last message: {0}
+access.forums.last_post_timestamp=last post: {0}
 
 # Contacts
 contacts.none_selected.title=No contact selected