diff --git a/build.gradle.kts b/build.gradle.kts
index 66f5b3840611ded29d76a30e5df56b74aa00219b..af4aeb877c4435e8f71126aaf68221ea36675392 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -24,6 +24,7 @@ dependencies {
 
     implementation("com.fasterxml.jackson.core:jackson-databind:2.10.0")
     implementation("com.github.ajalt:clikt:2.2.0")
+    implementation("org.jetbrains.compose.material:material-icons-extended:0.4.0")
 
     implementation(project(path = ":briar:briar-core", configuration = "default"))
     implementation(project(path = ":briar:bramble-java", configuration = "default"))
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/BriarService.kt b/src/main/kotlin/org/briarproject/briar/desktop/BriarService.kt
index ad43f0bb6125f53311ee26830001bdd01d1d99b2..18a11ca5237903a050e3aff7ea851375e7fd8e0c 100644
--- a/src/main/kotlin/org/briarproject/briar/desktop/BriarService.kt
+++ b/src/main/kotlin/org/briarproject/briar/desktop/BriarService.kt
@@ -66,13 +66,7 @@ constructor(
                     })
 
                 is Screen.Main ->
-                    Column(
-                        modifier = Modifier.padding(16.dp).fillMaxSize(),
-                        verticalArrangement = Arrangement.Center,
-                        horizontalAlignment = Alignment.CenterHorizontally
-                    ) {
-                        Text("Welcome to Briar")
-                    }
+                    briarUIStateManager()
             }
         }
     }
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/data/Contacts.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/Contacts.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2b7b47c2031f462448802bf78dee352ab35415d3
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/Contacts.kt
@@ -0,0 +1,229 @@
+package org.briarproject.briar.desktop.paul.data
+
+import org.briarproject.briar.desktop.paul.model.Contact
+import org.briarproject.briar.desktop.paul.model.Message
+
+object ContactList {
+    val msg1: List<Message> = listOf<Message>(
+        Message(from = "Alice", message = "hello!", time = "2 days ago", delivered = true),
+        Message(from = null, message = "yes I hear you", time = "1 day ago", delivered = true),
+        Message(
+            from = null,
+            message = "I am messaging you through this fake Briar Desktop app",
+            time = "18 hrs. ago",
+            delivered = true
+        ),
+        Message(from = "Alice", message = "Ah I see, very neat", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "Loren Ipsum", time = "2 min. ago", delivered = false)
+    )
+    val msg2: List<Message> = listOf<Message>(
+        Message(
+            from = null,
+            message = "The air bites shrewdly; it is very cold.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "It is a nipping and an eager air.", time = "1 day ago", delivered = true),
+        Message(from = null, message = "What hour now?", time = "18 hrs. ago", delivered = true),
+        Message(from = "Bob", message = "I think it lacks of twelve.", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "No, it is struck.", time = "2 min. ago", delivered = false),
+        Message(
+            from = "Bob",
+            message = "Indeed? I heard it not: then it draws near the season Wherein the spirit held his wont to walk. A flourish of trumpets, and ordnance shot off, within. What does this mean, my lord?",
+            time = "2 min. ago",
+            delivered = false
+        ),
+        Message(
+            from = null,
+            message = "The air bites shrewdly; it is very cold.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "It is a nipping and an eager air.", time = "1 day ago", delivered = true),
+        Message(from = null, message = "What hour now?", time = "18 hrs. ago", delivered = true),
+        Message(from = "Bob", message = "I think it lacks of twelve.", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "No, it is struck.", time = "2 min. ago", delivered = false),
+        Message(
+            from = null,
+            message = "The air bites shrewdly; it is very cold.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(
+            from = null,
+            message = "The air bites shrewdly; it is very cold.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "It is a nipping and an eager air.", time = "1 day ago", delivered = true),
+        Message(from = null, message = "What hour now?", time = "18 hrs. ago", delivered = true),
+        Message(from = "Bob", message = "I think it lacks of twelve.", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "No, it is struck.", time = "2 min. ago", delivered = false),
+        Message(from = "Bob", message = "It is a nipping and an eager air.", time = "1 day ago", delivered = true),
+        Message(from = null, message = "What hour now?", time = "18 hrs. ago", delivered = true),
+        Message(from = "Bob", message = "I think it lacks of twelve.", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "No, it is struck.", time = "2 min. ago", delivered = false),
+        Message(
+            from = "Bob",
+            message = "Indeed? I heard it not: then it draws near the season Wherein the spirit held his wont to walk. A flourish of trumpets, and ordnance shot off, within. What does this mean, my lord?",
+            time = "2 min. ago",
+            delivered = false
+        )
+    )
+    val msg3: List<Message> = listOf<Message>(
+        Message(
+            from = null,
+            message = "Give him this money and these notes, Reynaldo.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "I will, my lord.", time = "1 day ago", delivered = true),
+        Message(
+            from = null,
+            message = "You shall do marvellous wisely, good Reynaldo,Before you visit him, to make inquireOf his behavior.",
+            time = "18 hrs. ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "My lord, I did intend it.", time = "12 min. ago", delivered = true),
+        Message(
+            from = null,
+            message = "Marry, well said; very well said. Look you, sir,Inquire me first what Danskers are in Paris;And how, and who, what means, and where they keep,What company, at what expense; and findingBy this encompassment and drift of questionThat they do know my son, come you more nearerThan your particular demands will touch it:Take you, as ’twere, some distant knowledge of him;As thus, ‘I know his father and his friends,And in part him: ‘ do you mark this, Reynaldo?",
+            time = "2 min. ago",
+            delivered = false
+        ),
+    )
+    val msg4: List<Message> = listOf<Message>(
+        Message(
+            from = "Bob",
+            message = "So art thou to revenge, when thou shalt hear.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = null, message = "What?", time = "1 day ago", delivered = true),
+        Message(
+            from = "Bob",
+            message = "I am your father’s spirit, doomed for a certain time to walk the night, and for the day to burn in fires, till the foul crimes done during my lifetime have been burnt and purged away. But that I am forbidden to tell the secrets of my prison-house I could tell a tale whose lightest word would shrivel up your soul, freeze your young blood, make your eyes start from their sockets and your hair stand up on end like the quills of a frightened porcupine. But this eternal torture is not for ears of flesh and blood. Listen, oh listen! If you ever loved your dear father ….",
+            time = "18 hrs. ago",
+            delivered = true
+        ),
+        Message(from = null, message = "Oh God!", time = "12 min. ago", delivered = true),
+    )
+    val msg5: List<Message> = listOf<Message>(
+        Message(
+            from = null,
+            message = "Here's a knocking indeed! If a man were porter of hell-gate, he should have old turning the key.  Knocking within Knock, knock, knock! Who's there, i' the name of Beelzebub? Here's a farmer, that hanged himself on the expectation of plenty: come in time; have napkins enow about you; here you'll sweat for't.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(
+            from = null,
+            message = "Knock, knock! Who's there, in the other devil's name? Faith, here's an equivocator, that could swear in both the scales against either scale; who committed treason enough for God's sake, yet could not equivocate to heaven: O, come in, equivocator.",
+            time = "1 day ago",
+            delivered = true
+        ),
+    )
+    val contacts = listOf(
+        Contact(name = "Alice", online = true, profile_pic = "p1.png", last_heard = "now", privateMessages = msg2),
+        Contact(
+            name = "Bob",
+            online = false,
+            profile_pic = "p2.png",
+            last_heard = "22 min. ago",
+            privateMessages = msg1
+        ),
+        Contact(
+            name = "Carl",
+            online = true,
+            profile_pic = "p3.png",
+            last_heard = "2 hr. ago ",
+            privateMessages = msg3
+        ),
+        Contact(name = "Dan", online = false, profile_pic = "p4.png", last_heard = "1 day ago", privateMessages = msg4),
+        Contact(
+            name = "Eve",
+            online = false,
+            profile_pic = "p5.png",
+            last_heard = "3 days ago",
+            privateMessages = msg5
+        ),
+        Contact(
+            name = "Fred",
+            online = false,
+            profile_pic = "p2.png",
+            last_heard = "22 min. ago",
+            privateMessages = msg1
+        ),
+        Contact(
+            name = "Greg",
+            online = true,
+            profile_pic = "p3.png",
+            last_heard = "2 hr. ago ",
+            privateMessages = msg3
+        ),
+        Contact(
+            name = "Harold",
+            online = false,
+            profile_pic = "p4.png",
+            last_heard = "1 day ago",
+            privateMessages = msg4
+        ),
+        Contact(
+            name = "Irene",
+            online = false,
+            profile_pic = "p5.png",
+            last_heard = "3 days ago",
+            privateMessages = msg5
+        ),
+        Contact(
+            name = "Jeanne",
+            online = false,
+            profile_pic = "p2.png",
+            last_heard = "22 min. ago",
+            privateMessages = msg1
+        ),
+        Contact(
+            name = "Karl",
+            online = true,
+            profile_pic = "p3.png",
+            last_heard = "2 hr. ago ",
+            privateMessages = msg3
+        ),
+        Contact(
+            name = "Lorn",
+            online = false,
+            profile_pic = "p4.png",
+            last_heard = "1 day ago",
+            privateMessages = msg4
+        ),
+        Contact(
+            name = "Meg",
+            online = false,
+            profile_pic = "p5.png",
+            last_heard = "3 days ago",
+            privateMessages = msg5
+        ),
+        Contact(
+            name = "Nile",
+            online = false,
+            profile_pic = "p2.png",
+            last_heard = "22 min. ago",
+            privateMessages = msg1
+        ),
+        Contact(
+            name = "Oscar",
+            online = true,
+            profile_pic = "p3.png",
+            last_heard = "2 hr. ago ",
+            privateMessages = msg3
+        ),
+        Contact(
+            name = "Paul",
+            online = false,
+            profile_pic = "p4.png",
+            last_heard = "1 day ago",
+            privateMessages = msg4
+        ),
+        Contact(name = "Qi", online = false, profile_pic = "p5.png", last_heard = "3 days ago", privateMessages = msg5),
+    )
+}
+
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/data/ContentType.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/ContentType.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e29adb5f0b1379a0e3ea73b9f1ef62ae82c8866f
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/ContentType.kt
@@ -0,0 +1,16 @@
+package org.briarproject.briar.desktop.paul.data
+
+import org.briarproject.briar.desktop.paul.model.ContentType
+
+object ContentTypeList {
+    val types = listOf(
+        ContentType(id = -1, name = "Profile"),
+        ContentType(id = 0, name = "Contacts"),
+        ContentType(id = 1, name = "Private Groups"),
+        ContentType(id = 2, name = "Forums"),
+        ContentType(id = 3, name = "Blogs"),
+        ContentType(id = 4, name = "Transports"),
+        ContentType(id = 5, name = "Settings"),
+        ContentType(id = 6, name = "Sign Out")
+    )
+}
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/data/OptionType.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/OptionType.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5dbb5d8e4c787a8cb0dd04b2a699f2130953c103
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/OptionType.kt
@@ -0,0 +1,14 @@
+package org.briarproject.briar.desktop.paul.data
+
+import org.briarproject.briar.desktop.paul.model.OptionType
+
+object OptionTypeList {
+    val msgTypes = listOf(
+        OptionType(name = "Alice", unread = 2, online = true),
+        OptionType(name = "Bob", unread = 0, online = true),
+        OptionType(name = "Carl", unread = 0, online = false),
+        OptionType(name = "Dan", unread = 1, online = false),
+        OptionType(name = "Eve", unread = 0, online = false),
+    )
+}
+
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Contact.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Contact.kt
new file mode 100644
index 0000000000000000000000000000000000000000..22085dff5b7b3e44c920e725b2bbd8c8ab076399
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Contact.kt
@@ -0,0 +1,9 @@
+package org.briarproject.briar.desktop.paul.model
+
+data class Contact(
+    val name: String,
+    val online: Boolean,
+    val profile_pic: String,
+    val last_heard: String,
+    val privateMessages: List<Message>
+)
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/model/ContentType.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/ContentType.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0db88d307147c6363aafda082ed5947aaeb35bd3
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/ContentType.kt
@@ -0,0 +1,7 @@
+package org.briarproject.briar.desktop.paul.model
+
+data class ContentType(
+    val id: Int,
+    val name: String,
+    //val icon: Icon,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Message.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Message.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a7a79f553ff1f7be360faeade89114e2c9aba9a0
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Message.kt
@@ -0,0 +1,9 @@
+package org.briarproject.briar.desktop.paul.model
+
+data class Message(
+    val from: String?,
+    val message: String,
+    val time: String,
+    val delivered: Boolean,
+    //val read: Boolean,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/model/OptionType.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/OptionType.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8367e1eb877d0490a3151f2a29407db710f33de3
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/OptionType.kt
@@ -0,0 +1,9 @@
+package org.briarproject.briar.desktop.paul.model
+
+data class OptionType(
+    val name: String,
+    val unread: Int,
+    val online: Boolean
+    //val icon: Icon,
+)
+
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/theme/colors.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/theme/colors.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2d443639eed3b1057ae27d4072d07fefd1f8d106
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/theme/colors.kt
@@ -0,0 +1,32 @@
+package org.briarproject.briar.desktop.paul.theme
+
+import androidx.compose.material.darkColors
+import androidx.compose.ui.graphics.Color
+
+val graySurface = Color(0xFF2A2A2A)
+val lightGray = Color(0xFFD3D3D3)
+val briarGray = Color(0xff222222)
+val briarBlack = Color(0xff1E2228)
+val briarSelBlack = Color(0xff495261)
+val briarDarkGray = Color(0xFF3D4552)
+val darkGray = Color(0xFF151515)
+val divider = Color(0xff35383D)
+val briarBlue = Color(0xFF2D3E50)
+val briarLightBlue = Color(0xFFEBEFF2)
+val briarGreen = Color(0xFF97D323)
+val briarBlueMsg = Color(0xFF1b69b6)
+val briarBlueSpecialMsg = Color(0xFF134a80)
+val briarGrayMsg = Color(0xff3b4047)
+val briarGraySpecialMsg = Color(0xFF212d3b)
+
+val DarkColorPallet = darkColors(
+    primary = Color.White,
+    secondary = graySurface,
+    background = briarLightBlue,
+    surface = briarBlue,
+    onPrimary = Color.White,
+    onSecondary = lightGray,
+    onBackground = Color.White,
+    onSurface = Color.White,
+    error = Color.Red,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarSidebar.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarSidebar.kt
new file mode 100644
index 0000000000000000000000000000000000000000..85454f9c579868ced390782a84a93bb025006362
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarSidebar.kt
@@ -0,0 +1,103 @@
+package org.briarproject.briar.desktop.paul.views
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
+import androidx.compose.material.Surface
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.*
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.imageFromResource
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.dp
+import org.briarproject.briar.desktop.paul.theme.briarBlack
+import org.briarproject.briar.desktop.paul.theme.briarBlue
+
+@Composable
+fun briarSidebar(UIMode: String, onModeChange: (String) -> Unit) {
+    Surface(modifier = Modifier.width(66.dp).fillMaxHeight(), color = briarBlue) {
+        Column(verticalArrangement = Arrangement.Top) {
+            IconButton(
+                modifier = Modifier.align(Alignment.CenterHorizontally)
+                    .padding(top = 9.dp, bottom = 10.dp), onClick = {}) {
+                Image(
+                    bitmap = imageFromResource("images/profile_images/p0.png"),
+                    "my_profile_image",
+                    modifier = Modifier.size(48.dp).align(Alignment.CenterHorizontally).clip(
+                        CircleShape
+                    ).border(2.dp, color = Color.White, CircleShape)
+                )
+            }
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Contacts",
+                Icons.Filled.Contacts
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Private Groups",
+                Icons.Filled.Group
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Forums",
+                Icons.Filled.Forum
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Blogs",
+                Icons.Filled.ChromeReaderMode
+            )
+        }
+        Column(verticalArrangement = Arrangement.Bottom) {
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Transports",
+                Icons.Filled.WifiTethering
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Settings",
+                Icons.Filled.Settings
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Sign Out",
+                Icons.Filled.Logout
+            )
+        }
+    }
+}
+
+@Composable
+fun briarSidebarButton(
+    UIMode: String,
+    onModeChange: (String) -> Unit,
+    thisMode: String,
+    icon: ImageVector
+) {
+    val bg = if (UIMode == thisMode) briarBlack else briarBlue;
+    Column() {
+        IconButton(
+            modifier = Modifier.align(Alignment.CenterHorizontally).background(color = bg)
+                .padding(vertical = 9.dp, horizontal = 12.dp),
+            onClick = { onModeChange(thisMode) }) {
+            Icon(icon, thisMode, tint = Color.White, modifier = Modifier.size(30.dp))
+        }
+    }
+}
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarUIStateManager.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarUIStateManager.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a58fa8f036d6c3b345a5bb161e695c217508ee64
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarUIStateManager.kt
@@ -0,0 +1,51 @@
+package org.briarproject.briar.desktop.paul.views
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import org.briarproject.briar.desktop.paul.data.ContactList
+import org.briarproject.briar.desktop.paul.theme.briarBlack
+
+/*
+ * This is the root of the tree, all state is held here and passed down to stateless composables, which render the UI
+ * Desktop specific kotlin files are found in briarComposeDesktop (possibly briar-compose-desktop project in the future)
+ * Multiplatform, stateless, composable are found in briarCompose (possible briar-compose project in the future)
+ */
+@Composable
+fun briarUIStateManager() {
+    //current selected mode, changed using the sidebar buttons
+    val (UIMode, onModeChange) = remember { mutableStateOf("Contacts") }
+    //current selected contact
+    val (UIContact, onContactSelect) = remember { mutableStateOf(ContactList.contacts[0]) }
+    //current selected private message
+    val (UIPrivateMsg, onPMSelect) = remember { mutableStateOf(0) }
+    //current selected forum
+    val (UIForum, onForumSelect) = remember { mutableStateOf(0) }
+    //current blog state
+    val (UIBlog, onBlogSelect) = remember { mutableStateOf(0) }
+    //current transport state
+    val (UITransports, onTransportSelect) = remember { mutableStateOf(0) }
+    //current settings state
+    val (UISettings, onSettingSelect) = remember { mutableStateOf(0) }
+    //current profile
+    var Profile: String;
+    //Other global state that we need to track should go here also
+    Row() {
+        briarSidebar(UIMode, onModeChange)
+        when (UIMode) {
+            "Contacts" -> privateMessageView(UIContact, onContactSelect)
+            else -> Box(modifier = Modifier.fillMaxSize().background(briarBlack)) {
+                Text("TBD", modifier = Modifier.align(Alignment.Center), color = Color.White)
+            }
+        }
+    }
+
+}
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/views/PrivateMessageView.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/PrivateMessageView.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fc8544d5e9e8ffa10511fbe91471f9f0db732188
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/PrivateMessageView.kt
@@ -0,0 +1,319 @@
+package org.briarproject.briar.desktop.paul.views
+
+import androidx.compose.foundation.*
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material.*
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.imageFromResource
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.compose.ui.window.v1.DialogProperties
+import org.briarproject.briar.desktop.paul.data.ContactList
+import org.briarproject.briar.desktop.paul.model.Contact
+import org.briarproject.briar.desktop.paul.model.Message
+import org.briarproject.briar.desktop.paul.theme.*
+
+
+val HEADER_SIZE = 66.dp;
+
+@Composable
+fun privateMessageView(UIContact: Contact, onContactSelect: (Contact) -> Unit) {
+    //Local State for managing the Add Contact Popup
+    val (AddContactDialog, onCancelAdd) = remember { mutableStateOf(false) }
+    addContactDialog(AddContactDialog, onCancelAdd)
+    Column(modifier = Modifier.fillMaxHeight()) {
+        Row(modifier = Modifier.fillMaxWidth()) {
+            Divider(color = divider, modifier = Modifier.fillMaxHeight().width(1.dp))
+            Column(modifier = Modifier.fillMaxHeight().background(color = briarBlack).width(275.dp)) {
+                Row(
+                    modifier = Modifier.fillMaxWidth().height(HEADER_SIZE).padding(horizontal = 16.dp),
+                    horizontalArrangement = Arrangement.SpaceBetween,
+                ) {
+                    Text(
+                        "Contacts",
+                        fontSize = 24.sp,
+                        color = Color.White,
+                        modifier = Modifier.align(Alignment.CenterVertically)
+                    )
+                    IconButton(
+                        onClick = { onCancelAdd(true) },
+                        modifier = Modifier.align(Alignment.CenterVertically).background(color = briarDarkGray)
+                    ) {
+                        Icon(Icons.Filled.Add, "add contact", tint = Color.White, modifier = Modifier.size(24.dp))
+                    }
+                }
+                Divider(color = divider, thickness = 1.dp, modifier = Modifier.fillMaxWidth())
+                Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
+                    for (c in ContactList.contacts) {
+                        contactCard(c, UIContact, onSel = onContactSelect)
+                    }
+                }
+
+            }
+            Divider(color = divider, modifier = Modifier.fillMaxHeight().width(1.dp))
+            Column(modifier = Modifier.weight(1f).fillMaxHeight().background(color = darkGray)) {
+                drawMessageRow(UIContact)
+            }
+        }
+    }
+}
+
+@Composable
+fun addContactDialog(isVisible: Boolean, onCancel: (Boolean) -> Unit) {
+    if (isVisible) {
+        AlertDialog(
+            onDismissRequest = {
+                onCancel(false)
+            },
+            text = {
+                Column(modifier = Modifier.fillMaxWidth()) {
+                    Row(Modifier.fillMaxWidth().padding(vertical = 16.dp)) {
+                        Text(
+                            text = "Add Contact at a Distance",
+                            fontSize = 24.sp,
+                            color = Color.White,
+                            modifier = Modifier.align(Alignment.CenterVertically)
+                        )
+                    }
+                    Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
+                        Text(
+                            "Contact's Link",
+                            Modifier.width(128.dp).align(Alignment.CenterVertically),
+                            color = lightGray
+                        )
+                        TextField("", onValueChange = {}, modifier = Modifier.fillMaxWidth())
+                    }
+                    Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
+                        Text(
+                            "Contact's Name",
+                            Modifier.width(128.dp).align(Alignment.CenterVertically),
+                            color = lightGray
+                        )
+                        TextField("", onValueChange = {}, modifier = Modifier.fillMaxWidth())
+                    }
+                    Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
+                        Text(
+                            "Your Link",
+                            modifier = Modifier.width(128.dp).align(Alignment.CenterVertically),
+                            color = lightGray
+                        )
+                        TextField(
+                            "briar://ksdjlfgakslhjgaklsjdhglkasjdlk3j12h4lk2j3tkj4",
+                            onValueChange = {},
+                            modifier = Modifier.fillMaxWidth()
+                        );
+                    }
+                }
+            },
+            confirmButton = {
+                TextButton(
+                    onClick = {
+                        onCancel(false)
+                    },
+                    modifier = Modifier.background(briarGreen)
+                ) {
+                    Text("Add")
+                }
+            },
+            dismissButton = {
+                TextButton(
+                    onClick = {
+                        onCancel(false)
+                    }, modifier = Modifier.background(briarBlack)
+                ) {
+                    Text("Cancel")
+                }
+            },
+
+            backgroundColor = briarBlue,
+            contentColor = Color.White,
+            modifier = Modifier.border(1.dp, color = divider),
+            properties = DialogProperties(resizable = false, undecorated = true, size = IntSize(600, 300))
+        )
+    }
+}
+
+@Composable
+fun contactCard(contact: Contact, selContact: Contact, onSel: (Contact) -> Unit) {
+    var bgColor = briarBlack
+    if (selContact.name == contact.name) {
+        bgColor = darkGray
+    }
+    Row(
+        modifier = Modifier.fillMaxWidth().height(HEADER_SIZE).background(bgColor)
+            .clickable(onClick = { onSel(contact) }), horizontalArrangement = Arrangement.SpaceBetween
+    ) {
+        Row(modifier = Modifier.align(Alignment.CenterVertically).padding(horizontal = 16.dp)) {
+            Image(
+                bitmap = imageFromResource("images/profile_images/" + contact.profile_pic),
+                "image",
+                modifier = Modifier.size(40.dp).align(Alignment.CenterVertically).clip(
+                    CircleShape
+                ).border(2.dp, color = Color.White, CircleShape)
+            )
+            Column(modifier = Modifier.align(Alignment.CenterVertically).padding(start = 12.dp)) {
+                Text(
+                    contact.name,
+                    fontSize = 14.sp,
+                    color = Color.White,
+                    modifier = Modifier.align(Alignment.Start).padding(bottom = 2.dp)
+                )
+                Text(
+                    contact.last_heard,
+                    fontSize = 10.sp,
+                    color = Color.LightGray,
+                    modifier = Modifier.align(Alignment.Start)
+                )
+            }
+        }
+        androidx.compose.foundation.Canvas(
+            modifier = Modifier.padding(horizontal = 29.dp).size(22.dp).align(Alignment.CenterVertically), onDraw = {
+                val size = 16.dp.toPx()
+                drawCircle(
+                    color = Color.White,
+                    radius = size / 2f
+                )
+                if (contact.online) {
+                    drawCircle(
+                        color = briarGreen,
+                        radius = 14.dp.toPx() / 2f
+                    )
+                } else {
+                    drawCircle(
+                        color = briarBlack,
+                        radius = 14.dp.toPx() / 2f
+                    )
+                }
+            })
+    }
+
+    Divider(color = divider, thickness = 1.dp, modifier = Modifier.fillMaxWidth())
+}
+
+@Composable
+fun textBubble(m: Message) {
+    Column(Modifier.fillMaxWidth()) {
+        if (m.from == null) {
+            Column(Modifier.fillMaxWidth(fraction = 0.9f).align(Alignment.End)) {
+                Column(Modifier.background(briarBlueMsg).padding(8.dp).align(Alignment.End)) {
+                    Text(m.message, fontSize = 14.sp, color = Color.White, modifier = Modifier.align(Alignment.Start))
+                    Row(modifier = Modifier.padding(top = 4.dp)) {
+                        Text(m.time, Modifier.padding(end = 4.dp), fontSize = 10.sp, color = Color.LightGray)
+                        if (m.delivered) {
+                            Icon(
+                                Icons.Filled.Check,
+                                "sent",
+                                tint = Color.LightGray,
+                                modifier = Modifier.size(10.dp).align(Alignment.CenterVertically)
+                            )
+                        } else {
+                            Icon(
+                                Icons.Filled.Send,
+                                "sending",
+                                tint = Color.LightGray,
+                                modifier = Modifier.size(10.dp).align(Alignment.CenterVertically)
+                            )
+                        }
+                    }
+                }
+            }
+        } else {
+            Column(Modifier.fillMaxWidth(fraction = 0.9f).align(Alignment.Start)) {
+                Column(Modifier.background(briarGrayMsg).padding(8.dp).align(Alignment.Start)) {
+                    Text(m.message, fontSize = 14.sp, color = Color.White, modifier = Modifier.align(Alignment.Start))
+                    Row(modifier = Modifier.padding(top = 4.dp)) {
+                        Text(m.time, Modifier.padding(end = 4.dp), fontSize = 10.sp, color = Color.LightGray)
+                        if (m.delivered) {
+                            Icon(
+                                Icons.Filled.Check,
+                                "sent",
+                                tint = Color.LightGray,
+                                modifier = Modifier.size(10.dp).align(Alignment.CenterVertically)
+                            )
+                        } else {
+                            Icon(
+                                Icons.Filled.Send,
+                                "sending",
+                                tint = Color.LightGray,
+                                modifier = Modifier.size(10.dp).align(Alignment.CenterVertically)
+                            )
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+@Composable
+fun drawTextBubbles(msgList: List<Message>) {
+    LazyColumn(
+        Modifier.fillMaxWidth().padding(horizontal = 8.dp),
+        verticalArrangement = Arrangement.spacedBy(8.dp),
+        reverseLayout = true,
+        contentPadding = PaddingValues(vertical = 8.dp)
+    ) {
+        items(msgList) { m ->
+            textBubble(m)
+        }
+    }
+}
+
+@Composable
+fun drawMessageRow(UIContact: Contact) {
+    Box(Modifier.fillMaxHeight()) {
+        Box(modifier = Modifier.fillMaxWidth().height(HEADER_SIZE + 1.dp)) {
+            Row(modifier = Modifier.align(Alignment.Center)) {
+                Image(
+                    bitmap = imageFromResource("images/profile_images/" + UIContact.profile_pic),
+                    "sel_contact_prof",
+                    modifier = Modifier.size(36.dp).align(
+                        Alignment.CenterVertically
+                    ).clip(
+                        CircleShape
+                    ).border(2.dp, color = Color.White, CircleShape)
+                )
+                Text(
+                    UIContact.name,
+                    color = Color.White,
+                    modifier = Modifier.align(Alignment.CenterVertically).padding(start = 12.dp),
+                    fontSize = 24.sp
+                )
+            }
+            IconButton(onClick = {}, modifier = Modifier.align(Alignment.CenterEnd).padding(end = 16.dp)) {
+                Icon(Icons.Filled.MoreVert, "contact info", tint = Color.White, modifier = Modifier.size(24.dp))
+            }
+            Divider(color = divider, thickness = 1.dp, modifier = Modifier.fillMaxWidth().align(Alignment.BottomCenter))
+        }
+        Box(Modifier.padding(top = HEADER_SIZE + 1.dp, bottom = HEADER_SIZE)) {
+            drawTextBubbles(UIContact.privateMessages)
+        }
+        var text by remember { mutableStateOf(TextFieldValue("")) }
+        Box(Modifier.align(Alignment.BottomCenter).background(darkGray)) {
+            OutlinedTextField(
+                value = text,
+                trailingIcon = { Icon(Icons.Filled.Send, "send message", tint = briarGreen) },
+                leadingIcon = { Icon(Icons.Filled.AddCircle, contentDescription = "add file") },
+                modifier = Modifier.padding(start = 8.dp, end = 8.dp, bottom = 8.dp).fillMaxWidth(),
+                label = { Text(text = "Message") },
+                textStyle = TextStyle(color = Color.White),
+                placeholder = { Text(text = "Your message to " + UIContact.name) },
+                onValueChange = {
+                    text = it
+                },
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/resources/images/profile_images/p0.png b/src/main/resources/images/profile_images/p0.png
new file mode 100644
index 0000000000000000000000000000000000000000..8c67a3c592c8267f56a4c810cb2d561c88d05e18
Binary files /dev/null and b/src/main/resources/images/profile_images/p0.png differ
diff --git a/src/main/resources/images/profile_images/p1.png b/src/main/resources/images/profile_images/p1.png
new file mode 100644
index 0000000000000000000000000000000000000000..50155c8a1ebc3513e3b6e3cc2936881b594f92f4
Binary files /dev/null and b/src/main/resources/images/profile_images/p1.png differ
diff --git a/src/main/resources/images/profile_images/p2.png b/src/main/resources/images/profile_images/p2.png
new file mode 100644
index 0000000000000000000000000000000000000000..8ff9a6e10f151d8e9913a968a535cf7b3e542c0f
Binary files /dev/null and b/src/main/resources/images/profile_images/p2.png differ
diff --git a/src/main/resources/images/profile_images/p3.png b/src/main/resources/images/profile_images/p3.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b8509e1e21afe1863ad0d35395ef11cdd9113b4
Binary files /dev/null and b/src/main/resources/images/profile_images/p3.png differ
diff --git a/src/main/resources/images/profile_images/p4.png b/src/main/resources/images/profile_images/p4.png
new file mode 100644
index 0000000000000000000000000000000000000000..96ed7fbc717af1d66c71fd5b9376b6a32dfc6e5b
Binary files /dev/null and b/src/main/resources/images/profile_images/p4.png differ
diff --git a/src/main/resources/images/profile_images/p5.png b/src/main/resources/images/profile_images/p5.png
new file mode 100644
index 0000000000000000000000000000000000000000..72348d6d73b3a8cb15aa7f1269e5e980256c7388
Binary files /dev/null and b/src/main/resources/images/profile_images/p5.png differ