PeopleInSpace: a Kotlin Multiplatform reference app that runs on nine targets
Kotlin Multiplatform sample with SwiftUI, Jetpack Compose, Compose for Wear, Compose for Desktop, and Compose for Web clients along with Ktor backend.
At a glance
- What is it?
- PeopleInSpace is a sample that puts one shared Kotlin codebase behind SwiftUI, Jetpack Compose, Compose for Wear, Compose for Desktop, Compose for Web (Wasm), WinUI 3, a Ktor backend and an MCP server. It is best read as a working map of what KMP sharing costs per platform, not as a product you adopt.
- Who is it for?
- Adopt PeopleInSpace as a reading and scaffolding reference if you are starting a Kotlin Multiplatform project and want to see how shared Ktor, SQLDelight, Koin and view models sit under five different UI toolkits. Do not adopt it as a dependency or as a production template: it is a sample, it has no retrieved releases, and its backend is a thin proxy in front of The Space Devs and Where the ISS at APIs.
- 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 2 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 September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem PeopleInSpace actually solves
Kotlin Multiplatform documentation describes what sharing is possible. It does not show what a shared codebase looks like once five UI toolkits, a server, a widget and a command line package all consume it. PeopleInSpace fills that gap. The README states it is a Kotlin Multiplatform project with SwiftUI, Jetpack Compose, Compose for Wear OS, Compose for Desktop and Compose for Web clients along with a Ktor backend, and it lists the targets it currently runs on: Android, an Android app widget built with the Glance API, Wear OS, iOS, a Swift executable package, Desktop, Web via Compose for Web on Wasm, Windows via WinUI 3, a small JVM Ktor service, and an MCP server. The audience is an engineer who already knows Kotlin and wants to see the seams. Two upstream APIs supply the data. The Space Devs API provides names, bios and images of people currently in space, and the Where the ISS at API provides the station position. Both are reached through the project's own Ktor backend rather than directly from each client, which is the first design decision worth noticing. If you only need one platform, this repository is the wrong shape for you.
How the shared module is split from the clients
The module table is the architecture. The common module holds shared KMP code (Ktor, SQLDelight, Koin, view models), shared Compose Multiplatform UI, and the Windows NuGet API. Everything else is a surface. The app module is the Android client including the Glance widget, wearApp is the Wear OS client, PeopleInSpaceSwiftUI is the iOS client, compose-desktop and compose-web are the desktop and Wasm web clients, windows/WinUiApp is the WinUI 3 client, backend is the Ktor server, and mcp-server exposes the shared code over the Model Context Protocol. The data flow is one directional and shallow: client calls the Ktor backend, the backend calls the two upstream APIs, SQLDelight provides local storage in the shared layer, and Koin wires the dependencies. The MCP module is the interesting one, because it reuses the same shared code (Ktor, SQLDelight, Koin) that the mobile clients use, so the tools endpoint returning the list of people in space is not a parallel implementation. That reuse is the point of the sample. Note what the README does not describe: there is no caching policy, no refresh interval and no offline strategy documented for the ISS position, so do not assume one exists.
Getting a client running
Requirements stated in the README are JDK 17, a recent Android Studio for the Android and Wear clients, and Xcode for iOS. Android runs through the app configuration in Android Studio or ./gradlew :app:installDebug. Wear OS uses the wearApp configuration or ./gradlew :wearApp:installDebug. iOS is opened as PeopleInSpaceSwiftUI in Xcode and run from there. Desktop is ./gradlew :compose-desktop:run. Web is ./gradlew :compose-web:wasmJsBrowserDevelopmentRun. Windows is not a Gradle command: the README points at the WinUI 3 client guide in windows/README.md for prerequisites plus build, test and run instructions. The backend is ./gradlew :backend:run, or run Server.kt directly from Android Studio, after which the README says you should be able to open http://localhost:9090/astros_local.json in a browser. Tests run with ./gradlew :common:jvmTest, and there is a Maestro UI flow for Android invoked as maestro test maestro/PeopleInSpace.flow. The Kotlin badge in the README reads 2.4.0, so pin your toolchain against that before assuming a newer Kotlin release behaves the same.
Deployment and the MCP server wiring
The backend deployment path is documented as tested on Google App Engine, using the shadowJar plugin to produce an uber jar, then two commands: ./gradlew :backend:shadowJar followed by gcloud app deploy backend/build/libs/backend-all.jar --appyaml=backend/src/jvmMain/appengine/app.yaml. The README says it should be possible to deploy the jar to other services as well, which is a statement of possibility, not a tested path. The MCP server follows the same jar pattern. You run the Gradle shadowJar task, then in Claude Desktop open Edit Config under Developer Settings and add a server entry named kotlin-peopleinspace with command java and args -jar, the path to mcp-server/build/libs/serverAll.jar, and --stdio. The README explicitly tells you to update the path. The module uses the Kotlin MCP SDK from modelcontextprotocol. Two things are worth flagging here. First, the MCP config is a JSON block pasted into a desktop app's settings, so any path mistake surfaces as a failed server start rather than a build error. Second, the deployed backend and the local backend are the same jar, so a change to the shared KMP code affects the MCP tools and the mobile clients at once.
Where the sample is thin or the wrong tool
PeopleInSpace is a demonstration, and the documentation reflects that. There are no retrieved releases, so there is no versioned artifact to depend on and no changelog to read before upgrading. The README does not document error handling for the two upstream APIs, rate limits, or what a client shows when the backend is unreachable. The ISS position feature appears in the Wear OS screenshots (a position map and an edge button) but the README gives no update cadence for it. The Windows client is the clearest boundary: it is a .NET client documented in a separate windows/README.md rather than a Gradle target, which means the build story for that platform is outside the single-command pattern the other clients follow. If your goal is a production app with a single platform, a plain Android or iOS project with a direct HTTP client will be simpler than carrying a Ktor backend, SQLDelight and Koin in a shared module you do not need. The sample earns its complexity only when at least two of those targets are real for you.
How this differs from writing each client separately
The obvious alternative is not another library; it is the conventional approach of building each client on its own stack, with no shared module. Compose Multiplatform is the middle option, and PeopleInSpace shows both ends of it. The iOS client is SwiftUI, so its UI is native Swift while its data layer comes from the shared common module. The Android, Desktop and Wasm web clients use shared Compose Multiplatform UI as well. That difference matters when you are deciding how much to share: the repository lets you compare a native-UI client against a shared-UI client consuming the same Ktor, SQLDelight and Koin code. Koin is doing dependency injection across platforms, Ktor is the HTTP layer, SQLDelight is the storage layer, and the view models live in common. A per-platform rewrite would duplicate all four. The trade is that a shared UI layer constrains you to what Compose Multiplatform renders on each target, while the SwiftUI client keeps full access to platform UI conventions at the cost of writing that layer twice.
Maintenance cost and the Apache-2.0 terms
The repository is licensed Apache-2.0 and is not archived, with the last push recorded as 2026-09-06. That licence permits commercial use and modification and includes a patent grant, but it also requires you to keep the licence and notice files and to state significant changes. None of that is legal advice; read the licence text and your own counsel's view before shipping. The practical maintenance cost is the toolchain spread. A single change to the common module can require validating JDK 17, a recent Android Studio, Xcode, the .NET prerequisites described in windows/README.md, and a Wasm build. The Kotlin badge pins 2.4.0, and Kotlin Multiplatform moves quickly, so an upgrade to the compiler touches every target at once. The README's related posts list is effectively the project's own changelog of design decisions, covering SQLDelight storage, Koin, Swift async/await against Kotlin coroutines, and wrapping Kotlin Flow as a Swift Combine publisher. That list is more useful for understanding why the code looks the way it does than any release note you will find here.
Editorial conclusion
Adopt PeopleInSpace as a reading and scaffolding reference if you are starting a Kotlin Multiplatform project and want to see how shared Ktor, SQLDelight, Koin and view models sit under five different UI toolkits. Do not adopt it as a dependency or as a production template: it is a sample, it has no retrieved releases, and its backend is a thin proxy in front of The Space Devs and Where the ISS at APIs. Before copying anything, verify three things yourself: that JDK 17 plus your Xcode and Android Studio versions satisfy the build, that :common:jvmTest and the Maestro flow pass on your machine, and that the App Engine app.yaml path still matches your gcloud setup.
Community notes