Open-source project
Kotlin/kmp-basic-sample avatar
Kotlin/kmp-basic-sample

Kotlin kmp-basic-sample: the smallest KMP project that shows expect and actual properly

Example of Kotlin multiplatform project

1,138 stars201 forksKotlinApache-2.0

At a glance

What is it?
The Kotlin kmp-basic-sample repository is JetBrains' reference Kotlin Multiplatform project, with an Android app, an iOS app and a shared module, and it exists to demonstrate two things well: the expect and actual mechanism for platform specific APIs, and how tests for shared code are organised across both platforms. It is a teaching artefact rather than a library.
Who is it for?
kmp-basic-sample fits a developer learning Kotlin Multiplatform who wants a small, readable project rather than a framework, and a team deciding whether KMP is worth adopting who wants to see the build layout and test organisation before committing.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 35 days ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the repository is: three modules, two apps, one shared library

This is a Kotlin Multiplatform project. It includes iOS and Android applications with a native UI, and a module with code shared on iOS and Android.

The top level layout makes the shape immediately visible. There is an androidApp/ directory, an iosApp/ directory and a shared/ directory, alongside the Gradle build files: build.gradle.kts at the root, settings.gradle.kts, gradle.properties, and the gradle/ directory with the wrapper. The gradlew and gradlew.bat scripts are present, so the build runs through the wrapper and no local Gradle installation is needed.

That three-way split is the canonical Kotlin Multiplatform structure and it is worth understanding what each part is for, because the split is what a real KMP project inherits. The androidApp/ and iosApp/ directories are platform applications with their own native user interfaces, so an Android app and an iOS app, each with its own native user interface, each calling into the shared module. The shared/ directory is the common code, and it is where the logic that both platforms want lives.

The point of the arrangement is that the shared module is a library, not an application. The two apps are thin shells around it. A change to the shared code changes the behaviour of both applications at once, and that is the whole economic argument for KMP.

The repository is hosted under the Kotlin organisation at JetBrains and carries the official project badge. The licence is Apache-2.0 with a LICENSE file at the root, the primary language is Kotlin, the topics are kmm, kotlin and sample, and the repository is not archived with the last push on 2026-09-18. There are no GitHub releases, which is right for a sample that is consumed as source rather than as an artefact.

expect and actual, and what the sample says about it

The first feature the sample demonstrates is using platform specific APIs with the expect and actual mechanism, and the README points at the file where that happens, Platform.kt.

The mechanism itself is the one every KMP developer has to learn first. A shared function that needs different behaviour on Android and iOS is declared in the common source set as an expect declaration, and each platform provides an actual implementation. The compiler checks that each platform has supplied one, and the shared code calls it as if it were a normal function.

The value of the sample is that it shows the whole loop rather than a fragment. You see the common declaration, you see the Android implementation, you see the iOS implementation, and you see the shared code that calls across the boundary. There is no mocking and no interface hierarchy, because the point is that the platform mechanism is a language feature rather than a design pattern.

The practical thing to take from it is where the file lives. Platform.kt is one logical file that appears in more than one source set, so the same file name exists under the common code and again under the Android and iOS code, with different contents in each. A new developer reading a KMP repository for the first time often expects one file, finds three, and has to work out that the compiler is choosing between them. Seeing that arrangement in a file this small removes a real source of confusion.

The second thing the sample shows is that expect and actual is not a general purpose platform abstraction. It is for the cases where the two platforms genuinely have different implementations, such as a platform API that exists on one side and not the other. Using it for cases where a shared implementation would do adds friction for no benefit. The sample keeps it to the one file, which is the right proportion and a useful signal about how much of it you should expect to need in a real project.

The three test files, and what each one is proving

The second feature the sample demonstrates is tests for the shared module, and the README names three files: CalculatorTest.kt, iosTest.kt and androidTest.kt.

The naming makes the structure clear. CalculatorTest.kt is the shared test, and it exercises the shared module's own logic, the calculator being the sample's example domain object. The other two are platform specific test files, one for iOS and one for Android.

Why both? Because a shared module can contain code that is genuinely common and code that only compiles on one platform, and a KMP project needs to test both. The common test runs everywhere the shared module's common code is compiled, while the platform test runs on that platform only, which is where you test the actual implementation of an expect declaration, and where you can use platform APIs in the test itself.

That third point is the one the sample is really making. An expect declaration whose actual implementation is wrong will still compile and still pass the common tests, because the common test never calls the platform branch. Only the platform test exercises it. A project that has a shared module with platform specific behaviour and only common tests has a hole in its coverage, and this sample shows the two-file arrangement that closes it.

The three-file layout also teaches the source set structure indirectly, since each test file has to live in the source set whose code it can see. The common test can only call the common API, so the shared module's public surface has to be visible from common code, and the platform tests see more.

The README gives the workflow for running them. With the Kotlin Multiplatform plugin, you can run, test and debug shared code on both platforms without switching IDEs. You run and debug the application by selecting the corresponding configuration in the Run configuration menu, and you run and debug shared module tests by pressing the gutter icon on a test class or method. That second point is the ergonomic one, since running a shared test on both platforms from a single gutter click is what makes the two-source-set test arrangement tolerable in day to day work.

The plugin dependency, and the deliberate thinness of the sample

The sample depends on the Kotlin Multiplatform plugin, and the README links to it on the JetBrains plugin marketplace. The claim it makes about the plugin is the point of the tool: with it you can run, test and debug shared code on both platforms without switching IDEs, which is the workflow problem that makes KMP feel heavy.

The build files are the standard modern ones. build.gradle.kts and settings.gradle.kts at the root use the Kotlin DSL, gradle.properties holds the project properties, and the gradle/ directory with gradlew and gradlew.bat means the build is reproducible from a clone with the wrapper alone.

What the sample deliberately does not contain is as informative as what it does. There is no networking layer, no database, no dependency injection framework, no image loading, no navigation, no state management, and no UI framework abstraction for the shared code. The applications have native user interfaces, which is the point of the design, but the shared module is a calculator and a platform abstraction.

That thinness is correct for a sample and it is also the limitation to be aware of when you copy it. A production KMP application adds the layers the sample omits, and each of those layers raises the question of whether the code belongs in common or in a platform source set. The sample sidesteps all of that, and the KMP landing page and the developer portal are linked for the technology overview and the getting started path.

For a more realistic starting point, the README points to a hands-on lab, Networking and data storage with KMP hands-on, for creating a mobile application for Android and iOS with a shared codebase using Ktor and SQLDelight. That lab covers the two layers a real application cannot avoid, networking and storage, and it is the natural next step after the expect and actual mechanism makes sense.

Who should copy this, and what to check in it

The value of this repository is as a reference, and the value is entirely in the source rather than in the prose, because the README is short and the code is small.

The three things worth reading in the source are Platform.kt, for the expect and actual arrangement, the three test files, for the source set layout they imply, and the Gradle build files, for the module and source set declarations that produce that layout. Reading those three things gives you the shape of a KMP project in about ten minutes.

The first thing to check when you copy the structure is the source set declaration in the build files, because the common, android and ios source sets and the commonTest, androidTest and iosTest source sets are what the whole arrangement rests on, and getting a test source set wrong produces a test that silently does not run on the platform you thought it did.

The second is the plugin version. The sample tracks the current Kotlin Multiplatform plugin rather than pinning an old release, so if you are starting a real project you will want to pin a version you have tested rather than inheriting whatever the sample happened to use when you copied it.

The third is the platform target set. The sample covers iOS and Android, which is the common case, but a KMP project can also target desktop, web or other native platforms, and each additional target means additional actual implementations to write and additional platform test files. The expect and actual count grows with the platform count, and that is the cost that is easy to underestimate when you see a sample with one platform abstraction in it.

The last thing to know is where the real material is. The README links the Kotlin Multiplatform landing page for the technology overview, the developer portal for getting started, and the Ktor and SQLDelight lab for a realistic application. This repository is the one that answers the question of what the code looks like; those are the ones that answer what to build.

Editorial conclusion

kmp-basic-sample fits a developer learning Kotlin Multiplatform who wants a small, readable project rather than a framework, and a team deciding whether KMP is worth adopting who wants to see the build layout and test organisation before committing. It is the wrong starting point for a production application, because the sample deliberately omits networking, persistence and dependency injection, and the documentation points to a separate hands-on lab for a mobile application built with Ktor and SQLDelight. Before copying it, read the source sets rather than the README alone, since the value of the project is in how Platform.kt is split between common, Android and iOS, and check the Gradle plugin version, because the sample tracks the current Kotlin Multiplatform plugin rather than pinning an old one.

Frequently asked questions

What does the Kotlin kmp-basic-sample project demonstrate?

Two basic KMP features: using platform specific APIs with the expect and actual mechanism, in Platform.kt, and tests for the shared module, in CalculatorTest.kt, iosTest.kt and androidTest.kt. The project includes an iOS app and an Android app with native user interfaces plus a shared module.

What is the module layout of kmp-basic-sample?

Three directories at the top level, androidApp/, iosApp/ and shared/, alongside build.gradle.kts, settings.gradle.kts, gradle.properties, the gradle/ directory and the gradlew and gradlew.bat wrapper scripts. The two apps hold the native user interfaces and the shared module holds the code common to both platforms.

How do I run the shared module tests in the Kotlin KMP sample?

With the Kotlin Multiplatform plugin you can run, test and debug shared code on both platforms without switching IDEs. You run the application by picking the configuration in the Run configuration menu, and you run shared module tests by pressing the gutter icon on a test class or method.

Does the KMP sample include networking or a database?

No, it is deliberately thin. The README points to a separate hands-on lab, Networking and data storage with KMP hands-on, for building a mobile application with a shared codebase using Ktor and SQLDelight, which is the natural next step after the expect and actual mechanism.

Official sources

  1. Issues
  2. Kotlin/kmp-basic-sample on GitHub
  3. License: Apache-2.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kotlin-kmp-basic-sample.svg)](https://hysenlabs.com/projects/kotlin-kmp-basic-sample)

Was this useful?