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 83a8b4e19795f6e1fd46a2f41ec28d66c00546e4..c68fdc1d7ee09995f9f26a8bc24a61871d9f5083 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
@@ -21,6 +21,8 @@ package org.briarproject.briar.desktop.forums
 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.api.forum.ForumPostHeader
+import kotlin.math.max
 
 interface GroupItem {
     val id: GroupId
@@ -47,11 +49,10 @@ data class ForumItem(
     override val id: GroupId get() = forum.id
     override val name: String get() = forum.name
 
-    override fun equals(other: Any?): Boolean {
-        return other is ForumItem && other.id == id
-    }
-
-    override fun hashCode(): Int {
-        return forum.hashCode()
-    }
+    fun updateOnPostReceived(header: ForumPostHeader) =
+        copy(
+            msgCount = msgCount + 1,
+            unread = if (header.isRead) unread else unread + 1,
+            timestamp = max(header.timestamp, this.timestamp)
+        )
 }
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 3bfa842a781bb66951dbcbd3ee09318a22b9784d..bc8ff410fe512a70e0fa602d2cd1b4c9cb9dcab7 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
@@ -21,6 +21,7 @@ package org.briarproject.briar.desktop.forums
 import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.mutableStateListOf
 import androidx.compose.runtime.mutableStateOf
+import mu.KotlinLogging
 import org.briarproject.bramble.api.db.TransactionManager
 import org.briarproject.bramble.api.event.Event
 import org.briarproject.bramble.api.event.EventBus
@@ -29,8 +30,11 @@ import org.briarproject.bramble.api.sync.GroupId
 import org.briarproject.bramble.api.sync.event.GroupAddedEvent
 import org.briarproject.bramble.api.sync.event.GroupRemovedEvent
 import org.briarproject.briar.api.forum.ForumManager
+import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent
 import org.briarproject.briar.desktop.threading.BriarExecutors
 import org.briarproject.briar.desktop.utils.clearAndAddAll
+import org.briarproject.briar.desktop.utils.removeFirst
+import org.briarproject.briar.desktop.utils.replaceFirst
 import org.briarproject.briar.desktop.viewmodel.EventListenerDbViewModel
 import org.briarproject.briar.desktop.viewmodel.asState
 import javax.inject.Inject
@@ -44,6 +48,10 @@ class ForumViewModel @Inject constructor(
     eventBus: EventBus,
 ) : EventListenerDbViewModel(briarExecutors, lifecycleManager, db, eventBus) {
 
+    companion object {
+        private val LOG = KotlinLogging.logger {}
+    }
+
     private val _fullForumList = mutableStateListOf<ForumItem>()
     val forumList = derivedStateOf {
         val filter = _filterBy.value
@@ -75,31 +83,44 @@ class ForumViewModel @Inject constructor(
     }
 
     override fun eventOccurred(e: Event) {
-        if (e is GroupAddedEvent) {
-            if (e.group.clientId == ForumManager.CLIENT_ID) loadGroups()
-        } else if (e is GroupRemovedEvent) {
-            if (e.group.clientId == ForumManager.CLIENT_ID) {
-                loadGroups()
+        when {
+            e is GroupAddedEvent && e.group.clientId == ForumManager.CLIENT_ID -> {
+                runOnDbThreadWithTransaction(true) { txn ->
+                    val item = ForumItem(
+                        forum = forumManager.getForum(txn, e.group.id),
+                        groupCount = forumManager.getGroupCount(txn, e.group.id),
+                    )
+                    txn.attach {
+                        addItem(item)
+                    }
+                }
+            }
+
+            e is GroupRemovedEvent && e.group.clientId == ForumManager.CLIENT_ID -> {
+                removeItem(e.group.id)
                 if (selectedGroupItem.value?.id == e.group.id) _selectedGroupItem.value = null
             }
+
+            e is ForumPostReceivedEvent -> {
+                // todo: better use equivalent to ConversationMessageTrackedEvent to update on new *own* posts as well
+                updateItem(e.groupId) { it.updateOnPostReceived(e.header) }
+            }
         }
     }
 
-    fun createForum(name: String) {
+    fun createForum(name: String) = runOnDbThread {
         forumManager.addForum(name)
     }
 
-    private fun loadGroups() {
-        runOnDbThreadWithTransaction(true) { txn ->
-            val list = forumManager.getForums(txn).map { forums ->
-                ForumItem(
-                    forum = forums,
-                    groupCount = forumManager.getGroupCount(txn, forums.id),
-                )
-            }
-            txn.attach {
-                _fullForumList.clearAndAddAll(list)
-            }
+    private fun loadGroups() = runOnDbThreadWithTransaction(true) { txn ->
+        val list = forumManager.getForums(txn).map { forums ->
+            ForumItem(
+                forum = forums,
+                groupCount = forumManager.getGroupCount(txn, forums.id),
+            )
+        }
+        txn.attach {
+            _fullForumList.clearAndAddAll(list)
         }
     }
 
@@ -113,4 +134,19 @@ class ForumViewModel @Inject constructor(
     fun setFilterBy(filter: String) {
         _filterBy.value = filter
     }
+
+    private fun addItem(forumItem: ForumItem) = _fullForumList.add(forumItem)
+
+    private fun updateItem(forumId: GroupId, update: (ForumItem) -> ForumItem) {
+        _fullForumList.replaceFirst(
+            { it.id == forumId },
+            update
+        )
+    }
+
+    private fun removeItem(forumId: GroupId) {
+        _fullForumList.removeFirst {
+            it.id == forumId
+        }
+    }
 }