Skip to content

Latest commit

Β 

History

45 Commits

Folders and files

Repository files navigation

πŸ›οΈ Store App - MVI Compose Multiplatform Template ✨

A beautiful, modern E-Commerce application built with Compose Multiplatform featuring MVI architecture, type-safe navigation, and dynamic theming. Explore products, manage favorites/wishlist, add items to cart, and enjoy a seamless experience across Android, Desktop, and iOS platforms powered by DummyJSON API.

Store App Compose Multiplatform Preview

✨ Features

🎯 Core Features

  • πŸ“± Multiplatform: Android, Desktop, and iOS support with shared business logic and UI
  • πŸ—οΈ MVI Architecture: Clean, unidirectional data flow (Intent/Event -> ViewModel -> State & Effect)
  • 🧭 Type-Safe Navigation: Kotlin Serialization-based routing with adaptive navigation (Bottom Bar & Navigation Rail)
  • 🎨 Material 3 Design: Modern UI with dynamic theming and Material You integration
  • πŸŒ“ Theme Management: Dark / Light / System default modes + Android Dynamic Colors persisted via DataStore
  • πŸ’Ύ Offline Support: Room Multiplatform database with SQLite for persistent favorites and shopping cart
  • πŸ”„ Reactive UI: StateFlow and SharedFlow for real-time, responsive UI updates
  • πŸ‘οΈ MultiPreview Support: Comprehensive @ComponentPreviews, @AllAdaptivePreviews, and @PhonePreview annotations with custom MyThemeWrapper

πŸ›οΈ Product & E-Commerce Features

  • πŸ” Product Catalog: Browse products with infinite scroll pagination and pull-to-refresh
  • πŸ”Ž Instant Search & Filters: 350ms debounced live search, horizontal category pill filter, and dynamic sorting by Price (Low/High) & Rating
  • πŸ›’ Shopping Cart System: Room DB persisted cart with real-time bottom nav badge, quantity controls, discount calculations, item deletion, and checkout simulation
  • πŸ‘€ User Authentication & Profile: JWT token persistence via DataStore, 1-click demo login (emilys), detailed user profile view, and logout support
  • ❀️ Favorites / Wishlist: Add/remove products from favorites with swipe-to-delete gesture
  • πŸ“Š Rich Detailed View: Image carousel, price, discount tags, ratings, stock status, specs, customer reviews, and direct "Add to Cart" action
  • ✨ Shimmer Loading: Polished shimmer placeholder animations for smooth loading states

🎭 UI/UX Features

  • 🌊 Smooth Animations: Animated transitions, bottom sheet modals, and micro-interactions
  • πŸ“± Adaptive UI: Responsive layouts scaling seamlessly from phones to tablets and desktop screens
  • πŸ‘† Swipe Actions: Swipe-to-delete favorites with background reveal
  • 🌈 Dynamic Colors: Android 12+ Material You dynamic color extraction
  • ⚑ Performance: Optimized with Coil3 image caching, Room query flows, and lazy composables

Getting Started

Installation πŸ› οΈ

  1. Clone this repository:
    git clone https://github.com/Coding-Meet/CMP-MVI-Template.git
  2. Open in the latest version of Android Studio or IntelliJ IDEA.
  3. Build configuration with BuildConfig (via BuildKonfig): Create or update your local.properties file in the project root:
    Is_Debug_Build=true
    (Note: The app is powered by the public DummyJSON API β€” no external API key is required!)

Run the app on your device or emulator:

  • Android: Run the androidApp module by selecting the app run configuration in Android Studio.
  • iOS: Run the iosApp scheme in Xcode or via Android Studio's Kotlin Multiplatform plugin.
  • Desktop: Run the Gradle task:
    ./gradlew :desktopApp:run

Screenshots πŸ’»

πŸ“± Android (Google Pixel 9)

πŸŒ™ Dark Mode (12 Screens β€” Click to collapse)
01. Products Catalog
Products Catalog
02. Shimmer Loading
Shimmer Loading
03. Live Search & Filters
Search & Filters
04. Sort Bottom Sheet
Sort Sheet
05. Product Details
Product Details
06. Shopping Cart
Shopping Cart
07. Checkout Dialog
Checkout Dialog
08. Favorites / Wishlist
Favorites
09. User Profile (Auth)
User Profile
10. Settings Screen
Settings
11. Theme Selection
Theme Selection
12. Onboarding
Onboarding
β˜€οΈ Light Mode (12 Screens β€” Click to expand)
01. Products Catalog
Products Catalog
02. Shimmer Loading
Shimmer Loading
03. Live Search & Filters
Search & Filters
04. Sort Bottom Sheet
Sort Sheet
05. Product Details
Product Details
06. Shopping Cart
Shopping Cart
07. Checkout Dialog
Checkout Dialog
08. Favorites / Wishlist
Favorites
09. User Profile (Auth)
User Profile
10. Settings Screen
Settings
11. Theme Selection
Theme Selection
12. Onboarding
Onboarding

🍎 iOS (Apple iPhone 16 Pro)

πŸŒ™ Dark Mode (12 Screens β€” Click to collapse)
01. Products Catalog
Products Catalog
02. Shimmer Loading
Shimmer Loading
03. Live Search & Filters
Search & Filters
04. Sort Bottom Sheet
Sort Sheet
05. Product Details
Product Details
06. Shopping Cart
Shopping Cart
07. Checkout Dialog
Checkout Dialog
08. Favorites / Wishlist
Favorites
09. User Profile (Auth)
User Profile
10. Settings Screen
Settings
11. Theme Selection
Theme Selection
12. Onboarding
Onboarding
β˜€οΈ Light Mode (12 Screens β€” Click to expand)
01. Products Catalog
Products Catalog
02. Shimmer Loading
Shimmer Loading
03. Live Search & Filters
Search & Filters
04. Sort Bottom Sheet
Sort Sheet
05. Product Details
Product Details
06. Shopping Cart
Shopping Cart
07. Checkout Dialog
Checkout Dialog
08. Favorites / Wishlist
Favorites
09. User Profile (Auth)
User Profile
10. Settings Screen
Settings
11. Theme Selection
Theme Selection
12. Onboarding
Onboarding

πŸ–₯️ Desktop (macOS Large Window Two-Pane Layout)

πŸŒ™ Dark Mode (7 Screens β€” Click to collapse)
01. Products Catalog
Products Catalog
02. Product Details
Product Details
03. Shopping Cart Summary
Shopping Cart Summary
04. Favorites Wishlist
Favorites Wishlist
05. User Profile
User Profile
06. Settings Screen
Settings Screen
07. Theme Selection Dialog
Theme Selection Dialog
β˜€οΈ Light Mode (7 Screens β€” Click to expand)
01. Products Catalog
Products Catalog
02. Product Details
Product Details
03. Shopping Cart Summary
Shopping Cart Summary
04. Favorites Wishlist
Favorites Wishlist
05. User Profile
User Profile
06. Settings Screen
Settings Screen
07. Theme Selection Dialog
Theme Selection Dialog

🌐 Web (Google Chrome Browser Frame)

πŸŒ™ Dark Mode (7 Screens β€” Click to collapse)
01. Products Catalog
Web Products Catalog
02. Product Details
Web Product Details
03. Shopping Cart Summary
Web Shopping Cart
04. Favorites Wishlist
Web Favorites
05. User Profile
Web User Profile
06. Settings Screen
Web Settings
07. Theme Selection Dialog
Web Theme Dialog
β˜€οΈ Light Mode (7 Screens β€” Click to expand)
01. Products Catalog
Web Products Catalog
02. Product Details
Web Product Details
03. Shopping Cart Summary
Web Shopping Cart
04. Favorites Wishlist
Web Favorites
05. User Profile
Web User Profile
06. Settings Screen
Web Settings
07. Theme Selection Dialog
Web Theme Dialog

πŸ—οΈ Architecture

Clean Architecture + MVI Pattern

πŸ“± Presentation Layer (UI)
β”œβ”€β”€ 🎭 Compose Screens (Declarative UI)
β”œβ”€β”€ 🧠 ViewModels (MVI State & Effect Emitters)
└── πŸ“Š State Management (StateFlow & SharedFlow)

πŸ’Ό Domain Layer (Business Logic)  
β”œβ”€β”€ πŸ“‹ Use Cases (Single-responsibility business rules)
β”œβ”€β”€ πŸͺ Repository Interfaces (Domain contracts)
└── πŸ“¦ Domain Models (Pure Kotlin entities)

πŸ’Ύ Data Layer (Data Sources)
β”œβ”€β”€ 🌐 Remote (Ktor + DummyJSON API)
β”œβ”€β”€ πŸ’Ώ Local (Room Database + Preferences DataStore)  
└── πŸ”„ Repository Implementation (Data orchestration & mapping)

Tech Stack

  • 🎯 UI: Compose Multiplatform + Material 3 + Adaptive Layouts
  • πŸ—οΈ Architecture: MVI (Model-View-Intent) + Clean Architecture + Domain Use Cases
  • 🧭 Navigation: Jetpack Compose Navigation + Type-safe Serialization Routes
  • 🌐 Networking: Ktor Client (CIO / Darwin / OkHttp) + kotlinx.serialization
  • πŸ’Ύ Database: Room Multiplatform + SQLite Bundled Driver
  • 🎨 Theming & Preferences: androidx.datastore (Preferences DataStore)
  • πŸ”§ Dependency Injection: Koin Multiplatform
  • πŸ–ΌοΈ Image Loading: Coil3 (Async Image Loading & Memory Caching)

πŸ“ Project Structure

CMP-MVI-Template/
β”œβ”€β”€ shared/                                 # βœ… KMP library β€” shared code for all platforms
β”‚   β”œβ”€β”€ build.gradle.kts                    # βž• Gradle config (com.android.kotlin.multiplatform.library)
β”‚   β”œβ”€β”€ setting.preferences_pb              # πŸ“¦ Proto DataStore schema for user settings
β”‚   β”‚
β”‚   └── src/
β”‚       β”œβ”€β”€ androidMain/                    # πŸ€– Android-specific implementations (Toast, SQLite Driver, Engine)
β”‚       β”œβ”€β”€ iosMain/                        # 🍎 iOS-specific code (Darwin HTTP Engine, MainViewController)
β”‚       β”œβ”€β”€ desktopMain/                    # πŸ–₯ Desktop-specific implementations (JVM Engine, Toast)
β”‚       β”‚
β”‚       β”œβ”€β”€ commonMain/                     # πŸ” Shared code between all platforms
β”‚       β”‚   β”œβ”€β”€ composeResources/           # 🎨 Compose Multiplatform resources (drawables, strings)
β”‚       β”‚   └── kotlin/com/example/cmp_mvi_template/
β”‚       β”‚       β”œβ”€β”€ app/                    # 🌐 Root app navigation, AppScaffold, AppViewModel
β”‚       β”‚       β”œβ”€β”€ di/                     # 🧩 Dependency Injection modules (AppModule, CoreModule, initKoin)
β”‚       β”‚       β”œβ”€β”€ core/                   # πŸ“š Core reusable utilities, domain errors, networking, local DB
β”‚       β”‚       β”‚   β”œβ”€β”€ data/               # πŸ—ƒοΈ Local database, DataStore, Ktor client factory
β”‚       β”‚       β”‚   β”œβ”€β”€ domain/             # πŸ“¦ Base models, ResultWrapper, DataError, Paginator
β”‚       β”‚       β”‚   β”œβ”€β”€ platform/           # 🌍 Expect/actual platform bridges (Database, Toast, DataStore)
β”‚       β”‚       β”‚   └── utility/            # πŸ”§ WindowSize, AppLogger, UiText, StateController
β”‚       β”‚       β”œβ”€β”€ ui/                     # 🧱 Reusable UI components, themes, and dialogs
β”‚       β”‚       β”‚   β”œβ”€β”€ component/          # 🧩 15+ Material3 custom components (Buttons, TopAppBar, etc.)
β”‚       β”‚       β”‚   β”œβ”€β”€ dialog/             # πŸ’¬ ToastPopup, LoadingDialog
β”‚       β”‚       β”‚   β”œβ”€β”€ layout/             # πŸ“ ErrorMessageLayout
β”‚       β”‚       β”‚   β”œβ”€β”€ navigation/         # 🧭 AdaptiveNavigation, BottomNavigationBar, Destinations
β”‚       β”‚       β”‚   └── theme/              # 🎨 Material3 Theme, Dimens, and MultiPreview Annotations
β”‚       β”‚       └── feature/                # 🌟 Feature modules (Clean Architecture + MVI per feature)
β”‚       β”‚           β”œβ”€β”€ product/            # πŸ›οΈ Catalog, Search, Categories, Sort, Details, Favorites
β”‚       β”‚           β”œβ”€β”€ cart/               # πŸ›’ Room-backed Shopping Cart & Checkout
β”‚       β”‚           β”œβ”€β”€ auth/               # πŸ‘€ User Authentication & Profile (DataStore JWT token)
β”‚       β”‚           β”œβ”€β”€ onboarding/         # πŸš€ First-launch Onboarding Pager
β”‚       β”‚           β”œβ”€β”€ splash/             # ⏳ App Splash Flow & Initial Route Resolution
β”‚       β”‚           β”œβ”€β”€ setting/            # βš™οΈ Theme Selection & Dynamic Colors
β”‚       β”‚           └── sample_example/     # πŸ§ͺ Reference MVI feature template
β”‚       β”‚
β”‚       └── commonTest/                     # πŸ§ͺ Shared unit tests
β”‚
β”œβ”€β”€ androidApp/                             # πŸ€– Android entry point module
β”‚   β”œβ”€β”€ build.gradle.kts                    # βž• Gradle config (com.android.application)
β”‚   └── src/main/kotlin/                    # πŸš€ MainActivity & MyApplication (Koin setup)
β”‚
β”œβ”€β”€ desktopApp/                             # πŸ–₯ Desktop entry point module
β”‚   β”œβ”€β”€ build.gradle.kts                    # βž• Gradle config (Compose Desktop application)
β”‚   └── src/desktopMain/kotlin/             # πŸ’» Desktop launcher (main.kt)
β”‚
└── iosApp/                                 # 🍎 iOS Xcode project entry point

πŸ“ Detailed Project Structure

└── CMP-MVI-Template/
β”œβ”€β”€ androidApp/
β”‚   β”œβ”€β”€ build.gradle.kts
β”‚   └── src/main/
β”‚       β”œβ”€β”€ AndroidManifest.xml
β”‚       └── kotlin/com/example/cmp_mvi_template/
β”‚           β”œβ”€β”€ MyApplication.kt
β”‚           └── MainActivity.kt
β”œβ”€β”€ desktopApp/
β”‚   β”œβ”€β”€ build.gradle.kts
β”‚   └── src/desktopMain/kotlin/com/example/cmp_mvi_template/
β”‚       └── main.kt
β”œβ”€β”€ shared/
β”‚   β”œβ”€β”€ build.gradle.kts
β”‚   └── src/
β”‚       β”œβ”€β”€ androidMain/kotlin/com/example/cmp_mvi_template/core/platform/
β”‚       β”‚   β”œβ”€β”€ theme/PlatformTheme.android.kt
β”‚       β”‚   β”œβ”€β”€ datastore/createDataStore.android.kt
β”‚       β”‚   β”œβ”€β”€ toast/AndroidToastManager.kt
β”‚       β”‚   β”œβ”€β”€ http_engine/GetHttpClientEngine.android.kt
β”‚       β”‚   └── database/getDatabaseBuilder.android.kt
β”‚       β”œβ”€β”€ commonMain/
β”‚       β”‚   β”œβ”€β”€ composeResources/
β”‚       β”‚   β”‚   β”œβ”€β”€ drawable/
β”‚       β”‚   β”‚   └── values/strings.xml
β”‚       β”‚   └── kotlin/com/example/cmp_mvi_template/
β”‚       β”‚       β”œβ”€β”€ app/
β”‚       β”‚       β”‚   β”œβ”€β”€ presentation/
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ App.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ AppThemeState.kt
β”‚       β”‚       β”‚   β”‚   └── AppViewModel.kt
β”‚       β”‚       β”‚   └── di/AppModule.kt
β”‚       β”‚       β”œβ”€β”€ di/
β”‚       β”‚       β”‚   β”œβ”€β”€ initKoin.kt
β”‚       β”‚       β”‚   └── CoreModule.kt
β”‚       β”‚       β”œβ”€β”€ core/
β”‚       β”‚       β”‚   β”œβ”€β”€ data/
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ datastore/
β”‚       β”‚       β”‚   β”‚   β”‚   β”œβ”€β”€ ThemeMode.kt
β”‚       β”‚       β”‚   β”‚   β”‚   β”œβ”€β”€ ThemePreferences.kt
β”‚       β”‚       β”‚   β”‚   β”‚   └── onboarding/OnboardingPreferences.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ local/
β”‚       β”‚       β”‚   β”‚   β”‚   β”œβ”€β”€ AppDatabase.kt
β”‚       β”‚       β”‚   β”‚   β”‚   β”œβ”€β”€ AppDatabaseConstructor.kt
β”‚       β”‚       β”‚   β”‚   β”‚   └── dao/
β”‚       β”‚       β”‚   β”‚   β”‚       β”œβ”€β”€ ProductDao.kt
β”‚       β”‚       β”‚   β”‚   β”‚       └── CartDao.kt
β”‚       β”‚       β”‚   β”‚   └── network/
β”‚       β”‚       β”‚   β”‚       β”œβ”€β”€ HttpClientFactory.kt
β”‚       β”‚       β”‚   β”‚       └── NetworkExtensions.kt
β”‚       β”‚       β”‚   β”œβ”€β”€ domain/
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ DataError.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ DataErrorToUiTextExtension.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ Error.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ Paginator.kt
β”‚       β”‚       β”‚   β”‚   └── ResultWrapper.kt
β”‚       β”‚       β”‚   β”œβ”€β”€ platform/
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ database/getDatabaseBuilder.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ datastore/AppSettings.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ datastore/createDataStore.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ http_engine/GetHttpClientEngine.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ theme/PlatformTheme.kt
β”‚       β”‚       β”‚   β”‚   └── toast/
β”‚       β”‚       β”‚   β”‚       β”œβ”€β”€ ToastDuration.kt
β”‚       β”‚       β”‚   β”‚       β”œβ”€β”€ ToastManager.kt
β”‚       β”‚       β”‚   β”‚       └── ToastManagerFactory.kt
β”‚       β”‚       β”‚   └── utility/
β”‚       β”‚       β”‚       β”œβ”€β”€ AppLogger.kt
β”‚       β”‚       β”‚       β”œβ”€β”€ ComposableExtensions.kt
β”‚       β”‚       β”‚       β”œβ”€β”€ IconResource.kt
β”‚       β”‚       β”‚       β”œβ”€β”€ StateController.kt
β”‚       β”‚       β”‚       β”œβ”€β”€ UiText.kt
β”‚       β”‚       β”‚       └── WindowSize.kt
β”‚       β”‚       β”œβ”€β”€ ui/
β”‚       β”‚       β”‚   β”œβ”€β”€ component/
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ badges/Badges.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ bottom_app_bar/BottomAppBar.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ button/Button.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ checkbox/Checkbox.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ divider/Divider.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ fab/Fab.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ icon_button/IconButton.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ navigation_bar/NavigationBar.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ progress_indicator/ProgressIndicators.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ radio_button/RadioButton.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ segmented_button/SegmentedButton.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ slider/Slider.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ switch_custom/Switch.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ text/Text.kt
β”‚       β”‚       β”‚   β”‚   └── top_app_bar/TopAppBar.kt
β”‚       β”‚       β”‚   β”œβ”€β”€ dialog/
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ LoadingDialog.kt
β”‚       β”‚       β”‚   β”‚   └── ToastPopup.kt
β”‚       β”‚       β”‚   β”œβ”€β”€ layout/ErrorMessageLayout.kt
β”‚       β”‚       β”‚   β”œβ”€β”€ navigation/
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ AdaptiveNavigation.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ AppDestination.kt
β”‚       β”‚       β”‚   β”‚   β”œβ”€β”€ NavigationExtensions.kt
β”‚       β”‚       β”‚   β”‚   └── bottom_navigation_bar/
β”‚       β”‚       β”‚   β”‚       β”œβ”€β”€ BottomNavigationBar.kt
β”‚       β”‚       β”‚   β”‚       └── NavigationItem.kt
β”‚       β”‚       β”‚   └── theme/
β”‚       β”‚       β”‚       β”œβ”€β”€ AnnotationPreview.kt
β”‚       β”‚       β”‚       β”œβ”€β”€ Color.kt
β”‚       β”‚       β”‚       β”œβ”€β”€ Dimens.kt
β”‚       β”‚       β”‚       β”œβ”€β”€ Theme.kt
β”‚       β”‚       β”‚       └── Type.kt
β”‚       β”‚       └── feature/
β”‚       β”‚           β”œβ”€β”€ product/
β”‚       β”‚           β”‚   β”œβ”€β”€ di/ProductModule.kt
β”‚       β”‚           β”‚   β”œβ”€β”€ data/
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ mapper/toDomain.kt
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ remote/
β”‚       β”‚           β”‚   β”‚   β”‚   β”œβ”€β”€ api/
β”‚       β”‚           β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ProductApiService.kt
β”‚       β”‚           β”‚   β”‚   β”‚   β”‚   └── ProductApiServiceImpl.kt
β”‚       β”‚           β”‚   β”‚   β”‚   └── dto/ProductDto.kt
β”‚       β”‚           β”‚   β”‚   └── repository/ProductRepositoryImpl.kt
β”‚       β”‚           β”‚   β”œβ”€β”€ domain/
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ entity/
β”‚       β”‚           β”‚   β”‚   β”‚   β”œβ”€β”€ Product.kt
β”‚       β”‚           β”‚   β”‚   β”‚   └── ProductEntity.kt
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ repository/ProductRepository.kt
β”‚       β”‚           β”‚   β”‚   └── usecase/
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ CheckIfProductFavoriteUseCase.kt
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ GetCategoriesUseCase.kt
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ GetFavoriteProductsUseCase.kt
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ GetProductDetailsUseCase.kt
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ GetProductListUseCase.kt
β”‚       β”‚           β”‚   β”‚       └── ToggleFavoriteProductUseCase.kt
β”‚       β”‚           β”‚   └── presentation/
β”‚       β”‚           β”‚       β”œβ”€β”€ component/
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ ProductCard.kt
β”‚       β”‚           β”‚       β”‚   └── ShimmerEffect.kt
β”‚       β”‚           β”‚       β”œβ”€β”€ product_list/
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ component/
β”‚       β”‚           β”‚       β”‚   β”‚   β”œβ”€β”€ CategoryChipsRow.kt
β”‚       β”‚           β”‚       β”‚   β”‚   β”œβ”€β”€ ProductListContent.kt
β”‚       β”‚           β”‚       β”‚   β”‚   └── SortBottomSheet.kt
β”‚       β”‚           β”‚       β”‚   └── screen/
β”‚       β”‚           β”‚       β”‚       β”œβ”€β”€ ProductListEffect.kt
β”‚       β”‚           β”‚       β”‚       β”œβ”€β”€ ProductListEvent.kt
β”‚       β”‚           β”‚       β”‚       β”œβ”€β”€ ProductListScreen.kt
β”‚       β”‚           β”‚       β”‚       β”œβ”€β”€ ProductListState.kt
β”‚       β”‚           β”‚       β”‚       └── ProductListViewModel.kt
β”‚       β”‚           β”‚       β”œβ”€β”€ product_details/
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ component/
β”‚       β”‚           β”‚       β”‚   β”‚   β”œβ”€β”€ ProductDetailsContent.kt
β”‚       β”‚           β”‚       β”‚   β”‚   β”œβ”€β”€ ProductImageCarousel.kt
β”‚       β”‚           β”‚       β”‚   β”‚   β”œβ”€β”€ ProductInfoSection.kt
β”‚       β”‚           β”‚       β”‚   β”‚   β”œβ”€β”€ ProductReviewsSection.kt
β”‚       β”‚           β”‚       β”‚   β”‚   └── ProductSpecsSection.kt
β”‚       β”‚           β”‚       β”‚   └── screen/
β”‚       β”‚           β”‚       β”‚       β”œβ”€β”€ ProductDetailsEffect.kt
β”‚       β”‚           β”‚       β”‚       β”œβ”€β”€ ProductDetailsEvent.kt
β”‚       β”‚           β”‚       β”‚       β”œβ”€β”€ ProductDetailsScreen.kt
β”‚       β”‚           β”‚       β”‚       β”œβ”€β”€ ProductDetailsState.kt
β”‚       β”‚           β”‚       β”‚       └── ProductDetailsViewModel.kt
β”‚       β”‚           β”‚       └── favorites/
β”‚       β”‚           β”‚           β”œβ”€β”€ component/
β”‚       β”‚           β”‚           β”‚   β”œβ”€β”€ EmptyFavoritesScreen.kt
β”‚       β”‚           β”‚           β”‚   β”œβ”€β”€ FavoritesListContent.kt
β”‚       β”‚           β”‚           β”‚   └── SwipeToDeleteProductCard.kt
β”‚       β”‚           β”‚           └── screen/
β”‚       β”‚           β”‚               β”œβ”€β”€ FavoritesEffect.kt
β”‚       β”‚           β”‚               β”œβ”€β”€ FavoritesEvent.kt
β”‚       β”‚           β”‚               β”œβ”€β”€ FavoritesScreen.kt
β”‚       β”‚           β”‚               β”œβ”€β”€ FavoritesState.kt
β”‚       β”‚           β”‚               └── FavoritesViewModel.kt
β”‚       β”‚           β”œβ”€β”€ cart/
β”‚       β”‚           β”‚   β”œβ”€β”€ di/CartModule.kt
β”‚       β”‚           β”‚   β”œβ”€β”€ data/
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ mapper/toDomain.kt
β”‚       β”‚           β”‚   β”‚   └── repository/CartRepositoryImpl.kt
β”‚       β”‚           β”‚   β”œβ”€β”€ domain/
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ entity/
β”‚       β”‚           β”‚   β”‚   β”‚   β”œβ”€β”€ CartItem.kt
β”‚       β”‚           β”‚   β”‚   β”‚   └── CartItemEntity.kt
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ repository/CartRepository.kt
β”‚       β”‚           β”‚   β”‚   └── usecase/
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ AddToCartUseCase.kt
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ ClearCartUseCase.kt
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ GetCartCountUseCase.kt
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ GetCartItemsUseCase.kt
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ RemoveFromCartUseCase.kt
β”‚       β”‚           β”‚   β”‚       └── UpdateCartQuantityUseCase.kt
β”‚       β”‚           β”‚   └── presentation/
β”‚       β”‚           β”‚       β”œβ”€β”€ component/
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ CartItemCard.kt
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ CartSummaryCard.kt
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ CheckoutSuccessDialog.kt
β”‚       β”‚           β”‚       β”‚   └── EmptyCartScreen.kt
β”‚       β”‚           β”‚       └── screen/
β”‚       β”‚           β”‚           β”œβ”€β”€ CartEffect.kt
β”‚       β”‚           β”‚           β”œβ”€β”€ CartEvent.kt
β”‚       β”‚           β”‚           β”œβ”€β”€ CartScreen.kt
β”‚       β”‚           β”‚           β”œβ”€β”€ CartState.kt
β”‚       β”‚           β”‚           └── CartViewModel.kt
β”‚       β”‚           β”œβ”€β”€ auth/
β”‚       β”‚           β”‚   β”œβ”€β”€ di/AuthModule.kt
β”‚       β”‚           β”‚   β”œβ”€β”€ data/
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ datastore/AuthPreferences.kt
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ mapper/toDomain.kt
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ remote/
β”‚       β”‚           β”‚   β”‚   β”‚   β”œβ”€β”€ api/
β”‚       β”‚           β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ AuthApiService.kt
β”‚       β”‚           β”‚   β”‚   β”‚   β”‚   └── AuthApiServiceImpl.kt
β”‚       β”‚           β”‚   β”‚   β”‚   └── dto/AuthDto.kt
β”‚       β”‚           β”‚   β”‚   └── repository/AuthRepositoryImpl.kt
β”‚       β”‚           β”‚   β”œβ”€β”€ domain/
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ entity/AuthUser.kt
β”‚       β”‚           β”‚   β”‚   β”œβ”€β”€ repository/AuthRepository.kt
β”‚       β”‚           β”‚   β”‚   └── usecase/
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ GetAuthStateUseCase.kt
β”‚       β”‚           β”‚   β”‚       β”œβ”€β”€ LoginUseCase.kt
β”‚       β”‚           β”‚   β”‚       └── LogoutUseCase.kt
β”‚       β”‚           β”‚   └── presentation/screen/
β”‚       β”‚           β”‚       β”œβ”€β”€ AuthEffect.kt
β”‚       β”‚           β”‚       β”œβ”€β”€ AuthEvent.kt
β”‚       β”‚           β”‚       β”œβ”€β”€ AuthState.kt
β”‚       β”‚           β”‚       β”œβ”€β”€ AuthViewModel.kt
β”‚       β”‚           β”‚       └── ProfileScreen.kt
β”‚       β”‚           β”œβ”€β”€ onboarding/
β”‚       β”‚           β”‚   β”œβ”€β”€ di/OnboardingModule.kt
β”‚       β”‚           β”‚   └── presentation/
β”‚       β”‚           β”‚       β”œβ”€β”€ model/OnboardingPage.kt
β”‚       β”‚           β”‚       β”œβ”€β”€ component/
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ OnboardingPageContent.kt
β”‚       β”‚           β”‚       β”‚   └── OnboardingPageIndicator.kt
β”‚       β”‚           β”‚       └── screen/
β”‚       β”‚           β”‚           β”œβ”€β”€ OnboardingEffect.kt
β”‚       β”‚           β”‚           β”œβ”€β”€ OnboardingEvent.kt
β”‚       β”‚           β”‚           β”œβ”€β”€ OnboardingScreen.kt
β”‚       β”‚           β”‚           β”œβ”€β”€ OnboardingState.kt
β”‚       β”‚           β”‚           └── OnboardingViewModel.kt
β”‚       β”‚           β”œβ”€β”€ splash/
β”‚       β”‚           β”‚   β”œβ”€β”€ di/SplashModule.kt
β”‚       β”‚           β”‚   └── presentation/screen/
β”‚       β”‚           β”‚       β”œβ”€β”€ SplashEffect.kt
β”‚       β”‚           β”‚       β”œβ”€β”€ SplashScreen.kt
β”‚       β”‚           β”‚       └── SplashViewModel.kt
β”‚       β”‚           β”œβ”€β”€ setting/
β”‚       β”‚           β”‚   β”œβ”€β”€ di/SettingModule.kt
β”‚       β”‚           β”‚   └── presentation/
β”‚       β”‚           β”‚       β”œβ”€β”€ component/
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ DynamicThemeToggleAndroidOnly.kt
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ ThemePreview.kt
β”‚       β”‚           β”‚       β”‚   β”œβ”€β”€ ThemeSelectionDialog.kt
β”‚       β”‚           β”‚       β”‚   └── ThemeSelectionRow.kt
β”‚       β”‚           β”‚       └── screen/
β”‚       β”‚           β”‚           β”œβ”€β”€ SettingEffect.kt
β”‚       β”‚           β”‚           β”œβ”€β”€ SettingEvent.kt
β”‚       β”‚           β”‚           β”œβ”€β”€ SettingScreen.kt
β”‚       β”‚           β”‚           β”œβ”€β”€ SettingState.kt
β”‚       β”‚           β”‚           └── SettingViewModel.kt
β”‚       β”‚           └── sample_example/
β”‚       β”‚               β”œβ”€β”€ di/SampleExampleModule.kt
β”‚       β”‚               └── presentation/screen/
β”‚       β”‚                   β”œβ”€β”€ SampleEffect.kt
β”‚       β”‚                   β”œβ”€β”€ SampleEvent.kt
β”‚       β”‚                   β”œβ”€β”€ SampleExampleScreen.kt
β”‚       β”‚                   β”œβ”€β”€ SampleExampleViewModel.kt
β”‚       β”‚                   └── SampleState.kt
β”‚       β”œβ”€β”€ desktopMain/kotlin/com/example/cmp_mvi_template/core/platform/
β”‚       β”‚   β”œβ”€β”€ database/getDatabaseBuilder.desktop.kt
β”‚       β”‚   β”œβ”€β”€ datastore/createDataStore.desktop.kt
β”‚       β”‚   β”œβ”€β”€ http_engine/GetHttpClientEngine.desktop.kt
β”‚       β”‚   β”œβ”€β”€ theme/PlatformTheme.desktop.kt
β”‚       β”‚   └── toast/
β”‚       β”‚       β”œβ”€β”€ DesktopToastManager.kt
β”‚       β”‚       β”œβ”€β”€ RoundedPanel.kt
β”‚       β”‚       └── ToastManager.desktop.kt
β”‚       β”œβ”€β”€ iosMain/kotlin/com/example/cmp_mvi_template/
β”‚       β”‚   β”œβ”€β”€ MainViewController.kt
β”‚       β”‚   └── core/platform/
β”‚       β”‚       β”œβ”€β”€ database/getDatabaseBuilder.ios.kt
β”‚       β”‚       β”œβ”€β”€ datastore/createDataStore.ios.kt
β”‚       β”‚       β”œβ”€β”€ http_engine/GetHttpClientEngine.ios.kt
β”‚       β”‚       β”œβ”€β”€ theme/PlatformTheme.ios.kt
β”‚       β”‚       └── toast/
β”‚       β”‚           β”œβ”€β”€ IosToastManager.kt
β”‚       β”‚           └── ToastManager.ios.kt
β”‚       └── commonTest/kotlin/com/example/cmp_mvi_template/
β”‚           └── ComposeAppCommonTest.kt

🎯 Next Goals

Here are upcoming feature enhancements and engineering improvements planned for the project:

  • 🏷️ Koin Annotations Integration

    • Integrate Koin Annotations processing (@Single, @Factory) to reduce manual DI module boilerplate.
  • πŸ’³ Payment & Checkout Gateway

    • Integrate simulated/live payment flows (Stripe / Mock Gateway) into the checkout experience.
  • πŸ”” Push Notifications

    • Multiplatform push notifications for order updates and flash sale alerts.
  • βš™οΈ Dev Tooling & Automation Scripts

    • Create Gradle scripts for automatic feature module scaffolding (generating MVI contracts, ViewModel, and screen templates).
    • Package renaming automation scripts.
  • πŸ§ͺ Unit & UI Flow Testing

    • Comprehensive unit testing for UseCases, ViewModels, and Room DAOs.
    • Integration with Maestro for end-to-end multiplatform UI flow tests.

Contributing 🀝

Feel free to contribute to this project by submitting issues, feature suggestions, or pull requests. Your contributions are always welcome! πŸ™Œ

❀ Show your support

Give a ⭐️ if this project helped you!

Buy Me A Coffee

Your generosity is greatly appreciated! Thank you for supporting this project.

Connect with me

Author

Meet