diff --git a/build.gradle.kts b/build.gradle.kts
index 10d1dab29ba1a521d92a7f756572275c71131820..006fc3bb7e2fcd38aedbbf8984a81b849721e73b 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -22,8 +22,11 @@ repositories {
 dependencies {
     testImplementation(kotlin("test-testng"))
     implementation(compose.desktop.currentOs)
+    implementation("com.fasterxml.jackson.core:jackson-databind:2.10.0")
     implementation(project(path = ":briar:briar-core", configuration = "default"))
     implementation(project(path = ":briar:bramble-java", configuration = "default"))
+    val daggerVersion = "2.24"
+    kapt("com.google.dagger:dagger-compiler:$daggerVersion")
 }
 
 tasks.test {
diff --git a/src/main/kotlin/main.kt b/src/main/kotlin/main.kt
deleted file mode 100644
index 2faebd09932f5078d3b79fec926e1605ebf7bd72..0000000000000000000000000000000000000000
--- a/src/main/kotlin/main.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-import androidx.compose.desktop.Window
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.*
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.Text
-import androidx.compose.material.Button
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.MaterialTheme.typography
-import androidx.compose.runtime.*
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.res.imageResource
-import androidx.compose.ui.res.svgResource
-import androidx.compose.ui.res.vectorXmlResource
-import androidx.compose.ui.unit.dp
-
-fun main() = Window {
-    Column(
-        modifier = Modifier.padding(16.dp)
-    ) {
-        TheImage()
-        Spacer(Modifier.height(32.dp))
-        TheText()
-        TheButton()
-    }
-}
-
-@Composable
-private fun TheButton() {
-    var text by remember { mutableStateOf("Start chatting") }
-    Button(onClick = {
-        text = "Sorry, not yet available"
-    }) {
-        Text(text)
-    }
-}
-
-@Composable
-private fun TheImage() {
-    Image(
-        painter = svgResource("images/logo_circle.svg"),
-        contentDescription = "Briar logo",
-        modifier = Modifier
-            .fillMaxWidth()
-            .clip(shape = RoundedCornerShape(400.dp))
-    )
-}
-
-@Composable
-private fun TheText() {
-    Text("Welcome to Briar")
-}
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/compose/BriarService.kt b/src/main/kotlin/org/briarproject/briar/compose/BriarService.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9a5912a716ec8774ec79bfd920785eb66fd815db
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/compose/BriarService.kt
@@ -0,0 +1,81 @@
+package org.briarproject.briar.compose
+
+//import com.github.ajalt.clikt.core.UsageError
+//import com.github.ajalt.clikt.output.TermUi.echo
+import org.briarproject.bramble.api.account.AccountManager
+import org.briarproject.bramble.api.crypto.DecryptionException
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator
+import org.briarproject.bramble.api.lifecycle.LifecycleManager
+//import org.briarproject.briar.swing.AccountUtil.Companion.check
+//import org.briarproject.briar.swing.dialogs.NewAccountPrompt
+//import org.briarproject.briar.swing.dialogs.PasswordPrompt
+import javax.annotation.concurrent.Immutable
+import javax.inject.Inject
+import javax.inject.Singleton
+import javax.swing.JOptionPane
+import kotlin.system.exitProcess
+
+interface BriarService {
+    fun start()
+    fun stop()
+}
+
+@Immutable
+@Singleton
+internal class BriarServiceImpl
+@Inject
+constructor(
+    private val accountManager: AccountManager,
+    private val lifecycleManager: LifecycleManager,
+    private val passwordStrengthEstimator: PasswordStrengthEstimator
+) : BriarService {
+
+    override fun start() {
+        if (!accountManager.accountExists()) {
+            createAccount();
+        } else {
+            while (true) {
+//                val password = PasswordPrompt.promptForPassword();
+//                if (!password.isValid) {
+//                    // this happens when dismissing the dialog or clicking 'cancel'
+//                    exitProcess(1)
+//                }
+                val password = "sdifjasdjhfksjadf"
+                try {
+                    accountManager.signIn(password)
+                    break
+                } catch (e: DecryptionException) {
+                    JOptionPane.showMessageDialog(
+                        null, "Wrong password",
+                        "Error", JOptionPane.ERROR_MESSAGE
+                    )
+                }
+            }
+        }
+        val dbKey = accountManager.databaseKey ?: throw AssertionError()
+        lifecycleManager.startServices(dbKey)
+        lifecycleManager.waitForStartup()
+    }
+
+    override fun stop() {
+        lifecycleManager.stopServices()
+        lifecycleManager.waitForShutdown()
+    }
+
+    private fun createAccount() {
+//        echo("No account found. Let's create one!\n\n")
+//        val result = NewAccountPrompt.promptForDetails();
+//        if (!result.isValid) {
+//            echo("Error: Please enter a username and password")
+//            exitProcess(1)
+//        }
+//        try {
+//            check(passwordStrengthEstimator, result)
+//        } catch (e: UsageError) {
+//            return;
+//        }
+
+        accountManager.createAccount("Nico", "sdifjasdjhfksjadf")
+    }
+
+}
diff --git a/src/main/kotlin/org/briarproject/briar/compose/BriarSwingApp.kt b/src/main/kotlin/org/briarproject/briar/compose/BriarSwingApp.kt
new file mode 100644
index 0000000000000000000000000000000000000000..74737afbc7c2dea9efb8d94cf437e3309ae5fa00
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/compose/BriarSwingApp.kt
@@ -0,0 +1,25 @@
+package org.briarproject.briar.compose
+
+import dagger.Component
+import org.briarproject.bramble.BrambleCoreEagerSingletons
+import org.briarproject.bramble.BrambleCoreModule
+import org.briarproject.briar.BriarCoreEagerSingletons
+import org.briarproject.briar.BriarCoreModule
+import java.security.SecureRandom
+import javax.inject.Singleton
+
+@Component(
+    modules = [
+        BrambleCoreModule::class,
+        BriarCoreModule::class,
+        SwingModule::class
+    ]
+)
+@Singleton
+internal interface BriarSwingApp : BrambleCoreEagerSingletons, BriarCoreEagerSingletons {
+
+    fun getUI(): UI
+
+    fun getSecureRandom(): SecureRandom
+
+}
diff --git a/src/main/kotlin/org/briarproject/briar/compose/MainUI.java b/src/main/kotlin/org/briarproject/briar/compose/MainUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b33d76cb2e14ffe96b835e600e233c0213fdc70
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/compose/MainUI.java
@@ -0,0 +1,215 @@
+package org.briarproject.briar.compose;
+
+import org.briarproject.bramble.api.account.AccountManager;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.briar.api.conversation.ConversationManager;
+import org.briarproject.briar.api.conversation.ConversationMessageHeader;
+import org.briarproject.briar.api.introduction.IntroductionManager;
+import org.briarproject.briar.api.messaging.MessagingManager;
+import org.briarproject.briar.api.messaging.PrivateMessageFactory;
+//import org.briarproject.briar.swing.actions.AboutAction;
+//import org.briarproject.briar.swing.actions.AddContactAction;
+//import org.briarproject.briar.swing.actions.ChangePasswordAction;
+//import org.briarproject.briar.swing.actions.CloseChatAction;
+//import org.briarproject.briar.swing.actions.QuitAction;
+//import org.briarproject.briar.swing.actions.SettingsAction;
+//import org.briarproject.briar.swing.chat.Chat;
+import org.briarproject.briar.compose.config.Configuration;
+//import org.briarproject.briar.swing.contactlist.ContactList;
+//import org.briarproject.briar.swing.contactlist.ContactListModel;
+//import org.briarproject.briar.swing.contactlist.ContactWithMeta;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.Collection;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JToolBar;
+import javax.swing.UIManager;
+
+//import de.topobyte.awt.util.GridBagConstraintsEditor;
+
+public class MainUI extends JFrame implements EventListener {
+
+	final static Logger logger = LoggerFactory.getLogger(MainUI.class);
+
+	private final BriarService briarService;
+	private final AccountManager accountManager;
+	private final ContactManager contactManager;
+	private final ConversationManager conversationManager;
+	private final MessagingManager messagingManager;
+	private final IntroductionManager introductionManager;
+	private final PrivateMessageFactory privateMessageFactory;
+	private final EventBus eventBus;
+	private final PasswordStrengthEstimator passwordStrengthEstimator;
+	private final Configuration configuration;
+
+	private JPanel mainPanel;
+	private JPanel contentPanel;
+//	private ContactList contactList;
+//	private Chat chat;
+
+//	private ContactListModel contactListModel;
+
+	public MainUI(BriarService briarService,
+			AccountManager accountManager,
+			ContactManager contactManager,
+			ConversationManager conversationManager,
+			MessagingManager messagingManager,
+			IntroductionManager introductionManager,
+			PrivateMessageFactory privateMessageFactory,
+			EventBus eventBus,
+			PasswordStrengthEstimator passwordStrengthEstimator,
+			Configuration configuration) {
+		this.briarService = briarService;
+		this.accountManager = accountManager;
+		this.contactManager = contactManager;
+		this.conversationManager = conversationManager;
+		this.messagingManager = messagingManager;
+		this.introductionManager = introductionManager;
+		this.privateMessageFactory = privateMessageFactory;
+		this.eventBus = eventBus;
+		this.passwordStrengthEstimator = passwordStrengthEstimator;
+		this.configuration = configuration;
+
+		String lookAndFeel = configuration.getLookAndFeel();
+		if (lookAndFeel != null) {
+			try {
+				UIManager.setLookAndFeel(lookAndFeel);
+			} catch (Exception e) {
+				logger.error("error while setting look and feel", e);
+			}
+		}
+
+		setTitle("Briar Swing");
+//		setJMenuBar(new MainMenu(this));
+
+		JToolBar toolbar = new JToolBar();
+		toolbar.setFloatable(false);
+//		toolbar.add(new AddContactAction(this));
+//		toolbar.add(new ChangePasswordAction(this));
+//		toolbar.add(new SettingsAction(this));
+//		toolbar.add(new CloseChatAction(this));
+//		toolbar.add(new QuitAction());
+//		toolbar.add(new AboutAction(this));
+
+		mainPanel = new JPanel(new BorderLayout());
+		setContentPane(mainPanel);
+
+		contentPanel = new JPanel(new GridBagLayout());
+		addComponents();
+
+		mainPanel.add(toolbar, BorderLayout.NORTH);
+		mainPanel.add(contentPanel, BorderLayout.CENTER);
+
+//		EventBusConnector eventBusConnector =
+//				new EventBusConnector(messagingManager);
+//		eventBus.addListener(eventBusConnector);
+//		eventBus.addListener(this);
+	}
+
+	public Configuration getConfiguration() {
+		return configuration;
+	}
+
+	public AccountManager getAccountManager() {
+		return accountManager;
+	}
+
+	public ContactManager getContactManager() {
+		return contactManager;
+	}
+
+	public PasswordStrengthEstimator getPasswordStrengthEstimator() {
+		return passwordStrengthEstimator;
+	}
+
+	private void addComponents() {
+		GridBagConstraints c = new GridBagConstraints();
+//		GridBagConstraintsEditor ce =
+//				new GridBagConstraintsEditor(c);
+//
+//		contactList = new ContactList();
+//		chat = new Chat(conversationManager, messagingManager,
+//				introductionManager, privateMessageFactory, eventBus);
+//
+//		ce.fill(GridBagConstraints.BOTH);
+//
+//		ce.gridPos(0, 0);
+//		ce.weight(3, 1);
+//		contentPanel.add(contactList, c);
+//
+//		ce.gridPos(1, 0);
+//		ce.weight(7, 1);
+//		contentPanel.add(chat, c);
+//
+//		reloadContactList();
+//
+//		contactList.addContactSelectedListener(this::displayChatHistory);
+	}
+
+	public void closeChat() {
+//		chat.displayNone();
+//		contactList.selectNone();
+	}
+
+	private void displayChatHistory(Contact contact) {
+//		chat.displayHistory(contact);
+	}
+
+	private void tryListContacts() {
+		try {
+			listContacts();
+		} catch (DbException e) {
+			e.printStackTrace();
+		}
+	}
+
+	private void listContacts() throws DbException {
+//		Collection<Contact> contacts = contactManager.getContacts();
+//		for (Contact contact : contacts) {
+//			contactListModel.add(new ContactWithMeta(contact), 0);
+//		}
+//		for (int i = 0; i < contactListModel.getSize(); i++) {
+//			ContactWithMeta entry = contactListModel.getElementAt(i);
+//			Contact contact = entry.getContact();
+//			logger.debug(
+//					String.format("%s (%s)", contact.getAuthor().getName(),
+//							contact.getAlias()));
+//			Collection<ConversationMessageHeader> messageHeaders =
+//					conversationManager.getMessageHeaders(contact.getId());
+//			int unread = 0;
+//			for (ConversationMessageHeader header : messageHeaders) {
+//				if (!header.isRead()) {
+//					unread += 1;
+//				}
+//			}
+//			entry.setNumUnreadMessages(unread);
+//		}
+	}
+
+	@Override
+	public void eventOccurred(Event e) {
+		if (e instanceof ContactAddedEvent) {
+			reloadContactList();
+		}
+	}
+
+	private void reloadContactList() {
+//		contactListModel = new ContactListModel();
+//		tryListContacts();
+//		contactList.setModel(contactListModel);
+	}
+
+}
diff --git a/src/main/kotlin/org/briarproject/briar/compose/SwingDatabaseConfig.kt b/src/main/kotlin/org/briarproject/briar/compose/SwingDatabaseConfig.kt
new file mode 100644
index 0000000000000000000000000000000000000000..34154addc0b93817d4a0663b5eaddb1d668cbe31
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/compose/SwingDatabaseConfig.kt
@@ -0,0 +1,15 @@
+package org.briarproject.briar.compose
+
+import org.briarproject.bramble.api.crypto.KeyStrengthener
+import org.briarproject.bramble.api.db.DatabaseConfig
+import java.io.File
+
+internal class SwingDatabaseConfig(private val dbDir: File, private val keyDir: File) :
+    DatabaseConfig {
+
+    override fun getDatabaseDirectory() = dbDir
+
+    override fun getDatabaseKeyDirectory() = keyDir
+
+    override fun getKeyStrengthener(): KeyStrengthener? = null
+}
diff --git a/src/main/kotlin/org/briarproject/briar/compose/SwingModule.kt b/src/main/kotlin/org/briarproject/briar/compose/SwingModule.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cfa67a1e1293c5d816bab8a3b74a30876c19d876
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/compose/SwingModule.kt
@@ -0,0 +1,82 @@
+package org.briarproject.briar.compose
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import dagger.Module
+import dagger.Provides
+import org.briarproject.bramble.account.AccountModule
+import org.briarproject.bramble.api.FeatureFlags
+import org.briarproject.bramble.api.db.DatabaseConfig
+import org.briarproject.bramble.api.plugin.PluginConfig
+import org.briarproject.bramble.api.plugin.TorDirectory
+import org.briarproject.bramble.api.plugin.TransportId
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory
+import org.briarproject.bramble.battery.DefaultBatteryManagerModule
+import org.briarproject.bramble.event.DefaultEventExecutorModule
+import org.briarproject.bramble.network.JavaNetworkModule
+import org.briarproject.bramble.plugin.tor.CircumventionModule
+import org.briarproject.bramble.plugin.tor.UnixTorPluginFactory
+import org.briarproject.bramble.socks.SocksModule
+import org.briarproject.bramble.system.DefaultTaskSchedulerModule
+import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule
+import org.briarproject.bramble.system.DesktopSecureRandomModule
+import org.briarproject.bramble.system.JavaSystemModule
+import org.briarproject.bramble.util.OsUtils.isLinux
+import org.briarproject.bramble.util.OsUtils.isMac
+import java.io.File
+import java.util.Collections.emptyList
+import javax.inject.Singleton
+
+@Module(
+    includes = [
+        AccountModule::class,
+        CircumventionModule::class,
+        DefaultBatteryManagerModule::class,
+        DefaultEventExecutorModule::class,
+        DefaultTaskSchedulerModule::class,
+        DefaultWakefulIoExecutorModule::class,
+        DesktopSecureRandomModule::class,
+        JavaNetworkModule::class,
+        JavaSystemModule::class,
+        SocksModule::class
+    ]
+)
+internal class SwingModule(private val appDir: File) {
+
+    @Provides
+    @Singleton
+    internal fun provideBriarService(briarService: BriarServiceImpl): BriarService = briarService
+
+    @Provides
+    @Singleton
+    internal fun provideDatabaseConfig(): DatabaseConfig {
+        val dbDir = File(appDir, "db")
+        val keyDir = File(appDir, "key")
+        return SwingDatabaseConfig(dbDir, keyDir)
+    }
+
+    @Provides
+    @TorDirectory
+    internal fun provideTorDirectory(): File {
+        return File(appDir, "tor")
+    }
+
+    @Provides
+    internal fun providePluginConfig(tor: UnixTorPluginFactory): PluginConfig {
+        val duplex: List<DuplexPluginFactory> =
+            if (isLinux() || isMac()) listOf(tor) else emptyList()
+        return object : PluginConfig {
+            override fun getDuplexFactories(): Collection<DuplexPluginFactory> = duplex
+            override fun getSimplexFactories(): Collection<SimplexPluginFactory> = emptyList()
+            override fun shouldPoll(): Boolean = true
+            override fun getTransportPreferences(): Map<TransportId, List<TransportId>> = emptyMap()
+        }
+    }
+
+    @Provides
+    @Singleton
+    internal fun provideObjectMapper() = ObjectMapper()
+
+    @Provides
+    internal fun provideFeatureFlags() = FeatureFlags { false }
+}
diff --git a/src/main/kotlin/org/briarproject/briar/compose/UI.kt b/src/main/kotlin/org/briarproject/briar/compose/UI.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cd10bb9c2e4dc1857ca9d4ebcb0bf4682ed1ace4
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/compose/UI.kt
@@ -0,0 +1,68 @@
+package org.briarproject.briar.compose
+
+import org.briarproject.bramble.api.account.AccountManager
+import org.briarproject.bramble.api.contact.ContactManager
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator
+import org.briarproject.bramble.api.event.EventBus
+import org.briarproject.briar.api.conversation.ConversationManager
+import org.briarproject.briar.api.introduction.IntroductionManager
+import org.briarproject.briar.api.messaging.MessagingManager
+import org.briarproject.briar.api.messaging.PrivateMessageFactory
+import org.briarproject.briar.compose.config.Configuration
+import java.util.logging.Logger.getLogger
+import javax.annotation.concurrent.Immutable
+import javax.inject.Inject
+import javax.inject.Singleton
+import javax.swing.JFrame
+
+private const val VERSION = "v1"
+private const val WS = "/$VERSION/ws"
+
+@Immutable
+@Singleton
+internal class UI
+@Inject
+constructor(
+    private val briarService: BriarService,
+    private val accountManager: AccountManager,
+    private val contactManager: ContactManager,
+    private val messagingManager: MessagingManager,
+    private val introductionManager: IntroductionManager,
+    private val conversationManager: ConversationManager,
+    private val privateMessageFactory: PrivateMessageFactory,
+    private val eventBus: EventBus,
+    private val passwordStrengthEstimator: PasswordStrengthEstimator
+) {
+
+    private val logger = getLogger(UI::javaClass.name)
+    private val configuration = Configuration()
+
+    internal fun startBriar() {
+        briarService.start();
+    }
+
+    internal fun startUI() {
+        val mainUI = MainUI(
+            briarService,
+            accountManager,
+            contactManager,
+            conversationManager,
+            messagingManager,
+            introductionManager,
+            privateMessageFactory,
+            eventBus,
+            passwordStrengthEstimator,
+            configuration
+        );
+
+        mainUI.defaultCloseOperation = JFrame.EXIT_ON_CLOSE;
+        mainUI.setSize(800, 600);
+        mainUI.setVisible(true);
+    }
+
+    internal fun getContactManager(): ContactManager {
+        return contactManager
+    }
+
+}
+
diff --git a/src/main/kotlin/org/briarproject/briar/compose/config/Configuration.java b/src/main/kotlin/org/briarproject/briar/compose/config/Configuration.java
new file mode 100644
index 0000000000000000000000000000000000000000..9822305f81c58c27d146968f82956394e92d7b2e
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/compose/config/Configuration.java
@@ -0,0 +1,15 @@
+package org.briarproject.briar.compose.config;
+
+public class Configuration {
+
+	private String lookAndFeel;
+
+	public String getLookAndFeel() {
+		return lookAndFeel;
+	}
+
+	public void setLookAndFeel(String lookAndFeel) {
+		this.lookAndFeel = lookAndFeel;
+	}
+
+}
diff --git a/src/main/kotlin/org/briarproject/briar/compose/main.kt b/src/main/kotlin/org/briarproject/briar/compose/main.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0278c0e628fd37a1cac83bdd1b8383315f4511d5
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/compose/main.kt
@@ -0,0 +1,92 @@
+package org.briarproject.briar.compose
+
+import androidx.compose.desktop.Window
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.Text
+import androidx.compose.material.Button
+import androidx.compose.runtime.*
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.res.svgResource
+import androidx.compose.ui.unit.dp
+import org.briarproject.bramble.BrambleCoreEagerSingletons
+import org.briarproject.briar.BriarCoreEagerSingletons
+import java.io.File
+import java.io.File.separator
+import java.io.IOException
+import java.lang.System.getProperty
+import java.nio.file.Files.setPosixFilePermissions
+import java.nio.file.attribute.PosixFilePermission
+import java.util.logging.Level
+import java.util.logging.LogManager
+
+fun main() = Window {
+    LogManager.getLogManager().getLogger("").level = Level.INFO
+
+    val dataDir = getDataDir()
+    val app =
+        DaggerBriarSwingApp.builder().swingModule(
+            SwingModule(
+                dataDir
+            )
+        ).build()
+    // We need to load the eager singletons directly after making the
+    // dependency graphs
+    BrambleCoreEagerSingletons.Helper.injectEagerSingletons(app)
+    BriarCoreEagerSingletons.Helper.injectEagerSingletons(app)
+
+    app.getUI().startBriar()
+    app.getUI().startUI()
+
+    Column(
+        modifier = Modifier.padding(16.dp)
+    ) {
+        TheImage()
+        Spacer(Modifier.height(32.dp))
+        TheText()
+        TheButton()
+    }
+}
+
+private fun getDataDir(): File {
+    val file = File(getProperty("user.home") + separator + ".briar")
+    if (!file.exists() && !file.mkdirs()) {
+        throw IOException("Could not create directory: ${file.absolutePath}")
+    } else if (!file.isDirectory) {
+        throw IOException("Data dir is not a directory: ${file.absolutePath}")
+    }
+    val perms = HashSet<PosixFilePermission>()
+    perms.add(PosixFilePermission.OWNER_READ)
+    perms.add(PosixFilePermission.OWNER_WRITE)
+    perms.add(PosixFilePermission.OWNER_EXECUTE)
+    setPosixFilePermissions(file.toPath(), perms)
+    return file
+}
+
+@Composable
+private fun TheButton() {
+    var text by remember { mutableStateOf("Start chatting") }
+    Button(onClick = {
+        text = "Sorry, not yet available"
+    }) {
+        Text(text)
+    }
+}
+
+@Composable
+private fun TheImage() {
+    Image(
+        painter = svgResource("images/logo_circle.svg"),
+        contentDescription = "Briar logo",
+        modifier = Modifier
+            .fillMaxWidth()
+            .clip(shape = RoundedCornerShape(400.dp))
+    )
+}
+
+@Composable
+private fun TheText() {
+    Text("Welcome to Briar")
+}
\ No newline at end of file