'Kotlin Multiplatform Compose + Desktop + Web + Mobile

Is it possible at the moment to have a kotlin multiplatform project using compose for sharing the ui code for desktop, web, and mobile at the same time? All the examples i found only cover multiplatform with JS Front + Jvm Backend, or JVM Android + Desktop + Common Module, and I'm having trouble setting a project with all those at the same time.

I tried doing:

plugins {
    kotlin("multiplatform")
    id("org.jetbrains.compose") version "1.0.1-rc2"
    id("com.android.library")
}
kotlin {
    android()
    jvm("desktop") {
       ...
    }
    js{
       ...
    }
    sourceSets {
        val commonMain by getting {
            dependencies {
               ...
            }
        }
        val commonTest by getting {
            dependencies {
               ...
            }
        }
        val androidMain by getting {
            dependencies {
                ...
            }
        }
        val androidTest by getting {
            dependencies {
                ...
            }
        }
        val desktopMain by getting {
            dependencies {
                ...
            }
        }
        val desktopTest by getting
        val jsMain by getting{
            dependencies{
                ...
            }
        }
        val jsTest by getting {
            dependencies {
                ...
            }
        }
    }
}

But it produces the error:

:common:jsMain: Could not resolve org.jetbrains.compose.runtime:runtime:1.0.1-rc2.
Required by:
    project :common

If i comment the JS related sections it works, or if i comment all the non-js related stuff it also works

Commenting everything compose-related also works

The problem is only when combining everything



Solution 1:[1]

The short answer is: No, this is not possible at this time.

I have not been able to reproduce your error, but I assume that you have not removed compose.foundation and compose.material from the common dependencies.

At the moment, only compose.runtime is available for the common module, and this makes it almost impossible to do any layout at this point: even Button and Text are not available.

As you can see in the JS application example, Text is not imported from androidx.compose.material.Text, but from org.jetbrains.compose.web.dom.Text, which is a completely different element, so it cannot be used in a common module.

I heard on some podcast that JetBrains has plans to make it fully multiplatform for JS, but at this point, I would say that Compose JS is another framework that allows you to write UI in code similar to Compose.

Solution 2:[2]

**

This answer is not an exact answer to this question. The correct answer for this is the answer by @PhilipDukhov. However, this might help others who land on this page for finding a solution to the other problem I am just leaving it here. For more info read comments between me and @PhilipDukhov for this answer.

**

Yes, it is possible to have all three modules in a single project. TLDR

I did some workarounds and managed to get all things in a single project i.e

  1. Compose for Desktop
  2. Compose for Android
  3. Compose for Web

Suggestion Before You Go Further

Although below code snippets works and by going through you will be able to achieve what you want actually. I personally recommend you to just go to the Github repository here . I think it will save time if you are creating a new project. However if you are adding web module to current KMM project continue reading.

The problem can be fixed by keeping the correct dependencies

So the project structure should be something like this

enter image description here

Note: If you are creating a new KMM project you will have only common, desktop, and android modules.(As you already know)

Step 1: You need to add the a folder to root (where the android, common,desktop folder is located) call it as web(should not matter)

Step 2: Add several folders to this newly created directory web your web directory should look something like this

enter image description here

Note : Dont add build (its autogenerated) add only

src/jsMain
   -kotlin
   -resources
src/jsTest 
    -kotlin
   -resources

and create a file called build.gradle.kts

Step 3: Change the content of this newly added Gradle file to something like this

import org.jetbrains.compose.compose
import org.jetbrains.compose.desktop.application.dsl.TargetFormat

plugins {
    kotlin("multiplatform")
    id("org.jetbrains.compose") version "1.0.0"
}

group = "com.example"
version = "1.0"

kotlin {
    js(IR) {
        browser {
            testTask {
                testLogging.showStandardStreams = true
                useKarma {
                    useChromeHeadless()
                    useFirefox()
                }
            }
        }
        binaries.executable()
    }
    sourceSets {
        val jsMain by getting {
            dependencies {
                implementation(compose.web.core)
                implementation(compose.runtime)
            }
        }
        val jsTest by getting {
            dependencies {
                implementation(kotlin("test-js"))
            }
        }
    }
}

Step 4: And Add Main.kt to jsMain/kotlin with following content

 renderComposable(rootElementId = "root") {
    Div(
        attrs = {
            // specify attributes here
            style {
                // specify inline style here
            }
        }
    ) {
        Text("A text in <div>")
    }
}

Step 4 : Add index.html to jsMain/resources with content

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>MultiplatformTest Sample</title>
</head>
<body>
<div id="root"></div>
<script src="web.js"></script>
</body>
</html>

Note: web.js file mentioned in the above snippet is sensitive and the project generated you need to make sure it is web.js only or else the folder_name.js which you created in step 1

Step 5: Finally add web module to settings.gradle.kts file

pluginManagement {
    repositories {
        google()
        jcenter()
        gradlePluginPortal()
        mavenCentral()
        maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
    }
    
}
rootProject.name = "MultiplatformTest"


include(":android")
include(":desktop")
include(":common")
include(":web")  // Note web module is included here 

I have created a repo check this repo and you can use it as a template for your projects

Link to the repo: https://github.com/PSPanishetti/ComposeMultiplatform

If you get any doubts feel free to ask them.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AgentP
Solution 2