← PlatformsKotlinJsonUIAndroid native output from one spec. kjui is the CLI, Dynamic mode mirrors sjui's story, and output is idiomatic Kotlin — Jetpack Compose is the primary target; XML Views are maintenance-only for legacy migrations.~10 min read
What you get`jui build` delegates Kotlin generation to kjui, which reads the spec and emits Kotlin files ready to drop into a Gradle module. Your Activity / Fragment / Compose Navigation setup stays yours; kjui generates the screen composables and the ViewModel base classes, leaving the app shell and integration points alone. Output compiles to the same bytecode any Android Studio build would produce.
Compose + XML outputNew app? Stay on Compose. Large XML Views codebase you are migrating one screen at a time? Point kjui at XML for the laggards. The spec is identical; only the generator's target branch differs. Compose recomposition is what the tooling is built around — Dynamic mode's network-fetched spec feeds straight into a remember { mutableStateOf } cache and the next recomposition picks it up. (See the Platform mode policy section below for the 2026-07-onward operating principle.)
Platform mode policy (2026-07 onward)As of 2026-07, Compose (both static codegen and Dynamic mode) is the primary target; XML / Android Views output is maintenance-frozen and slated for removal in KotlinJsonUI 3.0. New features, attribute additions, and bug fixes land on the Compose paths only. The consumer floor for Compose is Compose BOM 2025.04.01 (Compose UI 1.8.0) or later, and KotlinJsonUI 2.9.3+. The reason for the freeze: Renderer SSoT converges the attribute implementation onto a single source of truth, and keeping XML in parallel would force every SSoT-driven change to ship twice. Existing XML projects keep working through the KotlinJsonUI 2.x line — the recommendation is to migrate to Compose before 3.0 or pin to the 2.x major if migration is not on the roadmap.
Dynamic modeSame story as iOS — and literally the same server: the app in debug fetches Layout JSON from `jui hotload listen` at screen mount, and the listener pushes layout_changed events on save. The server distinguishes Android from iOS via a WebSocket handshake (`{ platform: 'android' }`) and per-path HTTP routes (`/android/layout/*`); one process covers both mobile targets. Coroutine scopes carry over cleanly because the ViewModel base is coroutine-first, so you rarely need to worry about where the work runs. Release builds bake the JSON into the APK and switch the runtime to the compiled path.
Production caveatsGenerated Kotlin is plain Kotlin. Two gotchas worth flagging: (1) if your app supports minSdk below 23, the Compose-first emission can fall back to XML under the same spec — but test the fallback early, because design fidelity is not identical. (2) Firebase / third-party library integration sits on your side of the contract; the generator does not opine on DI, so Hilt / Koin / Dagger2 all work but you wire them at the ViewModel layer. (3) Generated Composables are bounded by the same extractor, but the size limits are calibrated for the iOS mechanism and Compose has no counterpart — the real Android ceiling is the dex 65,535 code-unit cap, which is a hard compile error, so a build that succeeds has already proved the point (measured worst case: 12.6 % of the cap). Oversized functions are therefore not a build warning here; `jui lint-generated` lists them, and `--update-size-baseline` records the current set in `.jui-size-waivers` so later runs can single out functions that are newly oversized.
Keep reading
SwiftJsonUIThe iOS sibling — same spec, different native emit./platforms/swift
ReactJsonUIThe web sibling — Next.js + React + Tailwind from the same spec./platforms/react