diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/BlogScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/BlogScreen.kt
index 862f0360df3b60b7922d4e2e7ee4085eeeeb117b..90b493351cb6f2c9391e79fb78a370f8b25949ca 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/BlogScreen.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/BlogScreen.kt
@@ -18,24 +18,58 @@
 
 package org.briarproject.briar.desktop.blog
 
+import androidx.compose.foundation.layout.Arrangement.SpaceBetween
+import androidx.compose.foundation.layout.Arrangement.spacedBy
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.CircularProgressIndicator
+import androidx.compose.material.DropdownMenu
+import androidx.compose.material.DropdownMenuItem
+import androidx.compose.material.IconButton
+import androidx.compose.material.MaterialTheme
 import androidx.compose.material.Scaffold
 import androidx.compose.material.Text
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowBack
+import androidx.compose.material.icons.filled.MoreVert
+import androidx.compose.material.icons.filled.Share
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment.Companion.BottomCenter
 import androidx.compose.ui.Alignment.Companion.Center
+import androidx.compose.ui.Alignment.Companion.CenterVertically
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
+import org.briarproject.briar.desktop.blog.sharing.BlogSharingStatusDrawerContent
+import org.briarproject.briar.desktop.blog.sharing.BlogSharingViewModel
+import org.briarproject.briar.desktop.threadedgroup.SharingStrings
+import org.briarproject.briar.desktop.threadedgroup.sharing.ThreadedGroupSharingActionDrawerContent
+import org.briarproject.briar.desktop.ui.Constants.HEADER_SIZE
+import org.briarproject.briar.desktop.ui.HorizontalDivider
+import org.briarproject.briar.desktop.ui.getInfoDrawerHandler
 import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
+import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18nF
 import org.briarproject.briar.desktop.viewmodel.viewModel
 
 @Composable
-fun BlogScreen(onSideBarClickedKey: Any, viewModel: FeedViewModel = viewModel()) {
-    LaunchedEffect(onSideBarClickedKey) { viewModel.selectBlog(null) }
+fun BlogScreen(viewModel: FeedViewModel = viewModel()) {
     Scaffold(
+        topBar = {
+            // only show header if some blog is selected
+            if (viewModel.selectedBlog.value != null) {
+                BlogHeader(
+                    blogSharingViewModel = viewModel.blogSharingViewModel,
+                    onBackClick = { viewModel.selectBlog(null) }
+                )
+            }
+        },
         content = { padding ->
             if (viewModel.isLoading.value) {
                 Box(
@@ -65,10 +99,114 @@ fun BlogScreen(onSideBarClickedKey: Any, viewModel: FeedViewModel = viewModel())
             }
         },
         bottomBar = {
-            val onCloseReply = { viewModel.selectPost(null) }
-            BlogInput(viewModel.selectedPost.value, onCloseReply) { text ->
-                viewModel.createBlogPost(text)
+            // only show input field if no blog is selected, or if a blog and a post are selected
+            if (viewModel.selectedBlog.value == null || viewModel.selectedPost.value != null) {
+                val onCloseReply = { viewModel.selectPost(null) }
+                BlogInput(viewModel.selectedPost.value, onCloseReply) { text ->
+                    viewModel.createBlogPost(text)
+                }
             }
         }
     )
 }
+
+@Composable
+private fun BlogHeader(
+    blogSharingViewModel: BlogSharingViewModel,
+    onBackClick: () -> Unit,
+) {
+    val isMenuOpen = remember { mutableStateOf(false) }
+    Box(modifier = Modifier.fillMaxWidth().height(HEADER_SIZE + 1.dp)) {
+        Row(
+            horizontalArrangement = SpaceBetween,
+            verticalAlignment = CenterVertically,
+            modifier = Modifier.fillMaxWidth().align(Center).padding(horizontal = 16.dp),
+        ) {
+            Row(
+                horizontalArrangement = spacedBy(8.dp),
+                verticalAlignment = CenterVertically,
+            ) {
+                IconButton(
+                    icon = Icons.Filled.ArrowBack,
+                    contentDescription = i18n("blog.back"),
+                    onClick = onBackClick,
+                )
+                Column {
+                    Text(
+                        text = blogSharingViewModel.contactName.value,
+                        maxLines = 1,
+                        overflow = TextOverflow.Ellipsis,
+                        style = MaterialTheme.typography.h2,
+                    )
+                    val sharingInfo = blogSharingViewModel.sharingInfo.value
+                    Text(
+                        text = i18nF("blog.sharing.status.with", sharingInfo.total, sharingInfo.online)
+                    )
+                }
+            }
+            Row(
+                horizontalArrangement = spacedBy(4.dp),
+                verticalAlignment = CenterVertically,
+            ) {
+                val infoDrawerHandler = getInfoDrawerHandler()
+                IconButton(
+                    icon = Icons.Filled.Share,
+                    contentDescription = i18n("blog.sharing.action.title"),
+                    onClick = {
+                        infoDrawerHandler.open {
+                            ThreadedGroupSharingActionDrawerContent(
+                                close = infoDrawerHandler::close,
+                                viewModel = blogSharingViewModel,
+                                strings = object : SharingStrings {
+                                    override val sharingActionTitle = i18n("blog.sharing.action.title")
+                                    override val sharingActionClose = i18n("access.forum.sharing.action.close")
+                                    override val sharingActionNoContacts = i18n("blog.sharing.action.no_contacts")
+                                },
+                            )
+                        }
+                    },
+                )
+                IconButton(
+                    icon = Icons.Filled.MoreVert,
+                    contentDescription = i18n("access.menu"),
+                    onClick = { isMenuOpen.value = true },
+                ) {
+                    BlogDropdownMenu(
+                        expanded = isMenuOpen.value,
+                        onClose = { isMenuOpen.value = false },
+                        blogSharingViewModel = blogSharingViewModel,
+                    )
+                }
+            }
+        }
+        HorizontalDivider(modifier = Modifier.align(BottomCenter))
+    }
+}
+
+@Composable
+private fun BlogDropdownMenu(
+    expanded: Boolean,
+    onClose: () -> Unit,
+    blogSharingViewModel: BlogSharingViewModel,
+) = DropdownMenu(
+    expanded = expanded,
+    onDismissRequest = onClose,
+) {
+    val infoDrawerHandler = getInfoDrawerHandler()
+    DropdownMenuItem(
+        onClick = {
+            onClose()
+            infoDrawerHandler.open {
+                BlogSharingStatusDrawerContent(
+                    close = infoDrawerHandler::close,
+                    viewModel = blogSharingViewModel,
+                )
+            }
+        }
+    ) {
+        Text(
+            i18n("blog.sharing.status.title"),
+            style = MaterialTheme.typography.body2,
+        )
+    }
+}
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/FeedViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/FeedViewModel.kt
index 5b0f3ab8148fc81d5c69e98eeefb2e5a02944d5c..14c720ec5e26efbab66b2062c9b3fbb25654b8d2 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/FeedViewModel.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/FeedViewModel.kt
@@ -37,6 +37,7 @@ import org.briarproject.briar.api.blog.BlogManager
 import org.briarproject.briar.api.blog.BlogPostFactory
 import org.briarproject.briar.api.blog.BlogPostHeader
 import org.briarproject.briar.api.blog.event.BlogPostAddedEvent
+import org.briarproject.briar.desktop.blog.sharing.BlogSharingViewModel
 import org.briarproject.briar.desktop.threading.BriarExecutors
 import org.briarproject.briar.desktop.threading.UiExecutor
 import org.briarproject.briar.desktop.ui.UnreadFabsInfo
@@ -52,6 +53,7 @@ class FeedViewModel @Inject constructor(
     private val blogManager: BlogManager,
     private val blogPostFactory: BlogPostFactory,
     private val identityManager: IdentityManager,
+    val blogSharingViewModel: BlogSharingViewModel,
     briarExecutors: BriarExecutors,
     lifecycleManager: LifecycleManager,
     db: TransactionManager,
@@ -81,6 +83,16 @@ class FeedViewModel @Inject constructor(
         runOnDbThreadWithTransaction(true, this::loadAllBlogPosts)
     }
 
+    override fun onInit() {
+        super.onInit()
+        blogSharingViewModel.onEnterComposition()
+    }
+
+    override fun onCleared() {
+        super.onCleared()
+        blogSharingViewModel.onExitComposition()
+    }
+
     @Suppress("HardCodedStringLiteral")
     override fun eventOccurred(e: Event) {
         if (e is BlogPostAddedEvent) {
@@ -136,6 +148,12 @@ class FeedViewModel @Inject constructor(
     @UiExecutor
     fun selectBlog(groupId: GroupId?) {
         _selectedBlog.value = groupId
+        if (groupId != null) {
+            blogSharingViewModel.setGroupId(groupId)
+            // abort re-posting when navigating to somebody else's blog
+            if (_selectedPost.value?.groupId != groupId)
+                _selectedPost.value = null
+        }
     }
 
     @UiExecutor
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingStatusDrawerContent.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingStatusDrawerContent.kt
new file mode 100644
index 0000000000000000000000000000000000000000..99620cf531ea7f137489997476d6cd48122e13e1
--- /dev/null
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingStatusDrawerContent.kt
@@ -0,0 +1,109 @@
+/*
+ * Briar Desktop
+ * Copyright (C) 2023 The Briar Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package org.briarproject.briar.desktop.blog.sharing
+
+import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.material.icons.filled.Info
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Alignment.Companion.CenterVertically
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import org.briarproject.briar.desktop.contact.ContactItemViewSmall
+import org.briarproject.briar.desktop.ui.Constants
+import org.briarproject.briar.desktop.ui.HorizontalDivider
+import org.briarproject.briar.desktop.ui.ListItemView
+import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
+
+@Composable
+fun BlogSharingStatusDrawerContent(
+    close: () -> Unit,
+    viewModel: BlogSharingViewModel,
+) = Column {
+    Row(Modifier.fillMaxWidth().height(Constants.HEADER_SIZE)) {
+        IconButton(
+            icon = Icons.Filled.Close,
+            contentDescription = i18n("access.forum.sharing.status.close"),
+            onClick = close,
+            modifier = Modifier.padding(start = 24.dp).size(24.dp).align(CenterVertically)
+        )
+        Text(
+            text = i18n("blog.sharing.status.title"),
+            modifier = Modifier.align(CenterVertically).padding(start = 16.dp),
+            style = MaterialTheme.typography.h3,
+        )
+    }
+    HorizontalDivider()
+    Row(
+        verticalAlignment = CenterVertically,
+        horizontalArrangement = spacedBy(8.dp),
+        modifier = Modifier.padding(8.dp),
+    ) {
+        Icon(
+            imageVector = Icons.Filled.Info,
+            contentDescription = null,
+            modifier = Modifier.size(16.dp)
+        )
+        Text(
+            text = i18n("blog.sharing.status.info"),
+            style = MaterialTheme.typography.body2,
+        )
+    }
+    HorizontalDivider()
+    Box(Modifier.fillMaxSize()) {
+        if (viewModel.currentlySharedWith.value.isEmpty()) {
+            // todo: this might be shown to the user while the list is still loading
+            Text(
+                text = i18n("blog.sharing.status.nobody"),
+                style = MaterialTheme.typography.body1,
+                modifier = Modifier.align(Alignment.Center),
+            )
+        } else {
+            LazyColumn {
+                items(
+                    items = viewModel.currentlySharedWith.value,
+                    key = { it.id },
+                ) { contactItem ->
+                    ListItemView {
+                        ContactItemViewSmall(
+                            contactItem,
+                            modifier = Modifier.padding(8.dp)
+                        )
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingViewModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9cfbc2b6f6229ad525777d52ac99b1456aca4c3d
--- /dev/null
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingViewModel.kt
@@ -0,0 +1,153 @@
+/*
+ * Briar Desktop
+ * Copyright (C) 2021-2023 The Briar Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package org.briarproject.briar.desktop.blog.sharing
+
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.mutableStateOf
+import mu.KotlinLogging
+import org.briarproject.bramble.api.connection.ConnectionRegistry
+import org.briarproject.bramble.api.contact.ContactManager
+import org.briarproject.bramble.api.db.Transaction
+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.lifecycle.LifecycleManager
+import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent
+import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent
+import org.briarproject.bramble.api.sync.GroupId
+import org.briarproject.briar.api.blog.BlogManager
+import org.briarproject.briar.api.blog.BlogSharingManager
+import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent
+import org.briarproject.briar.api.conversation.ConversationManager
+import org.briarproject.briar.api.identity.AuthorManager
+import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE
+import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING
+import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent
+import org.briarproject.briar.desktop.threadedgroup.sharing.InvitationSentEvent
+import org.briarproject.briar.desktop.threadedgroup.sharing.ThreadedGroupSharingViewModel
+import org.briarproject.briar.desktop.threading.BriarExecutors
+import org.briarproject.briar.desktop.threading.UiExecutor
+import org.briarproject.briar.desktop.viewmodel.asState
+import org.briarproject.briar.desktop.viewmodel.update
+import javax.inject.Inject
+
+class BlogSharingViewModel @Inject constructor(
+    private val blogManager: BlogManager,
+    private val blogSharingManager: BlogSharingManager,
+    contactManager: ContactManager,
+    authorManager: AuthorManager,
+    conversationManager: ConversationManager,
+    private val connectionRegistry: ConnectionRegistry,
+    briarExecutors: BriarExecutors,
+    lifecycleManager: LifecycleManager,
+    db: TransactionManager,
+    eventBus: EventBus,
+) : ThreadedGroupSharingViewModel(
+    contactManager,
+    authorManager,
+    conversationManager,
+    connectionRegistry,
+    briarExecutors,
+    lifecycleManager,
+    db,
+    eventBus,
+) {
+
+    companion object {
+        private val LOG = KotlinLogging.logger {}
+    }
+
+    private val _contactName = mutableStateOf("")
+    val contactName = _contactName.asState()
+
+    val currentlySharedWith = derivedStateOf {
+        _contactList.filter { _sharingStatus.value[it.id] == SHARING }
+    }
+
+    override fun reload() {
+        _shareableSelected.value = emptySet()
+        _sharingMessage.value = ""
+        val groupId = _groupId ?: return
+        runOnDbThreadWithTransaction(true) { txn ->
+            val contactName = blogManager.getBlog(txn, groupId).author.name
+            loadSharingStatus(txn, groupId)
+            txn.attach { _contactName.value = contactName }
+        }
+    }
+
+    @UiExecutor
+    override fun shareThreadedGroup() = runOnDbThreadWithTransaction(false) { txn ->
+        val groupId = _groupId ?: return@runOnDbThreadWithTransaction
+        val message = _sharingMessage.value.ifEmpty { null }
+        _shareableSelected.value.forEach { contactId ->
+            blogSharingManager.sendInvitation(txn, groupId, contactId, message)
+        }
+        // send custom event to force message reload if private chat is open for contactId
+        // todo: switch to a more generic approach where every locally sent message broadcasts an event per default
+        txn.attach(InvitationSentEvent(_shareableSelected.value.toList()))
+        txn.attach { reload() }
+    }
+
+    @UiExecutor
+    override fun eventOccurred(e: Event) {
+        super.eventOccurred(e)
+
+        val groupId = _groupId ?: return
+        when {
+            e is BlogInvitationResponseReceivedEvent && e.messageHeader.shareableId == groupId -> {
+                if (e.messageHeader.wasAccepted()) {
+                    _sharingStatus.value += e.contactId to SHARING
+                    val connected = connectionRegistry.isConnected(e.contactId)
+                    _sharingInfo.update { addContact(connected) }
+                } else {
+                    _sharingStatus.value += e.contactId to SHAREABLE
+                }
+            }
+
+            e is ContactLeftShareableEvent && e.groupId == groupId -> {
+                _sharingStatus.value += e.contactId to SHAREABLE
+                val connected = connectionRegistry.isConnected(e.contactId)
+                _sharingInfo.update { removeContact(connected) }
+            }
+
+            e is ContactConnectedEvent -> {
+                if (_sharingStatus.value[e.contactId] == SHARING)
+                    _sharingInfo.update { updateContactConnected(true) }
+            }
+
+            e is ContactDisconnectedEvent -> {
+                if (_sharingStatus.value[e.contactId] == SHARING)
+                    _sharingInfo.update { updateContactConnected(false) }
+            }
+        }
+    }
+
+    private fun loadSharingStatus(txn: Transaction, groupId: GroupId) {
+        val map = contactManager.getContacts(txn).associate { contact ->
+            contact.id to blogSharingManager.getSharingStatus(txn, groupId, contact)
+        }
+        val sharing = map.filterValues { it == SHARING }.keys
+        txn.attach {
+            val online =
+                sharing.fold(0) { acc, it -> if (connectionRegistry.isConnected(it)) acc + 1 else acc }
+            _sharingStatus.value = map
+            _sharingInfo.value = SharingInfo(sharing.size, online)
+        }
+    }
+}
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt
index 4c7a089c8c443807aec8412bc273eb6b40b0d51f..d211627e2f1878672ab5c25134f706da724d5fe8 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt
@@ -47,6 +47,7 @@ import org.briarproject.briar.api.attachment.AttachmentHeader
 import org.briarproject.briar.api.attachment.AttachmentReader
 import org.briarproject.briar.api.autodelete.UnexpectedTimerException
 import org.briarproject.briar.api.autodelete.event.ConversationMessagesDeletedEvent
+import org.briarproject.briar.api.blog.BlogSharingManager
 import org.briarproject.briar.api.conversation.ConversationManager
 import org.briarproject.briar.api.conversation.DeletionResult
 import org.briarproject.briar.api.conversation.event.ConversationMessageReceivedEvent
@@ -70,7 +71,6 @@ import org.briarproject.briar.desktop.conversation.ConversationRequestItem.Reque
 import org.briarproject.briar.desktop.threadedgroup.sharing.InvitationSentEvent
 import org.briarproject.briar.desktop.threading.BriarExecutors
 import org.briarproject.briar.desktop.threading.UiExecutor
-import org.briarproject.briar.desktop.utils.KLoggerUtils.e
 import org.briarproject.briar.desktop.utils.KLoggerUtils.i
 import org.briarproject.briar.desktop.utils.KLoggerUtils.logDuration
 import org.briarproject.briar.desktop.utils.KLoggerUtils.w
@@ -97,6 +97,7 @@ constructor(
     private val introductionManager: IntroductionManager,
     private val forumSharingManager: ForumSharingManager,
     private val groupInvitationManager: GroupInvitationManager,
+    private val blogSharingManager: BlogSharingManager,
     private val messagingManager: MessagingManager,
     private val privateMessageFactory: PrivateMessageFactory,
     briarExecutors: BriarExecutors,
@@ -463,8 +464,17 @@ constructor(
                     )
                 }
 
-                BLOG ->
-                    LOG.e { "Blogs are not supported for the time being." }
+                BLOG -> {
+                    require(desktopFeatureFlags.shouldEnableBlogs()) {
+                        "Blog requests are not supported for this build." // NON-NLS
+                    }
+                    blogSharingManager.respondToInvitation(
+                        /* txn = */ txn,
+                        /* c = */ _contactId.value!!,
+                        /* id = */ item.sessionId,
+                        /* accept = */ accept
+                    )
+                }
             }
             // reload all messages to also show request response message
             // todo: might be better to have an event to react to, also for (other) outgoing messages
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/navigation/SidebarViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/navigation/SidebarViewModel.kt
index d236e61f78a09fa1dcdaed15b8fec593f78f5cf5..d8f6441bf6268d367fe10dc77738e281671c297e 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/navigation/SidebarViewModel.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/navigation/SidebarViewModel.kt
@@ -37,7 +37,6 @@ import org.briarproject.briar.desktop.viewmodel.ViewModel
 import org.briarproject.briar.desktop.viewmodel.asState
 import org.briarproject.briar.desktop.viewmodel.update
 import javax.inject.Inject
-import kotlin.random.Random
 
 class SidebarViewModel
 @Inject
@@ -80,19 +79,12 @@ constructor(
     private val _uiMode = mutableStateOf(UiMode.CONTACTS)
     private val _account = mutableStateOf<LocalAuthor?>(null)
     private val _mailboxProblem = mutableStateOf(false)
-    private val _blogResetView = mutableStateOf(0L)
 
     private val _messageCount = mutableStateOf(MessageCount())
 
     val uiMode = _uiMode.asState()
     val account = _account.asState()
 
-    /**
-     * A random number that changes everytime, the user changes the [UiMode] with [setUiMode] to [UiMode.BLOGS].
-     * This can be useful to reset the blog screen to the main blog feed instead of showing an individual blog.
-     * When we have a proper navigation system in place, it can hopefully replace this hack.
-     */
-    val blogResetView = _blogResetView.asState()
     val mailboxProblem = _mailboxProblem.asState()
 
     val messageCount = _messageCount.asState()
@@ -100,7 +92,6 @@ constructor(
     @UiExecutor
     fun setUiMode(uiMode: UiMode) {
         _uiMode.value = uiMode
-        if (uiMode == UiMode.BLOGS) _blogResetView.value = Random.nextLong()
         if (uiMode == UiMode.MAILBOX) _mailboxProblem.value = false
     }
 
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/ThreadedGroupStrings.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/ThreadedGroupStrings.kt
index ce8bb7b8b91840d8f04b700320a6eb674cb14f67..4f3fb82882890e104993a55f6003fcced3bfb72f 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/ThreadedGroupStrings.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/ThreadedGroupStrings.kt
@@ -43,7 +43,13 @@ abstract class ThreadedGroupStrings(
     val messageReplyClose: String,
     val messageReplyHint: String,
     val messageHint: String,
-    val sharingActionTitle: String,
-    val sharingActionClose: String,
-    val sharingActionNoContacts: String,
-)
+    override val sharingActionTitle: String,
+    override val sharingActionClose: String,
+    override val sharingActionNoContacts: String,
+) : SharingStrings
+
+interface SharingStrings {
+    val sharingActionTitle: String
+    val sharingActionClose: String
+    val sharingActionNoContacts: String
+}
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/sharing/ThreadedGroupSharingActionDrawerContent.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/sharing/ThreadedGroupSharingActionDrawerContent.kt
index 944af65750665bf6e2ce5b88562f21df6939ad49..ff076d2cf2995a6ef942e868bcca6ba3c32e03c7 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/sharing/ThreadedGroupSharingActionDrawerContent.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/sharing/ThreadedGroupSharingActionDrawerContent.kt
@@ -48,7 +48,7 @@ import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.NOT_SUPPO
 import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE
 import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING
 import org.briarproject.briar.desktop.contact.ContactItemViewSmall
-import org.briarproject.briar.desktop.threadedgroup.ThreadedGroupStrings
+import org.briarproject.briar.desktop.threadedgroup.SharingStrings
 import org.briarproject.briar.desktop.ui.Constants.HEADER_SIZE
 import org.briarproject.briar.desktop.ui.HorizontalDivider
 import org.briarproject.briar.desktop.ui.ListItemView
@@ -59,7 +59,7 @@ import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
 fun ThreadedGroupSharingActionDrawerContent(
     close: () -> Unit,
     viewModel: ThreadedGroupSharingViewModel,
-    strings: ThreadedGroupStrings,
+    strings: SharingStrings,
 ) = Column {
     Row(
         verticalAlignment = CenterVertically,
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MainScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MainScreen.kt
index e014690de7f50fa5386e2ddd1369cc5d20ba58c1..549f6b401c4403278b79e2ec668b8589aeffe3f2 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MainScreen.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MainScreen.kt
@@ -65,7 +65,7 @@ fun MainScreen(viewModel: SidebarViewModel = viewModel()) {
                     UiMode.CONTACTS -> PrivateMessageScreen()
                     UiMode.GROUPS -> PrivateGroupScreen()
                     UiMode.FORUMS -> ForumScreen()
-                    UiMode.BLOGS -> BlogScreen(viewModel.blogResetView.value)
+                    UiMode.BLOGS -> BlogScreen()
                     UiMode.MAILBOX -> MailboxScreen()
                     UiMode.SETTINGS -> SettingsScreen()
                     UiMode.ABOUT -> AboutScreen()
diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/ViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/ViewModel.kt
index 17af4811fa33cb65d8d45bafb8ded7f9a063bf69..20906425cbb6390111ce517b947374782bcf6594 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/ViewModel.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/ViewModel.kt
@@ -1,6 +1,6 @@
 /*
  * Briar Desktop
- * Copyright (C) 2021-2022 The Briar Project
+ * Copyright (C) 2021-2023 The Briar Project
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -64,7 +64,7 @@ abstract class ViewModel {
      * Composable function goes out of scope.
      *
      * This function can be overridden in child classes,
-     * but implementations should always call `super.onInit()` first.
+     * but implementations should always call `super.onCleared()` first.
      *
      * Apart from that, **do not call this function manually anywhere.**
      */
diff --git a/briar-desktop/src/main/resources/strings/BriarDesktop.properties b/briar-desktop/src/main/resources/strings/BriarDesktop.properties
index e41d59318953cbfde67d999d4b64ef9a45148482..bc63011880be26ed513a07409009e8e3ef872d90 100644
--- a/briar-desktop/src/main/resources/strings/BriarDesktop.properties
+++ b/briar-desktop/src/main/resources/strings/BriarDesktop.properties
@@ -223,6 +223,13 @@ blog.post.reply.intro=Reblog this post:
 blog.post.hint=Type your blog post
 blog.post.reply.hint=Add a comment (optional)
 blog.open.from.author=Open blog of {0}
+blog.back=Show all blogs
+blog.sharing.status.title=Sharing Status
+blog.sharing.status.info=Anyone who subscribes to a blog can share it with their contacts. You are sharing this blog with the following contacts. There may also be other subscribers who you can't see.
+blog.sharing.status.with=Shared with {0} ({1} online)
+blog.sharing.status.nobody=Nobody
+blog.sharing.action.title=Share Blog
+blog.sharing.action.no_contacts=No contacts yet. You can only share blogs with your contacts.
 
 # Introduction
 introduction.introduce=Make Introduction