Basket Scan and Go is a modern cross-platform shopping application that revolutionizes the in-store shopping experience. Customers can scan product barcodes using their mobile device, add items to a virtual basket, and complete checkout without waiting in traditional checkout lines.
The application is built using Kotlin Multiplatform (KMP) and Compose Multiplatform, enabling a shared codebase across Android, iOS, Desktop, and Web (WasmJS) platforms. This approach maximizes code reuse while delivering native performance and user experience on each platform.
- Product Scanning: Scan product barcodes using the device camera to instantly add items to your basket
- Basket Management: Create, view, modify, and delete shopping baskets with real-time price calculations
- User Authentication: Secure login and registration with session management
- Shared Baskets: Collaborate with family or friends by sharing baskets across devices
- Cross-Platform: Single codebase runs on Android, iOS, Desktop (JVM), and Web (WasmJS)
- Offline Support: Continue shopping even with intermittent connectivity
- Backend Server: Ktor-based REST API server for data persistence and synchronization
| Layer | Technology |
|---|---|
| UI Framework | Compose Multiplatform |
| Language | Kotlin 2.x |
| Networking | Ktor Client |
| Serialization | Kotlinx Serialization |
| DI | Koin |
| Backend | Ktor Server (Netty) |
| Architecture | Clean Architecture + MVI |
- π§© Compose Multiplatform; for shared UI
- π Ktor; for networking
- π¦ Kotlinx Serialization; for content negotiation
- π°οΈ Kotlinx Datetime; for datetime
- π§Ή ktlint; for Kotlin linting and formatting
- π Kotlin Coroutines; for asynchronous programming
- π Koin; for dependency injection
When developing with a mobile device or switching networks, you need to update the server IP address in the client configuration. Helper scripts are provided in the scripts/ folder to automate this:
macOS/Linux:
./scripts/update-server-ip.shWindows:
scripts\update-server-ip.batThese scripts will:
- Auto-detect your machine's current IP address
- Update the client configuration file (
BasketApiServerPathProviderImpl.kt)
Note: The server is configured to listen on
0.0.0.0(all network interfaces), so it's accessible from any device on the same network.
The project includes pre-configured run configurations in .idea/runConfigurations/. After opening the project, you'll find these configurations in the Run/Debug dropdown:
| Configuration | Task | Description |
|---|---|---|
| Android App | :apps:androidApp:installDebug |
Run Android app on device/emulator |
| Desktop App | :apps:desktopApp:run |
Run desktop JVM application |
| Web WASM App | :apps:webApp:wasmJsBrowserDevelopmentRun |
Run WasmJS app in browser |
| Build All | build |
Build all modules |
| Ktlint Check | ktlintCheck |
Run ktlint code style check |
| iOS Framework | :apps:shared:embedAndSignAppleFrameworkForXcode |
Build iOS framework for Xcode |
| Server | :basket-server:run |
Run the Ktor backend server |
Open Run Config action:
or you can run it from file .fleet/run.json
| Platform | Gradle Command |
|---|---|
| Android | ./gradlew :apps:androidApp:installDebug |
| Desktop | ./gradlew :apps:desktopApp:run |
| Web (WasmJS) | ./gradlew :apps:webApp:wasmJsBrowserDevelopmentRun |
| iOS Framework | ./gradlew :apps:shared:linkDebugFrameworkIosSimulatorArm64 |
| Server | ./gradlew :basket-server:run |
| Build All | ./gradlew assemble |
This project uses ktlint for Kotlin code style checking and formatting. ktlint is a linter with built-in formatter that enforces the official Kotlin code style.
./gradlew ktlintCheck- Run ktlint check on all modules./gradlew ktlintFormat- Run ktlint format on all modules to automatically fix style violations./gradlew <module>:ktlintCheck- Run ktlint check on a specific module./gradlew <module>:ktlintFormat- Run ktlint format on a specific module
For IntelliJ IDEA / Android Studio, you can install the ktlint plugin to get real-time linting and formatting.
The application follows Clean Architecture principles with a clear separation of concerns:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PRESENTATION LAYER β
β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ β
β β ViewModels β β Screen States β β Events β β
β ββββββββββ¬βββββββββ βββββββββββββββββββ βββββββββββββββββββ β
β β β
βββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DOMAIN LAYER β
β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ β
β β Use Cases β β Domain Models β β Repositories β β
β β Interface β β β β Interface β β
β ββββββββββ¬βββββββββ βββββββββββββββββββ ββββββββββ¬βββββββββ β
β β β β
βββββββββββββΌββββββββββββββββββββββββββββββββββββββββββΌββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DATA LAYER β
β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ β
β β Repository Impl β β Data Sources β β DTOs/APIs β β
β ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ β
β β β β β
βββββββββββββΌβββββββββββββββββββββΌβββββββββββββββββββββΌββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PLATFORM LAYER β
β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ β
β β Result β β KLogger β β KTime β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
apps/
βββ shared (KMP Shared Code - Compose UI)
β βββ core/presentation
β βββ core/di
β
βββ androidApp (Android Application)
β βββ apps/shared
β
βββ desktopApp (Desktop JVM Application)
β βββ apps/shared
β
βββ webApp (WasmJS Web Application)
βββ apps/shared
core/
βββ designSystem (UI Components & Theme)
β
βββ di (Dependency Injection)
β βββ core/logic/presentation
β βββ core/logic/data
β βββ platform/ktime
β
βββ logic/
βββ presentation (ViewModels, States)
β βββ core/logic/domain
β βββ core/logic/data
β βββ core/designSystem
β βββ platform/klogger
β
βββ domain (Use Cases, Models)
β βββ platform/result
β βββ platform/klogger
β
βββ data (Repositories, Data Sources)
βββ core/logic/domain
βββ platform/klogger
platform/
βββ klogger (Logging utilities)
β βββ platform/ktime
βββ ktime (Date and time utilities)
βββ result (Result monad for error handling)
βββ platform/ktime
The following diagram shows a more detailed view of module dependencies in the project:
+---------------------+ +---------------------+ +---------------------+
| APPS | | CORE | | LOGIC |
| MODULES | | MODULES | | MODULES |
+---------------------+ +---------------------+ +---------------------+
| :apps:shared | | :designSystem | | :presentation |
| (KMP Shared UI) | | (UI Components) | | (ViewModels, States)|
| | | | | |
| :apps:androidApp | | :di | | :domain |
| (Android App) | | (Dependency | | (Use Cases, Models) |
| | | Injection) | | |
| :apps:desktopApp | | | | :data |
| (Desktop JVM App) | | | | (Repositories, |
| | | | | Data Sources) |
| :apps:webApp | | | | |
| (WasmJS Web App) | | | | |
| | | | | |
| :basket-server | | | | |
| (Ktor Backend) | | | | |
+---------------------+ +---------------------+ +---------------------+
| | | | | | |
| | | | | | |
| +---------------------->+ | | | |
| | | | | |
| +---------------------->+ | | | |
| | | +--------------------->+ | |
| | | | | |
| | +------------------------->+ | |
| | | | |
+--+------------------------------------------------->+ | |
| v v v
| +---------------------+
| | PLATFORM |
| | MODULES |
| +---------------------+
| | :klogger |
| | (Logging utilities) |
| | |
| | :ktime |
+----------------------------------------->| (Date and time |
| utilities) |
| |
| :result |
| (Result monad for |
| error handling) |
+---------------------+
Dependencies:
- apps:androidApp -> apps:shared
- apps:desktopApp -> apps:shared
- apps:webApp -> apps:shared
- apps:shared -> presentation, di
- di -> presentation, data, ktime
- presentation -> domain, data, designSystem, klogger
- domain -> result, klogger
- data -> domain, klogger
- klogger -> ktime
- result -> ktime
This diagram illustrates:
- Apps Modules: Platform-specific entry points (Android, Desktop, Web) depending on shared KMP code
- Core Modules: Shared UI components and dependency injection
- Logic Modules: Business logic implementation following Clean Architecture
- Platform Modules: Utility modules used across the application
The arrows indicate dependencies between modules, showing how they rely on each other.
-
Apps Modules (
apps/):- shared: KMP module with shared Compose UI code for all platforms
- androidApp: Android application entry point
- desktopApp: Desktop JVM application entry point
- webApp: WasmJS web application entry point
-
Core Modules (
core/):- designSystem: UI components and styling
- di: Dependency injection setup with Koin
- logic: Business logic implementation
- data: Repositories and data sources (Ktor client)
- domain: Use cases and domain models
- presentation: ViewModels and UI state management
-
Platform Modules (
platform/):- klogger: Logging utilities
- ktime: Date and time utilities
- result: Result monad for error handling
-
Server Module (
server/):- basket-server: Ktor-based backend server implementation (documentation)
-
iOS App (
iosApp/):- Native iOS app using the shared framework from
apps:shared
- Native iOS app using the shared framework from
Below are screenshots of the Basket Scan and Go application running on different platforms.





