arkivanov/Decompose: Lifecycle-Aware Kotlin Multiplatform Components with Pluggable UI
Kotlin Multiplatform lifecycle-aware business logic components (aka BLoCs) with routing (navigation) and pluggable UI (Jetpack Compose, SwiftUI, JS React, etc.)
At a glance
- What is it?
- Decompose splits Kotlin Multiplatform code into tree-structured, lifecycle-aware components with routing, and leaves the UI to Compose, SwiftUI, Android Views or Kotlin/React. It is a library, not a framework, and that distinction shapes both its flexibility and its cost.
- Who is it for?
- Adopt Decompose if you are building a Kotlin Multiplatform app that needs shared navigation logic and platform-specific UI, and you are willing to write your own UI adapters for each target. Do not adopt it if you want a batteries-included framework that owns your application structure, or if your app is single-platform Android with no multiplatform plans, where AndroidX Navigation and ViewModel already cover the same ground.
- 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 11 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 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The Problem Decompose Solves, and Who It Is For
Kotlin Multiplatform lets you share code across Android, iOS, desktop, web and other targets, but it does not tell you where to put navigation, lifecycle handling or state preservation. Each platform has its own answer: AndroidX ViewModel and Navigation on Android, SwiftUI's own state model on iOS, and whatever the JavaScript ecosystem provides on the web. Sharing business logic usually means either duplicating navigation on every platform or letting one platform's framework leak into the shared module.
Decompose takes the second problem head-on. The README describes it as a library for breaking code down into tree-structured lifecycle-aware business logic components, with routing and pluggable UI. Each component owns a piece of logic and an optional UI that is plugged in externally. The intended audience is teams already committed to Kotlin Multiplatform who want navigation and lifecycle behaviour written once and rendered differently per platform. If you are building a single-platform Android app, the library's own framing suggests you are not the target: the problems it addresses only appear once you have more than one UI layer to satisfy.
How the Component Tree and Navigation Model Work
The core abstraction is the component. Every component represents a piece of logic with its own lifecycle, and the UI is optional and plugged externally. Each component receives a ComponentContext, which is what makes it lifecycle-aware and enables state preservation, instance retaining and back button handling.
Components are organised into trees. The README is explicit that each parent component is only aware of its immediate children. That constraint is the architectural centre of the library: it prevents a root component from reaching into a deeply nested screen, and it forces communication to travel through the tree. The repository layout reflects this, with a decompose/ module at the top level alongside extensions-compose/, extensions-compose-experimental/, jetpack-component-context/ and decompose-test-utils/.
Navigation is built from predefined models rather than a single navigator object. Child Stack handles navigation between child components, including nested navigation. Child Slot allows one child component at a time, or none. Child Pages presents a list of child components with one selected, described as pager-like. Child Panels provides multi-pane navigation. When none of those fit, Generic Navigation lets you build a custom model.
Two design choices stand out. First, navigation state is fully exposed, so the UI layer can animate however it likes or use a predefined API. Second, the README describes navigation as a pure function from the old state to a new one. That is what makes the navigation logic testable with pure multiplatform unit tests, and it is why decompose-test-utils/ exists as a separate module. Components in the back stack are not destroyed; they continue working in the background without UI, which is a deliberate difference from frameworks that tear down screens on navigation.
Installing Decompose and Wiring a First Component
The README does not carry inline installation steps. It points to the Installation section of the project website, and there is a template repository, arkivanov/decompose-multiplatform-template, described as a way to kick-start a project. The supported targets listed are android, jvm, ios, watchos, tvos, macos, wasmJs and js, with the caveat that some modules do not support all targets and that support depends on the Decompose version.
Because the README gives no artifact coordinates, the honest first step is to read the installation page and confirm the current version there rather than copying a version number from an article. The recent releases are 3.5.0 (2026-03-15), 3.6.0-alpha01 (2026-07-01) and 3.6.0-beta01 (2026-09-10), so the stable line and the prerelease line are clearly separated.
Once the dependency is in place, the shape of a component follows the documented structure. A component is a class that receives a ComponentContext and exposes state to the UI. The exact constructor signature and the navigation model API belong to the documentation, not to this article, and inventing them would be worse than pointing you at the source. What can be said from the repository is that the sample/ directory contains per-platform applications, including sample/app-android/, sample/app-desktop/, sample/app-ios-compose/, sample/app-ios/, sample/app-js-compose/, sample/app-js/ and a shared module in sample/shared/. Reading those samples alongside the docs is the fastest way to see how a component is constructed and how each UI layer consumes it, because each sample pairs the same shared logic with a different rendering target.
Where Decompose Gets in Your Way
The library's flexibility is also its main cost. Decompose does not render anything. The README calls the UI pluggable, which means for every target you support you write the adapter that maps component state to that framework's widgets. Compose, Android Views, SwiftUI and Kotlin/React are all listed as options, and each one is a separate integration you own. A team expecting a drop-in navigation framework will spend its first weeks writing glue code.
The parent-only-knows-its-children rule is a real constraint, not a stylistic preference. Deeply nested screens cannot communicate directly, so anything shared across distant branches has to be lifted, passed down, or handled through dependency injection. The README lists proper DI and inversion of control via constructor as a benefit, and it is one, but it also means Decompose assumes you already have a DI story. Without one, the constructor wiring becomes the hard part of the project.
State preservation is asymmetric. The README states it happens automatically on Android and manually on all other targets via kotlinx-serialization. That is a meaningful difference in effort between platforms, and it pushes a serialization dependency into your shared code. Instance retaining, described as similar to AndroidX ViewModel, is noted as mostly useful on Android. If your primary pain point is iOS state restoration, Decompose does not remove the work; it gives you a place to put it.
Finally, the README states that module target support varies by version. That sentence should be read as a warning: before designing around a module, confirm it supports every target you ship.
Decompose Compared with Decompose-Router
The README names one alternative directly: Decompose-Router, at github.com/xxfast/Decompose-Router. The difference is not a competing library but a different layer. Decompose-Router is described as an example of leveraging Decompose to create a custom navigation solution with a completely different API.
That distinction matters when choosing. Decompose itself is a library that can be used as a framework, and the README says the component term is just one possible usage, the recommended one. The core is the manipulation of ComponentContext instances with a strict parent-child relationship, and the ComponentContext interface can have custom implementations that add properties, functions and stored data. Decompose-Router takes that core and imposes its own navigation API on top. If the predefined Child Stack, Slot, Pages and Panels models do not match how your app navigates, you have two paths: build a custom model with Generic Navigation, or adopt a project like Decompose-Router that has already made those decisions for you. The first keeps you closer to the documented API; the second trades control for a faster start.
Maintenance, Licence and Upgrade Cost
The repository is not archived, and the last push was on 2026-09-20, which is recent relative to the release cadence visible in the release list. The project publishes prereleases in the open: 3.6.0-alpha01 in July 2026 and 3.6.0-beta01 in September 2026, following the stable 3.5.0 in March 2026. That pattern suggests active iteration, but it also means the newest line is not stable, and the README's note that module target support depends on the Decompose version is the practical upgrade risk. A module that supports wasmJs on one version may not on another.
The licence is Apache-2.0, which is a permissive licence that generally allows commercial use, modification and distribution with attribution and notice requirements. The LICENSE file sits at the repository root. This is not legal advice; if your organisation has licence review requirements, the Apache-2.0 text is the document to review.
Upgrade cost is hard to estimate from the repository alone. The README does not document rollback or a deprecation policy, and it does not describe a migration guide. The presence of decompose-test-utils/ suggests the project expects you to test navigation logic, which helps when upgrading, but the documentation is silent on what happens between major versions.
Editorial conclusion
Adopt Decompose if you are building a Kotlin Multiplatform app that needs shared navigation logic and platform-specific UI, and you are willing to write your own UI adapters for each target. Do not adopt it if you want a batteries-included framework that owns your application structure, or if your app is single-platform Android with no multiplatform plans, where AndroidX Navigation and ViewModel already cover the same ground. Before committing, verify which modules support your target platforms, since the README states that module target support varies by version, and check whether the stable 3.5.0 release or the 3.6.0-beta01 line is the right base for your project.
Frequently asked questions
What is arkivanov/Decompose?
It is a Kotlin Multiplatform library for breaking code into tree-structured lifecycle-aware business logic components, with routing and pluggable UI such as Jetpack/Multiplatform Compose, Android Views, SwiftUI and Kotlin/React.
Which platforms does Decompose support?
The README lists android, jvm, ios, watchos, tvos, macos, wasmJs and js as targets, with the caveat that some modules do not support all targets and that support depends on the Decompose version.
Does Decompose require a specific UI framework?
No. The UI is pluggable and plugged in externally, so the same component logic can be rendered with Compose, Android Views, SwiftUI or Kotlin/React. You write the adapter for each target you support.
How does Decompose handle state preservation?
The README states that state preservation happens automatically on Android and manually on all other targets via kotlinx-serialization.
Is Decompose a framework or a library?
The README describes it as a library that can be used as a framework. Its core manipulates ComponentContext instances with a strict parent-child relationship, and the component term is described as just one possible usage, the recommended one.
Official sources
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.
[](https://hysenlabs.com/projects/arkivanov-decompose)