diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/HtmlText.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/HtmlText.kt
index 706668e7645ad1c03f3a46fa594ec88794056336..92b567956b13e2c19b8bdde6aa7de76842d5a35b 100644
--- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/HtmlText.kt
+++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/HtmlText.kt
@@ -47,6 +47,7 @@ import androidx.compose.ui.text.ParagraphStyle
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontStyle
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.style.BaselineShift
@@ -164,6 +165,7 @@ fun HtmlText(
     val listNumbering = ArrayDeque<Int>()
 
     var lastCharWasNewline = true
+    var withinPre = false
 
     // Elements we support:
     //    "h1", "h2", "h3", "h4", "h5", "h6",
@@ -190,9 +192,7 @@ fun HtmlText(
     val subscript = SpanStyle(baselineShift = BaselineShift.Subscript)
     val superscript = SpanStyle(baselineShift = BaselineShift.Superscript)
     val link = SpanStyle(textDecoration = TextDecoration.Underline, color = MaterialTheme.colors.primaryVariant)
-
-    // todo: trim newlines / whitespaces?!
-    // todo: nested paragraphs not possible, but in HTML it is?
+    val monospace = SpanStyle(fontFamily = FontFamily.Monospace) // todo: doesn't work for some reason
 
     val formattedString = remember(html) {
         buildAnnotatedString {
@@ -257,12 +257,25 @@ fun HtmlText(
 
             fun startPre() {
                 pushIndent(20.sp)
+                withinPre = true
+                pushStyle(monospace)
             }
 
             fun endPre() {
                 popIndent()
+                withinPre = false
+                pop()
+            }
+
+            fun startCode() {
+                if (!withinPre) pushStyle(monospace)
             }
 
+            fun endCode() {
+                if (!withinPre) pop()
+            }
+
+            // todo: this should be changed to start/endLink for consistent length
             fun addLink(node: Element) {
                 val start = cursorPosition
                 val end = start + node.text().length
@@ -340,17 +353,21 @@ fun HtmlText(
                 ensureNewline()
             }
 
-            // replace multiple newlines/whitespaces to single whitespace
-            // todo: also trim text (at least) inside <p> tags
-            val cleanHtml = html.replace("\\s+".toRegex(), " ")
-            val doc = Jsoup.parse(cleanHtml)
+            val doc = Jsoup.parse(html)
 
             doc.traverse(object : NodeVisitor {
                 override fun head(node: Node, depth: Int) {
                     when (node) {
                         is TextNode -> {
-                            if (node.text().isNotBlank()) {
-                                appendAndUpdateCursor(node.text())
+                            val text =
+                                if (withinPre) node.wholeText
+                                else node.text()
+                                    // replace multiple newlines/whitespaces to single whitespace
+                                    .replace("\\s+".toRegex(), " ")
+                                    // remove whitespace if first character in new line
+                                    .let { if (lastCharWasNewline) it.trimStart() else it }
+                            if (text.isNotBlank()) {
+                                appendAndUpdateCursor(text)
                             }
                         }
 
@@ -371,6 +388,7 @@ fun HtmlText(
                                 "strike" -> pushStyle(strikethrough)
                                 "sub" -> pushStyle(subscript)
                                 "sup" -> pushStyle(superscript)
+                                "code" -> startCode()
                                 "q" -> startInlineQuote()
                                 "a" -> addLink(node)
 
@@ -406,6 +424,8 @@ fun HtmlText(
                             "a",
                             -> pop()
 
+                            "code" -> endCode()
+
                             "q" -> endInlineQuote()
 
                             "ul" -> endUnorderedList()
diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/blog/TestCode.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/blog/TestCode.kt
index 2a162e1e65f923f678bb7dbe0d6993e5f0ac626a..1dae48eeb50d7873fc312af48d8c9ccc68f81009 100644
--- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/blog/TestCode.kt
+++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/blog/TestCode.kt
@@ -36,7 +36,7 @@ private val testHtml = """
         drwx------   2 root root  16K Apr  7  2023 lost+found
         </code></pre>
         And here's some more regular text.
-        <p>Then there's more text and another code block:</p>
+        <p>Then there's more text, an <code>inline</code> code and another code block:</p>
         <pre>
         drwxr-xr-x   5 root root 4,0K Nov 17  2023 boot
         drwx------   8 root root 4,0K Mar 29 14:27 root