Skip to content

Sendiko/MyChevaMobile

Repository files navigation

MyChevaMobile

A Kotlin Multiplatform (KMP) mobile application targeting Android and iOS, built with Compose Multiplatform for shared UI, Ktor for networking, and Koin for dependency injection. The shared business logic and UI live in the composeApp module; platform-specific entry points exist for Android and iOS.

Overview

  • Targets: Android and iOS
  • UI: JetBrains Compose Multiplatform (Material 3)
  • DI: Koin
  • Networking: Ktor client (OkHttp on Android, Darwin on iOS)
  • Persistence: AndroidX DataStore
  • Images: Coil 3 (Ktor network)
  • Camera/Scanning:
    • Android: CameraX + ML Kit Barcode Scanning
    • iOS: CameraK + QR scanner plugin

Common feature packages in the shared module include: auth, dashboard, meeting, profile, roadmap, attendance, and splashscreen (see composeApp/src/commonMain/kotlin/org/chevalierlab/my).

Tech Stack and Tooling

  • Language: Kotlin 2.2.20 (multiplatform)
  • UI Framework: Compose Multiplatform 1.8.2
  • Build system & package manager: Gradle 8.14.3 (Kotlin DSL, Version Catalog)
  • Android Gradle Plugin: 8.11.0
  • Android SDK: compileSdk 36, targetSdk 36, minSdk 24
  • iOS: iosArm64 and iosSimulatorArm64 targets

Requirements

  • JDK 11 (the project targets JVM 11)
  • Gradle wrapper (included) — no need to install Gradle separately
  • Android Studio or IntelliJ IDEA with Kotlin Multiplatform and Android support
  • Android SDK and device/emulator (API 24+)
  • macOS with Xcode for building/running the iOS app
    • Swift toolchain + CocoaPods not required (framework is generated directly)

Project Structure

  • composeApp — shared KMP module
    • src/commonMain — shared Kotlin and Compose UI
    • src/androidMain — Android-specific code (Manifest, MainActivity, resources)
    • src/iosMain — iOS-specific code (Compose UIViewController wrapper)
  • iosApp — SwiftUI container app for iOS
  • gradle — Gradle version catalog and wrapper config
  • build.gradle.kts, settings.gradle.kts — root Gradle config

Relevant entry points:

  • Android
    • Application: composeApp/src/androidMain/kotlin/org/chevalierlab/my/MyChevaMobileApp.kt
    • Activity: composeApp/src/androidMain/kotlin/org/chevalierlab/my/MainActivity.kt
    • Manifest: composeApp/src/androidMain/AndroidManifest.xml
  • iOS
    • SwiftUI app: iosApp/iosApp/iOSApp.swift
    • SwiftUI root view: iosApp/iosApp/ContentView.swift (bridges to KMP via MainViewController)
    • KMP bridge: composeApp/src/iosMain/kotlin/org/chevalierlab/my/MainViewController.kt
  • Shared UI root: composeApp/src/commonMain/kotlin/org/chevalierlab/my/core/App.kt

Architecture: Clean Architecture (per feature)

This project follows a pragmatic Clean Architecture approach organized per feature inside the shared KMP module. Each feature separates concerns into Presentation, Domain, and Data layers, with dependencies flowing inward only.

  • Presentation layer (Compose + ViewModels)

    • What: UI composables and UI state holders (e.g., ViewModels) that interact with domain abstractions.
    • Where: composeApp/src/commonMain/kotlin/org/chevalierlab/my/{feature}/presentation
    • Depends on: Domain (interfaces and models), DI wiring.
  • Domain layer (business entities and contracts)

    • What: Platform-agnostic business models and repository interfaces.
    • Where: composeApp/src/commonMain/kotlin/org/chevalierlab/my/{feature}/domain
    • Depends on: Nothing framework-specific; pure Kotlin.
    • Note: If/when use cases (interactors) are introduced, place them here. Currently, the codebase shows domain models (for example, RoadMap.kt) and repository interfaces per feature.
  • Data layer (implementations and external services)

    • What: Repository implementations, DTOs, mappers, and data sources (network via Ktor, local via DataStore, etc.). Maps DTOs to domain models.
    • Where: composeApp/src/commonMain/kotlin/org/chevalierlab/my/{feature}/data
    • Depends on: Ktor, DataStore, and other libraries; implements Domain interfaces.

Dependency direction

  • Presentation -> Domain (interfaces, models)
  • Domain <- Data (Data implements Domain interfaces)
  • Presentation should not depend on Data directly.

Example: Roadmap feature

  • Data DTOs: composeApp/src/commonMain/kotlin/org/chevalierlab/my/roadmap/data/dto
  • Data repository impl: composeApp/src/commonMain/kotlin/org/chevalierlab/my/roadmap/data/repository/RoadMapRepositoryImpl.kt
  • Domain model: composeApp/src/commonMain/kotlin/org/chevalierlab/my/roadmap/domain/models/RoadMap.kt
  • Presentation UI: composeApp/src/commonMain/kotlin/org/chevalierlab/my/roadmap/presentation

Dependency Injection (Koin)

  • Koin modules wire interfaces to implementations and provide ViewModels. See composeApp/src/commonMain/kotlin/org/chevalierlab/my/core/di.

Why Clean Architecture here?

  • Testability: Domain is pure Kotlin and easy to test.
  • Separation of concerns: UI, business rules, and IO are clearly separated.
  • Replaceability: Data sources (e.g., network or local) can change with minimal impact on Presentation.

Adding a new feature (quick guide)

  1. Create feature package at composeApp/src/commonMain/kotlin/org/chevalierlab/my/.
  2. Inside it, add domain/, data/, and presentation/ subpackages.
  3. Define Domain models and repository interfaces.
  4. Implement Data layer (DTOs, repository impls, mappers) and map to Domain models.
  5. Build Presentation (composables, ViewModel) that depends on Domain interfaces only.
  6. Register bindings in Koin modules.

Setup

  1. Clone the repository
  2. Open the project in Android Studio or IntelliJ IDEA (KMP support recommended)
  3. Let the IDE sync Gradle and download dependencies
  4. Android: ensure an emulator or device is available (API 24+)
  5. iOS: open iosApp/iosApp.xcodeproj (or the iosApp workspace) in Xcode on macOS

Build & Run

  • Android (from IDE): Run the "composeApp" Android run configuration or MainActivity.

  • Android (terminal):

    • macOS/Linux: ./gradlew :composeApp:assembleDebug
    • Windows: .\gradlew.bat :composeApp:assembleDebug
    • Optional install to connected device: ./gradlew :composeApp:installDebug
  • iOS (from Xcode): Open iosApp in Xcode and run the iOS scheme to the simulator or device. The UI is provided by the shared KMP module via MainViewController.

Notes:

  • The Android app requests Camera and Internet permissions (see AndroidManifest.xml) for scanning functionality.

Scripts and Common Gradle Tasks

  • Build Android debug: ./gradlew :composeApp:assembleDebug
  • Build Android release: ./gradlew :composeApp:assembleRelease
  • Install Android debug: ./gradlew :composeApp:installDebug
  • Run tests: ./gradlew :composeApp:allTests or ./gradlew :composeApp:check
  • Clean: ./gradlew clean

Environment Variables and Configuration

No required environment variables are defined in the repository at this time.

  • TODO: If the app integrates with remote APIs, document configurable endpoints (e.g., base URL) and how to set them per build type or via environment/Gradle properties.

Tests

  • Location: composeApp/src/commonTest/kotlin
  • Example test: ComposeAppCommonTest
  • Run from IDE: Use the Gradle tool window (Tasks > verification > check) or run tests within the source set
  • Run from terminal: ./gradlew :composeApp:allTests

Useful Paths

  • Shared theme: composeApp/src/commonMain/kotlin/org/chevalierlab/my/core/ui/theme
  • DI setup: composeApp/src/commonMain/kotlin/org/chevalierlab/my/core/di
  • Features: composeApp/src/commonMain/kotlin/org/chevalierlab/my/

License

No license file is present in the repository.

  • TODO: Add a LICENSE file (e.g., MIT/Apache-2.0) and update this section accordingly.

Acknowledgements

  • Kotlin Multiplatform and Compose Multiplatform by JetBrains
  • Libraries: Ktor, Koin, DataStore, Coil, CameraX, ML Kit, CameraK

About

Migration to Multiplatform

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors