Stop Hardcoding Your UI: Why the Future of Native Apps is JSON with Gen AI
How to transform your Swift and Kotlin apps into dynamic rendering engines powered by Generative AI.
Lets see the way to build highly flexible mobile apps called AI-Augmented Server-Driven UI (SDUI).
SDUI used to be an expensive architecture reserved for giants like Airbnb and Uber. Generative AI and Declarative UI have democratized it for everyone
If you are a senior mobile engineer, you might be rolling your eyes at the hype around “AI-Generated UI.”
“We did this in 2016,” you say. “We called it Server-Driven UI. We built it with Java and Swift 2.0+. It was a nightmare.”
And you are right. We did build it. And it was a nightmare.
In the “Old Era” of Android XML and iOS UIKit/AutoLayout, implementing Server-Driven UI (SDUI) required a massive upfront investment. You had to build a complex Component Factory pattern. You had to write verbose parsing logic to manually render views, calculate constraints, and wire up click listeners.
The “juice” (dynamic updates) was rarely worth the “squeeze” (maintenance hell).
But the game has changed. Two independent technologies — Declarative UI (SwiftUI/Compose) and Generative AI — have collided to remove the friction from both ends of the wire.
Here is how the “New SDUI” is different from the one we abandoned.
How??? :
Catalyst 1: The Receiver (SwiftUI & Jetpack Compose)
Problem: The “Translation Tax.”
Basically, it used to be really hard and annoying to turn data (like a JSON file, which is shaped like a tree) into the visual stuff you see on your screen (the app’s interface).
The Old Way (The Component Factory): The old systems (like the older Android and iOS tools) were clunky. They required you to write a lot of code by hand to connect the data to the on-screen elements, which were often complicated, changeable objects.
Remember all the extra code you had to write to make this happen?
// The Old Nightmare (Java/Kotlin pre-Compose)
public View getView(String type, Context context) {
if (type.equals("card")) {
CardView view = new CardView(context);
// ... manually find IDs, set text, set listeners ...
return view;
} else if (type.equals("row")) {
// ... infinite if-else statements ...
}
}The New Way (Declarative Composition): Newer tools like SwiftUI (for Apple devices) and Jetpack Compose (for Android) build user interfaces like building a tree, similar to how simple data (like JSON) is organized. They work well together.
The complicated idea of a “Component Factory” (a way to create different parts of the screen) is now simple: it’s just a simple choice (like a switch) that calls the right function.
Get S.s.Sailesh kumar’s stories in your inbox
Join Medium for free to get updates from this writer.
Because these new ways of building the screen (ViewBuilders and @Composables) manage their own data and updates, the effort (the “Translation Tax”) needed to make things look right is almost zero.
// The New Reality (Jetpack Compose)
@Composable
fun Render(component: UIComponent) {
when (component) {
is Card -> CardView(component.data) // One line. Done.
is Row -> RowView(component.data)
}
}What changed from 1st : We used to build the screen step-by-step (like following a recipe), but now we just say what the screen should look like (like describing the finished dish). This means your app can easily show whatever information the server sends it.
The New Solution (Why it’s Easy Now):
The Server Side (The Sender): Generative AI (LLMs)
- In the old way, the server could only send layouts a human designer had already created (the “Template Trap”).
- Now, Generative AI acts as an “Architect.” You can tell the AI what you want (e.g., “Show a retention screen with a discount”) and the AI instantly generates the correct, valid data (JSON) for the app to display.
The Result: “Liquid UI”
- The server can now generate unique, real-time screens in milliseconds that no human explicitly designed.
- The app can instantly display these generated screens.
- This means apps can change their look and feel instantly, adapt to a user’s behavior, and update without an App Store release, all with vastly less code and effort than before. The era of the “Static App” is over.
But How ??
The “Blueprint” (The JSON Output) from Gen AI, basically generated using AI
{
"screen_title": "Weekend Vibes",
"root": {
"type": "vertical_stack",
"spacing": 16,
"children": [
{
"type": "Text",
"text": "Premium members get ad-free listening tonight!",
"color": "#FFD700"
}
]
}
}The Mobile Renderer
Here is how modern frameworks handle this JSON with zero friction
Swift UI:
// 1. The Models
struct ServerUIResponse: Decodable {
let screen_title: String
let root: UIComponentWrapper
}// 2. The Renderer
struct SDUI_Renderer: View {
let component: UIComponent // Enum wrapper for polymorphic decoding
var body: some View {
switch component {
case .verticalStack(let data):
VStack(spacing: CGFloat(data.spacing)) {
ForEach(data.children) { child in
SDUI_Renderer(component: child) // Recursion
}
}
case .Text(let data):
Text(data.text)
.padding()
.background(Color(hex: data.color))
.cornerRadius(8)
case .unknown:
EmptyView()
}
}
}Jetpack Compose:
// 1. The Models (Polymorphic Serialization)
@Serializable
@JsonClassDiscriminator("type")
sealed class UIComponent {
@Serializable @SerialName("vertical_stack")
data class VerticalStack(val children: List<UIComponent>, val spacing: Int) : UIComponent()
@Serializable @SerialName("Text")
data class PromoBanner(val text: String, val color: String) : UIComponent()
}// 2. The Renderer
@Composable
fun SDUI_Renderer(component: UIComponent) {
when (component) {
is UIComponent.VerticalStack -> {
Column(verticalArrangement = Arrangement.spacedBy(component.spacing.dp)) {
component.children.forEach { child ->
SDUI_Renderer(child) // Recursion
}
}
}
is UIComponent.Text -> {
// Render Text...
}
}
}Unlike shipping a finished product (the traditional model), you provide a “set of paintbrushes.” By combining Jetpack Compose / SwiftUI (renderers) with LLMs (the architect), you achieve mobile engineering velocity, solving the choice between “Native Performance” and “Web Speed” with a native engine that moves at the speed of thought.






