What if you had to build a multiplatform (Android & iOS) and multi-tenant app with the objective of sharing the biggest amout of code possible while having all apps being UI/UX independent?
We want to take you through the discovery trip we made while building this. From architecture to ins and outs of KMM via Gradle magic that enabled us to have a Android, iOS and Desktop app.
Also sharing our rational over each of the options we took: Why not React Native? Or Xamarin? Should we use Compose Multiplatform?
2. ONCE
UPON A TIME…
… A MULTIPLATFORM, MULTI-TENANT CHALLENGE…
A story by @neteinstein / @tiper …………………
(the bald guy) / (the small guy)
#dclx23 / #JustSawSomebodyFromMinderaSpeak
3. @neteinstein @tiper
Mobile Software Craftsman @ Mindera
Helping teams getting better with LoopGain
Co-Founder @ GDG Porto
Burning people @ O Que Arde Cura
Somebody who sometimes the keys I hit on the
keyboard generate a sequence of characters
that resembles working code that somehow find
its way into production @ Mindera
4. @neteinstein @tiper
Mobile Software Craftsman @ Mindera
Helping teams getting better with LoopGain
Co-Founder @ GDG Porto
Burning people @ O Que Arde Cura
Somebody who sometimes the keys I hit on the
keyboard generate a sequence of characters
that resembles working code that somehow find
its way into production @ Mindera
#JustSawSomebodyFromMinderaSpeak
5. And so it begins
AS WITH ALL GOOD STORIES… WITH A COMPANY TRYING TO BUILD 7 APPS FROM A SHARED CODE BASE…
9. Go for it if…
… having a top notch app is core to your business;
… Focused on each ecosystem’s UI/UX — patterns easily recognised by
users
… core features require using the state-of-the-art and leverage all the
platform capabilities.
But…
… you have budget to maintain 2-N teams, given more developers are
needed, as they are specialised.
… more code bases means more alignment, possible bugs etc
10. Go for it if…
… your company’s know-how is .NET/C#
… the app is not core to your business, or it is but you
have a lot of complex code to share among apps
… you want 1 team / reduce costs
But…
… the app might not be as performant as other options;
… developer community support is a real concern;
… can be twice as big as a native file
… not the best for apps with complex graphics
11. Go for it if…
… your company’s know-how is strong in React *
… the app is not core to your business, or it is, but you have a lot of
complex code to share among apps;
… time-to-market frame is key or you’re trying to build a POC, that you
might or might not reuse code from.
… you want to reduce costs
But…
… depending on the complexity of the app, at some point during
development you are likely to need native development
… the app will have “good enough” performance as it becomes more
complex, unless you go for native solutions to cope with that.
12. Go for it if…
… your company’s know-how is strong in Dart;
… you want a complete common app (UX/UI + Logic)
… you’re trying to build a POC, that you might or might
not reuse code from
But…
… finding Dart developers can be challenging (and
expensive)
… there is always the risk of Google dropping Flutter
13. Go for it if…
… you already have good Android devs with Kotlin experience
… having a top-notch app is core to your business
… you want to just share the logic not UX/UI
… you want to reduce costs (less devs and codebase)
But…
… still Beta
… still hard to find devs with proper KMP knowledge
…still exports to iOS as Obj-C
14. Go for it if…
… you already have good Android devs with Kotlin
experience
… a common UI/UX between OSes is desirable
… you want to reduce costs
But…
… still Alpha for iOS
… harder to customize components on each OS
18. 7 dif Apps, 1 Codebase, ideas?
React
Flutter Xamarin
Your option better be good…
19. 7 Apps, 1 Codebase…ideas?
React
Flutter Xamarin
Your option better be good…
20. 7 Apps, 1 Codebase…ideas?
React
Flutter Xamarin
Your option better be good…
Before you ask:
Yes, it’s me and
I had hair…
21. 7 Apps, 1 Codebase…ideas?
React
Flutter Xamarin
Your option better be good…
No, Tiago was
still the same
size…
Before you ask:
Yes, it’s me and
I had hair…
22. 7 Apps, 1 Codebase…ideas?
React
Flutter Xamarin
Your option better be good…
No, Tiago was
still the same
size…
Before you ask:
Yes, it’s me and
I had hair…
Now stop the
questions, let’s
continue.
23. 7 Apps, 1 Codebase…ideas?
React
Flutter Xamarin
Your option better be good…
27. You’re the first one to ask…
💡 Shared logic
🖌 Features might have same or different UX/UIs
Meaning:you need to support both - we’ll decide along the way
💸 Budget
💥 Single code base for 7 tenants didn’t scale
properly…
28. 7 Apps, 1 Codebase, ideas?
React
Flutter Xamarin
Your option better be good…
Kotlin
Multiplaform?
32. Native UI
Native UI
Shared Code
API
Step 3: We can have multiple Apps being fed by the Shared
code layer (each with its UI layer)
Native UI Native UI
33. And how the hell do we
share:
● Common features
● UI components?
Good question!
35. Step 4: Let’s deep dive into the Android side.
Native
App
Code
Profile Register
…
Login
36. Step 4: Let’s deep dive into the Android side.
Native
App
Code
KMP
Shared
Library
Login
Business Logic Module
Profile Module
Register
Business Logic
Module
…
Network Module
...
Profile UI Register UI
…
Login UI
…
37. Step 4: Android: UI Components Library
Native
App
Code
KMP
Shared
Library
Login
Business Logic Module
Profile Module
Register
Business Logic
Module
…
Network Module
...
Profile UI Register UI
…
Login UI
…
Big Button
Android Native
UI Components Library
Text Label
Small Button
...
38. Step 4: A feature has 2 blocks
Native
App
Code
KMP
Shared
Library
Login
Business Logic Module
Profile Module
Register
Business Logic
Module
…
Network Module
...
Profile UI Register UI
…
Login UI
…
Big Button
Android Native
UI Components Library
Text Label
Small Button
...
39. Step 4: Android: and a feature have different logic
implementations (and UI)
Native
App
Code
KMP
Shared
Library
Login
Business Logic Module
Profile Module
App P Profile App T Profile
Register
Business Logic
Module
…
Network Module
...
Profile UI Register UI
…
Login UI
…
Big Button
Android Native
UI Components Library
Text Label
Small Button
...
40. Step 4: Android: and a feature have different logic
implementations (and UI)
App P Native Code
KMP
Shared
Library
Login
Business Logic Module
Profile Module
App P Profile App T Profile
Register
Business Logic
Module
…
Network Module
Homepage Logic
Profile UI
…
Big Button
Android Native
UI Components Library
…
App P Native Code
Profile UI
Homepage UI
Homepage UI
Login UI
Android Native
Common Features
…
41. Step 5: iOS (same with an extra layer to bring Swift sugar
syntax)!
Native
App
Code
KMP
Shared
Library
Login
Business Logic Module
Profile Module
App P Profile App T Profile
Register
Business Logic
Module
…
Network Module
...
Profile UI Register UI
…
Login UI
…
Big Button
iOS Native
UI Components Library
Text Label
Small Button
...
Objective-C to Swift Abstraction Layer
42. Step 5: iOS!
Native
App
Code
Profile UI Register UI
…
Login UI
Objective-C to Swift Abstraction Layer
Again this Native App Code above is a simplified version.
It will contain an Architecture pattern, Navigation, Deep
Links, Pushs, etc as a “normal” app.
44. Step 7: How do we export?
Login Module
Register Module
Register Module
Domain
Module
Profile P
Module
Network Module
App P Business
Library
Profile T
Module
App T Business
Library
45. Step 8: And how do we work with all this?
Dependency
Dependency
Dependency KMP Common Lib
Business Layer (API,
DB..)
Dependency
Dependency
Step 8: How does it work on Android?
Android Common Components
Kotlin Code for Android native
UI components
App T Android
App P Android
Android Common Features
To be shared across tenants
46. Step 8: And how do we work with all this?
Dependency
Dependency
Dependency KMP Common Lib
Business Layer (API,
DB..)
Dependency
Dependency
Step 9: And iOS?
Export
Export
iOS Common Components
Swift Code for Android native
UI components
App T iOS KMP
XCFramework generated from KMP
for iOS App consumption
App T iOS
iOS Common Features
To be shared across tenants
Dependency
App P iOS
Dependency
App P iOS KMP (Exports)
XCFramework generated from KMP
for iOS App consumption
Dependency
Dependency
Dependency
Android Common Components
Kotlin Code for Android native
UI components
App T Android
App P Android
Android Common Features
To be shared across tenants
47. Are you sure you can do
this?
Let’s deep dive to
prove it!
49. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
50. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
51. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
52. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
53. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
55. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
77. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
78. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
79. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
84. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
85. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
90. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
91. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
101. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
102. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
113. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need.
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
114. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
115. Let’s recap ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
121. Let’s “check” ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
122. Let’s “check” ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
123. Let’s “check” ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
124. Let’s “check” ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
125. Let’s “check” ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
126. Let’s “check” ‘the requirements’ {
}
Shared UI components. That can be themed and
customized per need
Shared features. Data, business logic, UI
Architecture agnostic. Each tenant/platform can
have its own MVDeprecatedNextYear
Navigation independent. Each tenant will define
its own
Compose multiplatform support
130. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lessons.1 {
}
Life DSL
What we learned on the KMP journey
● Be sure what you are trying to accomplish
Do you need shared logic, features, components? For business sometimes it
all seems the same.
● Get the right team
Being an Android dev is not equivalent to developing KMP properly
● Act as one team, not 2 (Android & iOS)
This needs much closer alignment between OSes make sure that happens
● Start with less repos and break slowly
Multiple repos is cumbersome. Use submodules or merge repos if the team is
small
● iOS will be dependent on Android
Either have everyone working on KMP or make sure the Android team is large
enough
131. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lessons.1 {
}
Life DSL
What we learned on the KMP journey
● Be sure what you are trying to accomplish
Do you need shared logic, features, components? For business sometimes it
all seems the same.
● Get the right team
Being an Android dev is not equivalent to developing KMP properly
● Act as one team, not 2 (Android & iOS)
This needs much closer alignment between OSes make sure that happens
● Start with less repos and break slowly
Multiple repos is cumbersome. Use submodules or merge repos if the team is
small
● iOS will be dependent on Android
Either have everyone working on KMP or make sure the Android team is large
enough
132. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lessons.1 {
}
Life DSL
What we learned on the KMP journey
● Be sure what you are trying to accomplish
Do you need shared logic, features, components? For business sometimes it
all seems the same.
● Get the right team
Being an Android dev is not equivalent to developing KMP properly
● Act as one team, not 2 (Android & iOS)
This needs much closer alignment between OSes make sure that happens
● Start with less repos and break slowly
Multiple repos is cumbersome. Use submodules or merge repos if the team is
small
● iOS will be dependent on Android
Either have everyone working on KMP or make sure the Android team is large
enough
133. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lessons.1 {
}
Life DSL
What we learned on the KMP journey
● Be sure what you are trying to accomplish
Do you need shared logic, features, components? For business sometimes it
all seems the same.
● Get the right team
Being an Android dev is not equivalent to developing KMP properly
● Act as one team, not 2 (Android & iOS)
This needs much closer alignment between OSes make sure that happens
● Start with less repos and break slowly
Multiple repos is cumbersome. Use submodules or merge repos if the team is
small
● iOS will be dependent on Android
Either have everyone working on KMP or make sure the Android team is large
enough
134. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lessons.1 {
}
Life DSL
What we learned on the KMP journey
● Be sure what you are trying to accomplish
Do you need shared logic, features, components? For business sometimes it
all seems the same.
● Get the right team
Being an Android dev is not equivalent to developing KMP properly
● Act as one team, not 2 (Android & iOS)
This needs much closer alignment between OSes make sure that happens
● Start with less repos and break slowly
Multiple repos is cumbersome. Use submodules or merge repos if the team is
small
● iOS will be dependent on Android
Either have everyone working on KMP or make sure the Android team is large
enough
135. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lessons.2 {
}
Life DSL
What we learned on the KMP journey
● How agnostic do you want to be?
If another team picks up another tenant is it ok to change architectures?
● Compose Multiplatform vs Jetpack Compose
If there is a plan to support other platforms it’s simple to pick up
● Use design tokens
If possible use something like Toolabs with Figma to auto-generate code
● Desktop is useful to force decoupling,
but...
It’s a pain sometimes to support features that are more mobile aimed
136. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lessons.2 {
}
Life DSL
What we learned on the KMP journey
● How agnostic do you want to be?
If another team picks up another tenant is it ok to change architectures?
● Compose Multiplatform vs Jetpack Compose
If there is a plan to support other platforms it’s simple to pick up
● Use design tokens
If possible use something like Toolabs with Figma to auto-generate code
● Desktop is useful to force decoupling,
but...
It’s a pain sometimes to support features that are more mobile aimed
137. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lessons.2 {
}
Life DSL
What we learned on the KMP journey
● How agnostic do you want to be?
If another team picks up another tenant is it ok to change architectures?
● Compose Multiplatform vs Jetpack Compose
If there is a plan to support other platforms it’s simple to pick up
● Use design tokens
If possible use something like Toolabs with Figma to auto-generate code
● Desktop is useful to force decoupling,
but...
It’s a pain sometimes to support features that are more mobile aimed
138. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lessons.2 {
}
Life DSL
What we learned on the KMP journey
● How agnostic do you want to be?
If another team picks up another tenant is it ok to change architectures?
● Compose Multiplatform vs Jetpack Compose
If there is a plan to support other platforms it’s simple to pick up
● Use design tokens
If possible use something like Toolabs with Figma to auto-generate code
● Desktop is useful to force decoupling,
but...
It’s a pain sometimes to support features that are more mobile aimed
140. Drop by our yellow booth if you want to know more
about what we are building at Mindera
…or just go all in fanboy and insult us 🙈
We promise we’ll give you a 🤗
anyway!
Btw, we’re hiring!
141. Mobile is within our
core. We’re grateful to
work with iconic brands.