I like to start a project using ktor latest as bac...
# compose-web
c
I like to start a project using ktor latest as backend and compose-web latest as frontend. I find multiple tutorials and templates for both of them separately but I can’t figure out how to combine the gradle configurations to have a multiplatform build with ktor and compose-web as browser frontend. Does anyone have an example gradle config that works?
h
b
Ktor backend and compose fronted. Frontend an be served via ktor or standalone.
c
Thank you will look into this. I understand the difference between backend and frontend, I was hoping to have a single multiplaform configuration like this for example https://github.com/kotlin-hands-on/jvm-js-fullstack
b
You mean both, fronted and backend inside one module?
c
yes but once I use something like jv-js-fullstack as the basis and add compose-web as documented then I get strange gradle issues
b
You shouldn't. Are you sure you've matched kotlin and compose versions to be compatible?
c
I tried different versions combination but the issues only started when I had also ktor included but let me make a sample config for review. most likely just an obvious error on my part that I don’t see
So I forked the jvm-js-fullstack project as a starter and ensured that I can build and start that. Then I added compose web dependencies resulting in this build.gradle.kts I downgraded the kotlin version from 1.7.20-beta to 1.7.10 and use org.jetbrains.compose version 1.1.1 because when I trued kotlin 1.7.20-beta and compose 1.2.0-beta1 then I got the error that the compose compiler is not compatible with 1.7.20-beta and requires 1.7.10 latest https://github.com/clippka/jvm-js-fullstack/blob/master/build.gradle.kts With this I get the
Copy code
Unable to find method ''void org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions.setUseIR(boolean)''
'void org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions.setUseIR(boolean)'
issue which I found some hits on the web but all seem to refer to issues with older non stable kotlin versions. Any help is appreciated. I would also not mind switching to 1.7.20-beta and 1.2.0-beta1 if possible as this is not yet for production
h
Yes, you have to use a dev/beta build of compose and kotlin 1.7.10. The latest dev/beta build is 1.2.0-beta1. If you want to keep using a stable version of compose (1.1.1), you have to use Kotlin 1.6.21.
c
When using
Copy code
id("org.jetbrains.compose") version "1.2.0-beta1"
and changing nothing else I get
Copy code
Build file '/Users/christian/Workspace/jvm-js-fullstack/build.gradle.kts' line: 11

Plugin [id: 'org.jetbrains.compose', version: '1.2.0-beta1'] was not found in any of the following sources:
does 1.2.0-beta1 have a different id or path? thanks for your help
h
You have to add the compose repo to your settings.gradle.build file too:
Copy code
pluginManagement {
    repositories {
        maven("<https://maven.pkg.jetbrains.space/public/p/compose/dev>")
        google()
        gradlePluginPortal()
    }
}
c
I had that but I also did a freaking type ’“1.2.0-beta1” vs “1.2.0-beta01" Now I’m back to the more interesting issues. When I’m not adding
Copy code
implementation(compose.web.core)
                implementation(compose.runtime)
to
Copy code
val jsMain by getting {
            dependencies {
my gradle sync runs without issues. But once I add them I get the following
Copy code
A problem occurred configuring root project 'shoppinglist'.
> Could not resolve all dependencies for configuration ':jsCompileClasspath'.
   > Could not resolve org.jetbrains.compose.web:web-core:1.2.0-beta01.
     Required by:
         project :
      > No matching variant of org.jetbrains.compose.web:web-core:1.2.0-beta01 was found. The consumer was configured to find a usage of 'kotlin-api' of a library, preferably optimized for non-jvm, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js', attribute 'org.jetbrains.kotlin.js.compiler' with value 'legacy' but:
          - Variant 'jsApiElements-published' capability org.jetbrains.compose.web:web-core:1.2.0-beta01 declares a usage of 'kotlin-api' of a library, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js':
              - Incompatible because this component declares a component, as well as attribute 'org.jetbrains.kotlin.js.compiler' with value 'ir' and the consumer needed a component, as well as attribute 'org.jetbrains.kotlin.js.compiler' with value 'legacy'
              - Other compatible attribute:
                  - Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
          - Variant 'jsRuntimeElements-published' capability org.jetbrains.compose.web:web-core:1.2.0-beta01 declares a library, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js':
              - Incompatible because this component declares a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.js.compiler' with value 'ir' and the consumer needed a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.js.compiler' with value 'legacy'
              - Other compatible attribute:
                  - Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
          - Variant 'jvmApiElements-published' capability org.jetbrains.compose.web:web-core:1.2.0-beta01 declares an API of a library:
              - Incompatible because this component declares a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' and the consumer needed a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
              - Other compatible attributes:
                  - Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
                  - Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
          - Variant 'jvmRuntimeElements-published' capability org.jetbrains.compose.web:web-core:1.2.0-beta01 declares a runtime of a library:
              - Incompatible because this component declares a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' and the consumer needed a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
              - Other compatible attributes:
                  - Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
                  - Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
          - Variant 'metadataApiElements' capability org.jetbrains.compose.web:web-core:1.2.0-beta01 declares a library:
              - Incompatible because this component declares a usage of 'kotlin-metadata' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
              - Other compatible attributes:
                  - Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
                  - Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
same for runtime
h
Oh, the sample uses
js {
as target, which still uses the legacy js backend. Use
js(IR) {
in line 30 to use the IR based backend. The Compose compiler only supports the IR backend.
c
nice. After that I’m running into https://github.com/JetBrains/compose-jb/issues/1568 when compiling jvmMain. I tried the workaround as proposed by Artrosis and added compose.runtime as a dependency for jvmMain. Now the example is working for me with compose-web as dependency! But looks like at this moment it would be more clean to really separate Server and JS code into separate modules. Thanks a bunch @hfhbd and @Big Chungus
If someone finds this and has the same issue, I pushed all fixes to make this work in this fork https://github.com/clippka/jvm-js-fullstack
h
cleaner, yes. But I don't think, adding the runtime is a big problem. And if you want to use a shared module, eg extracting your api/data classes (dto) or logic, you could apply the compose plugin for better performance (adding @Stable) at this shared module too, which will be used in the backend too. Sample: https://github.com/hfhbd/ComposeTodo/blob/main/shared/build.gradle.kts
f
https://kotlinlang.slack.com/archives/C01F2HV7868/p1663517306641079?thread_ts=1663516770.344609&amp;cid=C01F2HV7868 Sorry, what is the difference between "Frontend can be served via ktor or standalone" ???
h
You can serve your frontend with your own backend or use a static file hoster, like GitHub Pages