JsonUI
← PlatformsSwiftJsonUIiOS native output from one spec — no runtime interpreter, no Swift-Kotlin-JS interop layer. sjui is the CLI, Dynamic mode is the hot-reload story, and the emitted code is indistinguishable from hand-written SwiftUI + UIKit.~10 min read
What you get`jui build` delegates Swift generation to sjui, which reads your Layout JSON + ViewModel and emits Swift files that would pass code review at any iOS shop. You get the Xcode project layout you already know, your own types, your own imports — the generator just removes the 'write the view three times' tax. Dual-mode output means every screen compiles for both SwiftUI and UIKit; you pick the host per screen, the generator does the rest.
SwiftUI + UIKit outputWriting a new app? Stay on SwiftUI. Maintaining a heavy UIKit codebase you cannot migrate in one go? Point sjui at UIKit for that screen. The spec is identical in both cases — the generator branch decides which NavigationStack / UINavigationController idiom to use, which UIView / View container to pick, which state primitive to lift. A project can mix both modes indefinitely; we use it on ours.
Dynamic modeDev-only: the app does not bake Layout JSON into the binary. It fetches the JSON from the unified `jui hotload listen` server on mount, so the simulator updates the moment you save a layout. A physical device can point at your Mac's IP and do the same thing — that's how most iOS devs first experience 'web-style hot reload on a phone'. The same server also handles Android, so a single listener covers both mobile targets. Release builds flip Dynamic mode off; production ships compiled SwiftUI with no network hop.
Production caveatsGenerated Swift is plain Swift — App Store review sees only the compiled binary, same as hand-written. Two things to know up front: (1) if you use obscure SwiftUI modifiers the generator has not yet learned, you will get a build warning; add the mapping in rjui_tools (sjui_tools) or file it under /learn/installation's troubleshooting. (2) SwiftData and Observation framework work, but the generator's ViewModel emission assumes Combine-first — if you want the new macros you will write a thin adapter for now. (3) Generated views are size-bounded: each function stays within a hard brace depth of 5 and a soft 250-line target, and every extracted section boundary is erased through `AnyView`. The erasure is the point — `some View` is opaque but still composes one giant generic type whose metadata the runtime decodes on a 1 MB device stack, so splitting into `some View` helpers does not stop a stack overflow (measured on a device with an 881-line body that had already been extracted). Anything the bounder cannot split safely is named in a build warning rather than passed over quietly.
Keep reading
KotlinJsonUIThe Android sibling — same spec, different native emit./platforms/kotlin
ReactJsonUIThe web sibling — Next.js + React + Tailwind from the same spec./platforms/react