In this blogpost we will deep dive into JetBrains multiplatform projects feature, why you should consider using it and how you can do so to level up your product development.

With Kotlin 1.2 JetBrains introduced a new experimental feature called multiplatform projects. This allows you, as things stand today, to share your code across any JVM or JavaScript based client. This can be your React based web-frontend, an Android client, a desktop client or whatever comes to your mind.

Cross-platform frameworks

TLDR; as proof of concept we have implemented the Conway’s Game of Life as Multiplatform Project which can be found here on Github.

Why sharing code?

The main idea of multiplatform projects is to share code between different teams and platforms that work on the same product. Code sharing is almost as old as writing code. Nowadays almost every software project uses some kind of shared code: networking, persistence, data handling or even tooling. For almost every use case, each platform offers a large quantity of libraries.

However, when it comes to sharing code between different platforms within the same organisation we see much less effort. Why is that? The most obvious reason is the incompatibility between the different technology stacks: the backend teams deploy their microservices in Go or Scala, the web team is catching up with the latest JavaScript frontend framework and the mobile teams are dealing with Java/Kotlin and Objective-C/Swift to write their native Android and iOS applications.

While the big players may afford to maintain such a big number of teams and technologies we can see lately a trend towards cross-platform frameworks, especially on mobile. Depending on your needs, such tools might make sense. But trying to cover multiple platform SDK’s like Android or iOS with a single framework also comes with downsides such as UX challenges due to platform specifics, lack of tooling support and flexibility.

In contrast, Kotlin’s multiplatform project focuses on sharing the logic and leaving the platform specific concerns to the platform specialists and SDK’s. Especially for frontend platforms this makes total sense. Why should a company decide to spend her budget on implementing the same business logic and the same MV’X’ design pattern on different platforms when she can have it all from the same source? On top of that, modern programming languages like Kotlin & Swift are becoming more and more similar which makes it easier for iOS developers to adopt Kotlin and have the whole team share the same codebase.

It’s not just about pure development costs, another big benefit is to share the knowledge across your different teams. How often did you see that the web team spent ages to implement all the corner cases of your business logic exclusively for the web while your mobile teams are running into the same cases on the different platforms. All this could be avoided by sharing the logic and have each team truly owning the same code. This is basically where the idea of feature teams is coming from and a Kotlin multiplatform project makes it super easy to have such team structure in an organization.

We can also see the positive effect on code quality in relation to shared code. The more users a library has or the more people contribute to it, the more effort is usually spent into stability and high test coverage. The same can be applied to code being shared within the same organisation. If you know that three other teams are relying on your code, you better do it right. This means that in the end, sharing code results in cleaner code, less code and ultimately less bugs.

What code should be shared?

The most obvious part to share is your data models that represent your real world entities. Think of all the duplication you could get rid of by sharing your Data Transfer Objects, Data Access Objects and the whole conversion mechanism.

This sounds nice, but in the end it’s just data representation. Multiplatform projects show their real power when they can share the business logic, but this a little bit tricky. It requires you to model your business logic properly. This is a complete topic on its own where tools like Domain Driven Design come into play. Furthermore, you need a clear separation between your business logic and platform concerns like user interfaces, hardware sensors etc. A good starting point could be to design your application in such a way that you could easily port it from mobile to web and vice versa, hook it into a simple terminal client, or to quote Uncle Bob “Your delivery mechanism is just an implementation detail”.

For frontend applications you could even go a step further and try to generify your presentation layer so it can be shared. This is definitely a thing since all the fancy architectural design patterns you have heard of, like MVC, MVP, MVVM or MVI have the goal of separating the rendering logic from the business logic and making your views passive. The key value of having such architecture is to increase testability. It becomes much more valuable when you share the core business logic with proper test coverage across platforms.

Unlike the other solutions, Kotlin's multiplatform project does not try to standardise the platform dependant needs like threading, I/O etc. Instead, it gives you flexibility by allowing you to very easily use different implementations of abstract concepts within the shared code. This also allows you to share the test code independently of the platforms making sure that the implementations satisfy the expectations by running these tests not just once but for each platform.

How does it work?

Set up a Multi Platform Project

You can easily create a multiplatform project using the project wizard from the latest Version of IntelliJ IDEA with at least Kotlin Plugin 1.2 installed. What you get is a common main module, a JVM and JavaScript module with both depending on the main module. You should treat each platform module as a common module which enables you to have multiple clients per platform. E.g. you could have a desktop and an Android client where both are based on a common-jvm module.

Cross-platform frameworks

The underlying build system supported is Gradle, which makes it really easy to configure your multiplatform project according to your needs.
The dependencies between a common module and platform module is defined by using the keyword expectedBy in the platform modules build scripts. This signals that the actual platform specific implementations are expected and can be used by a common module.

Expected Declarations and actual Implementations

Kotlin multiplatform project only adds expect and actual keywords to the language. Expected declarations are defined in the common module and the platform specific modules use the actual keyword in the concrete implementations.

In traditional abstractions, you would have different names for the platform specific implementations. Unlike in Kotlin, the common module and platform specific modules need to have exactly the same fully qualified names. This allows you to easily create and use such classes in a common module.

// Common
expect class GameLoop {

    var onTick: () -> Unit

    fun startWith(intervalMs: Int)

    fun stop()

    fun isLooping(): Boolean
// JVM
actual class GameLoop {

    private var gameLoop: Disposable? = null

    actual var onTick: () -> Unit = {}

    actual fun startWith(intervalMs: Int) {
        gameLoop = Flowable
                .interval(intervalMs.toLong(), MILLISECONDS)
                .subscribe {

    actual fun stop() {
        gameLoop = null


    actual fun isLooping() = gameLoop != null


The expect keyword is not limited to interfaces and abstract classes. It can be put into any top-level declaration available in Kotlin. It can, for example, be applied to top-level functions.

You simply expect the counterpart of the expected class or top-level function to be available in each platform (and provided via the actual keyword) and directly use it in the common module. The expect declarations cannot have implementation code and the actual declarations must have the exact names implemented in their respected platform.


Kotlin common modules can only use the Kotlin language with the common version of the Kotlin standard library (kotlin-stdlib-common). Although Java and JavaScript interoperability is really good with Kotlin, the common module cannot have any Java or JavaScript code which also prevents you to depend on any platform specific library in the common module. But at the same time the expect keyword allows you to do the abstraction very easily to make use of different but similar libraries for each platform.

Native and therefore iOS support is still missing, but has been already announced by JetBrains. On February 14, 2018 JetBrains released Kotlin/Native 0.6 which adds support for multiplatform projects. In this blogpost we explain how to add an iOS client to such setup.

A common concurrency model is not yet available since Kotlin’s Coroutines are still experimental and only available for the JVM. On the other hand, there are discussions going on whether it’s worth to port RxJava to a pure Kotlin version or to come up with a Reactive Kotlin multiplatform project abstraction over already established RxJava and RxJS libraries.


There are the obvious Cross Platform Frameworks like Flutter which is based on Dart and has been lately released by Google, and React Native which is based on JavaScript, developed by Facebook and heavily used by AirBnB and others which provide a facade around the Android and iOS SDK. Since you need to develop against the facade SDK in such platform, you may lose flexibility to be able to use platform specific APIs. Also such frameworks unify the UI development which can be challenging due to platform specific UX patterns.

Besides that there have been already similar initiatives like Google’s j2objc or web toolkit. One success story for these tools is, for example, that Google used them to port their Inbox application to the web and iOS.
These tools also allow you to share the business logic and data models by writing them in Java and making them usable in different platforms. These approaches are mostly unidirectional meaning that only the common pure logic is shared and it is harder to use platform specific declarations in the shared code. To be able to have platform specific code usable in the shared code, you would need to have your own abstraction with multiple wrappers for each platform which makes it harder to setup.


JetBrains is pushing hard for Kotlin and that’s good. Kotlin multiplatform projects are a great initiative towards truly cross-platform, even cross-tier development with all its benefits. Write code, do it once and deploy it on all your platforms. Once iOS is supported this will be a true alternative to the existing cross platform frameworks. We’re super excited about that.
Our implementation for Conway’s Game of Life as multiplatform project can be found here on github.

Cross-platform frameworks