Exploring Android and iOS development with Compose Multiplatform, Koin, Ktor, SQLDelight, and build-time architecture enforcement.
Hey DEV Community! π
What if you could use a real cross-platform application to explore modern Kotlin architecture, modularization, and software engineering best practices?
Today, I'd like to introduce RestaurantApp, an open-source project I'm developing as part of ConnectApp, my independent initiative focused on building reusable software and sharing knowledge with the developer community.
RestaurantApp is built with Kotlin Multiplatform (KMP) and targets Android and iOS using Compose Multiplatform.
Although the project uses a restaurant-oriented application as its functional context, its main goal goes beyond restaurant management or reservations.
The real objective is to explore how to build a scalable, maintainable, and testable multiplatform application.
ποΈ Clean Architecture meets Kotlin Multiplatform
One of the most interesting aspects of RestaurantApp is its architecture.
The project follows Clean Architecture and the MVI (Model-View-Intent) pattern, with independent Gradle modules organized around features and responsibilities.
Rather than creating a few large modules, RestaurantApp separates its components into smaller units.
For example:
-
:domainβ Pure Kotlin business logic, models, repository interfaces, and use cases. -
:core:*β Shared infrastructure for networking, storage, database drivers, analytics, and MVI contracts. -
:data:*β Repository implementations, data sources, and mappers. -
:feature:*β Independent screens and user flows. -
:presentationβ Shared navigation and application shell. -
:composeAppβ Multiplatform composition root. -
:androidAppβ Android-specific launcher.
Each feature contains its own state, intents, effects, ViewModel, composables, and dependency injection configuration.
This allows developers to study individual parts of the application without having to understand the entire codebase at once.
π Architecture rules enforced at build time
One architectural decision I particularly wanted to explore was preventing unwanted dependencies between modules.
RestaurantApp includes a custom Gradle task:
./gradlew verifyModuleBoundaries
The task checks whether project modules respect the dependency rules established by the architecture.
For example, a feature module cannot directly depend on a data module.
If an invalid dependency is introduced, the build fails and identifies the offending modules.
This is an interesting approach because architectural principles are no longer just guidelines in the documentation.
They become rules that can be checked automatically.
π» The technology stack
RestaurantApp brings together several technologies from the Kotlin ecosystem:
- Kotlin Multiplatform β Shared application logic across platforms.
- Compose Multiplatform β Declarative user interfaces.
- Koin β Dependency injection.
- Ktor Client β HTTP communication.
- Kotlin Coroutines and Flow β Asynchronous operations and reactive state.
- SQLDelight β Local database persistence and offline caching.
- KVault β Platform-backed secure session storage.
- Navigation3 / Compose Navigation β Navigation between application screens.
- detekt β Static code analysis.
- Kover β Code coverage reporting.
For developers interested in moving beyond basic Kotlin applications, this provides several opportunities to study how different technologies work together.
π± Application features
The current project includes foundational application flows such as:
β Splash screen and initial navigation.
β Login, registration, and password recovery.
β Home dashboard.
β User profiles and account preferences.
β Material 3 theming.
β Locally cached orders and profile information.
β Optional crash and analytics reporting on Android.
The networking layer supports integration with a backend, but the repository does not deploy or provide a live backend service by itself.
This distinction is important: RestaurantApp is a reusable application architecture project, not a live restaurant reservation platform.
πΆ Offline-first development
Another interesting part of RestaurantApp is its local data strategy.
Using SQLDelight, certain information such as orders and profiles can remain available without an active network connection.
The application can serve cached data locally and refresh it when connectivity becomes
Top comments (0)