
At SOTI India, I built a Jetpack Compose UI library that cut feature deployment time by 99%. Here's what that actually meant — architecturally, technically, and in practice.
The number sounds impossible: 99% reduction in deployment time. When I first shared it on my resume, I braced for pushback. But the math is honest. Before the library existed, shipping a new UI feature to our enterprise Android product took weeks — design reviews, bespoke component work, back-and-forth alignment, QA cycles. After the library, that same feature took hours. That's not a percentage improvement. It's a different way of working.
Here's what we actually built, and why Jetpack Compose made it possible in a way the View system never would have.
SOTI's Android product is a Mobile Device Management platform — an enterprise tool used by IT administrators across hundreds of organizations. The UI requirements are dense: complex data tables, state-heavy forms, real-time device status indicators, customizable dashboards. Every client had slightly different branding requirements on top of a shared functional core.
With the traditional View system, every new UI surface meant a new XML layout, a new ViewHolder, new custom attributes if you needed theming, and a non-trivial amount of Java/Kotlin glue code to connect it all. Reusing a component across features required careful abstraction that always leaked — some consumer would reach into the view hierarchy directly, break the contract, and cause a regression three releases later.
The View system was designed for a world where screens were static. Enterprise software is not static. It's a live dashboard that changes with every MDM event.
Jetpack Compose's model — pure functions from state to UI — changed the fundamental contract. A composable describes what to render given a set of inputs. It has no internal imperative state that consumers can break. If you call `DeviceStatusCard(device = device, onAction = onAction)`, that's the entire surface area. The implementation is hidden. The contract is the function signature.
@Composable
fun DeviceStatusCard(
device: DeviceState,
onAction: (DeviceAction) -> Unit,
modifier: Modifier = Modifier
) {
val statusColor by animateColorAsState(
targetValue = when (device.status) {
DeviceStatus.ONLINE -> SotiGreen
DeviceStatus.OFFLINE -> SotiRed
DeviceStatus.PENDING -> SotiAmber
}
)
Card(
modifier = modifier,
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface)
) {
// Composition — not mutation
}
}With the View system, adding the animated status color would require a custom view, a ValueAnimator, and careful lifecycle management. In Compose, it's one line. That simplicity compounds: when every component is this easy to extend, teams stop writing one-off views and start reaching for the shared library instead.
Enterprise clients need white-labeling. In the old world, we'd maintain separate res/values folders with duplicated color declarations and pray that nothing fell through the cracks during a brand update. In Compose, we defined a `SotiTheme` composable that wraps the entire app and provides a `CompositionLocal` token system.
Before: a PM files a ticket for a new device detail screen. Designer creates mockups. Developer builds layout XML. Team reviews. Developer iterates. QA tests. Two to three weeks from ticket to merge.
After: the designer picks tokens from the shared system (they know what's available because the library has a Compose Preview catalog). The developer composes existing components — `DeviceStatusCard`, `ActionChipRow`, `MetricsGrid`. The screen is functional in an afternoon. The review is a logic review, not a pixel review, because the visual layer is already trusted.
The library didn't just accelerate development. It shifted where the creative work lived — from implementation to composition. That's the real value.
Then you’re in the right place. Get the best solution you’re looking for. Just reach out and let me know!