Skip to content

About

This is a collection of projects manage by a build-logic gradle scripting to share and reuse features and common modules across apps

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

KesiCollection

A full-stack expense splitting application built with Kotlin Multiplatform

πŸ“‹ Overview

KesiCollection is an expense management and bill-splitting application with support for Android, iOS, Desktop, and a backend server. The project uses Clean Architecture, modular design, and Kotlin Multiplatform to maximize code sharing across all platforms.

Key Features

  • πŸ’° Expense Splitting - Create groups, track payments, and automatically calculate who owes what
  • πŸ‘₯ Group Management - Create and manage expense groups with multiple members
  • πŸ“Š Settlement Tracking - View detailed payment history and outstanding balances
  • πŸ” Authentication - Secure JWT-based authentication system
  • πŸ‘« Friend Management - Connect with friends to simplify group creation
  • πŸ“± Multi-Platform - Runs on Android, iOS, and Desktop with shared business logic

πŸ—οΈ Architecture & Design

Clean Architecture

The application follows Clean Architecture principles with clear separation of concerns:

β”œβ”€β”€ domain/          # Business logic and use cases (platform-agnostic)
β”œβ”€β”€ data/           # Data sources, repositories, and API clients
β”œβ”€β”€ feature/        # Feature-specific UI and ViewModels
β”œβ”€β”€ core/           # Shared utilities and design system
└── server/         # Backend REST API

Modular Design

The codebase is organized into 55+ focused modules, each with a single responsibility. The architecture uses umbrella modules to enable multiple applications to share common infrastructure:

  • Core Modules: Shared across all applications (design system, infrastructure, models, Redux state management)
  • Feature Modules: Self-contained features that can be composed into different applications
  • Data Modules: API clients, local database, repositories
  • Domain Modules: Business logic and use cases
  • Application Modules: Umbrella modules that compose features and core modules into complete applications

Umbrella Module Architecture

The project is designed to support multiple applications sharing the same core infrastructure:

kesiSplit/              # Expense splitting application (Android/iOS/Desktop)
kesiSplitUmbrella/      # Umbrella module for KesiSplit
feature/                # Generic reusable features
featurekesisplit/       # Expense splitting specific features
core/                   # Shared across ALL applications
    β”œβ”€β”€ designsystem/   # UI components, theme, typography
    β”œβ”€β”€ infrastructure/ # Network, storage, utilities
    β”œβ”€β”€ model/          # Shared data models
    └── redux/          # State management framework

This umbrella approach allows:

  • βœ… Multiple apps with shared UI/UX - Different apps can use the same design system
  • βœ… Code reuse at scale - Core modules are shared across all applications
  • βœ… Independent feature development - Features can be developed and tested in isolation
  • βœ… Flexible composition - Applications cherry-pick which features to include
  • βœ… Consistent architecture - All apps follow the same patterns and structures

Technology Stack

Frontend (Mobile & Desktop)

  • Kotlin Multiplatform Mobile (KMM) - Share 80%+ code between Android, iOS, and Desktop
  • Compose Multiplatform - Modern declarative UI framework
  • Redux Pattern - Predictable unidirectional state management
  • Voyager - Type-safe navigation
  • Room Database - Local persistence with SQLite
  • Koin - Dependency injection
  • Coroutines & Flow - Asynchronous programming
  • Ktor Client - HTTP networking

Backend (Server)

  • Ktor - Asynchronous web framework
  • Exposed ORM - Type-safe SQL with Kotlin DSL
  • PostgreSQL - Production database
  • JWT Authentication - Secure token-based auth
  • Koin - Dependency injection

Build & DevOps

  • Gradle Convention Plugins - Standardized build configuration across 55+ modules
  • Kotlin DSL - Type-safe build scripts
  • Module Graph Plugin - Visualize module dependencies
  • Docker Compose - Local development environment

πŸ“± Platforms Supported

  • βœ… Android (API 24+)
  • βœ… iOS (iOS 14+)
  • βœ… Desktop (JVM - macOS, Windows, Linux)
  • βœ… Server (JVM)

πŸš€ Getting Started

Prerequisites

  • JDK 17 or higher
  • Android Studio Hedgehog (2023.1.1) or newer
  • Xcode 15+ (for iOS development)
  • Docker & Docker Compose (for backend)

Running the Android App

./gradlew :kesiSplit:assembleDebug
# Or open in Android Studio and run

Running the iOS App

# Build the Kotlin framework
./gradlew :kesiSplit:linkDebugFrameworkIosSimulatorArm64

# Open iosApp/iosApp.xcodeproj in Xcode and run

Running the Desktop App

./gradlew :kesiSplit:run

Running the Backend Server

With Docker Compose (Recommended)

docker-compose up db  # Start PostgreSQL database
./gradlew :server:run # Run the server

Manual Setup

  1. Start a PostgreSQL database
  2. Configure connection in server/src/main/resources/application.conf
  3. Run: ./gradlew :server:run

The server will start at http://localhost:8080

Running Tests

# Run all tests
./gradlew test

# Run specific module tests
./gradlew :featurekesisplit:home:testDebugUnitTest
./gradlew :server:test

πŸ›οΈ Project Structure

kesicollection/
β”‚
β”œβ”€β”€ build-logic/                    # Custom Gradle convention plugins
β”‚   └── convention/                 # Reusable build configuration
β”‚
β”œβ”€β”€ core/                           # Core shared modules
β”‚   β”œβ”€β”€ designsystem/              # UI components, theme, typography
β”‚   β”œβ”€β”€ infrastructure/            # Network, storage, utilities
β”‚   β”œβ”€β”€ model/                     # Shared data models
β”‚   └── redux/                     # State management framework
β”‚
β”œβ”€β”€ domain/                         # Business logic (platform-agnostic)
β”‚   β”œβ”€β”€ authentication/            # Auth use cases
β”‚   β”œβ”€β”€ datetime/                  # Date/time utilities
β”‚   └── misc/                      # Shared domain logic
β”‚
β”œβ”€β”€ data/                          # Data layer
β”‚   β”œβ”€β”€ api/                       # API models
β”‚   β”œβ”€β”€ authentication/            # Auth repository
β”‚   β”œβ”€β”€ exposed/                   # Database ORM
β”‚   β”œβ”€β”€ friendship/                # Friend management data
β”‚   β”œβ”€β”€ ktor/                      # HTTP client setup
β”‚   β”œβ”€β”€ repository/                # Data repositories
β”‚   β”œβ”€β”€ room/                      # Local database
β”‚   └── server/                    # Server data layer
β”‚
β”œβ”€β”€ feature/                       # Generic features
β”‚   β”œβ”€β”€ authentication/            # Login/register screens
β”‚   β”œβ”€β”€ friendlookup/              # Friend search
β”‚   β”œβ”€β”€ getstarted/                # Onboarding
β”‚   └── nomms/                     # Additional features
β”‚
β”œβ”€β”€ featurekesisplit/              # Expense splitting features
β”‚   β”œβ”€β”€ home/                      # Main dashboard
β”‚   β”œβ”€β”€ splits/                    # List of splits
β”‚   β”œβ”€β”€ split/                     # Split detail view
β”‚   β”œβ”€β”€ createsplit/               # Create new split
β”‚   β”œβ”€β”€ creategroup/               # Create expense group
β”‚   β”œβ”€β”€ addpayment/                # Add payment to split
β”‚   β”œβ”€β”€ submitpayment/             # Submit payment confirmation
β”‚   β”œβ”€β”€ paymentdetail/             # Payment details view
β”‚   β”œβ”€β”€ splitdetail/               # Split details view
β”‚   β”œβ”€β”€ splitbalance/              # Balance calculations
β”‚   β”œβ”€β”€ deletesettlement/          # Delete settlement
β”‚   β”œβ”€β”€ groupmembersselection/     # Select group members
β”‚   └── createanonymousmember/     # Add non-registered members
β”‚
β”œβ”€β”€ kesiSplit/                     # Main mobile application (umbrella for Android/iOS/Desktop)
β”œβ”€β”€ kesiSplitUmbrella/            # Umbrella module composing core + features
β”œβ”€β”€ iosApp/                        # iOS-specific code
β”œβ”€β”€ server/                        # Backend Ktor application
└── docker-server/                 # Docker configuration

🎯 Modularization Strategy

Gradle Convention Plugins

The build system uses custom convention plugins to standardize configuration across all 55+ modules:

  • KMPLibraryConventionPlugin - Base configuration for Kotlin Multiplatform libraries
  • KMPLibraryComposeConventionPlugin - Compose Multiplatform UI libraries
  • FeatureConventionPlugin - Feature module configuration with common dependencies
  • KMPApplicationConventionPlugin - Application module setup
  • KtorConventionPlugin - Server and client Ktor configuration

This approach eliminates duplication in build files and ensures consistency across the entire codebase.

Module Dependency Management

Each module explicitly declares its dependencies in build.gradle.kts, creating a directed acyclic graph (DAG) of dependencies. The module graph visualization below shows how core modules are depended upon by all features, while features remain independent of each other.

Key architectural constraints:

  • Core modules have no dependencies on feature or data modules
  • Domain modules are pure Kotlin with no platform dependencies
  • Feature modules depend only on core and domain modules
  • Data modules bridge domain and platform-specific implementations

πŸ“Š Module Dependency Graph

The following diagram shows the dependency relationships between core modules:

Module Graph

%%{
  init: {
    'theme': 'neutral'
  }
}%%

graph LR
  subgraph :common
    :common:component["component"]
  end
  subgraph :core
    :core:infrastructure["infrastructure"]
    :core:designsystem["designsystem"]
    :core:redux["redux"]
    :core:model["model"]
  end
  subgraph :data
    :data:api["api"]
    :data:server["server"]
  end
  subgraph :data:client
    :data:client:friendship["friendship"]
    :data:client:authentication["authentication"]
    :data:client:ktor["ktor"]
  end
  subgraph :datakesisplit
    :datakesisplit:transaction["transaction"]
    :datakesisplit:split["split"]
    :datakesisplit:splitgroup["splitgroup"]
    :datakesisplit:api["api"]
  end
  subgraph :domain
    :domain:authentication["authentication"]
    :domain:misc["misc"]
  end
  subgraph :feature
    :feature:authentication["authentication"]
    :feature:friendlookup["friendlookup"]
    :feature:getstarted["getstarted"]
    :feature:nomms["nomms"]
  end
  subgraph :featurekesisplit
    :featurekesisplit:deletesettlement["deletesettlement"]
    :featurekesisplit:groupmembersselection["groupmembersselection"]
    :featurekesisplit:addpayment["addpayment"]
    :featurekesisplit:creategroup["creategroup"]
    :featurekesisplit:paymentdetail["paymentdetail"]
    :featurekesisplit:split["split"]
    :featurekesisplit:splits["splits"]
    :featurekesisplit:createanonymousmember["createanonymousmember"]
    :featurekesisplit:createsplit["createsplit"]
    :featurekesisplit:home["home"]
    :featurekesisplit:splitbalance["splitbalance"]
    :featurekesisplit:splitdetail["splitdetail"]
    :featurekesisplit:submitpayment["submitpayment"]
  end
  :domain:authentication --> :core:infrastructure
  :featurekesisplit:deletesettlement --> :core:designsystem
  :featurekesisplit:deletesettlement --> :core:redux
  :featurekesisplit:groupmembersselection --> :core:designsystem
  :featurekesisplit:groupmembersselection --> :core:redux
  :common:component --> :core:model
  :common:component --> :core:designsystem
  :feature:authentication --> :core:designsystem
  :feature:authentication --> :core:redux
  :featurekesisplit:addpayment --> :core:designsystem
  :featurekesisplit:addpayment --> :core:redux
  :data:client:friendship --> :core:infrastructure
  :datakesisplit:transaction --> :core:infrastructure
  :featurekesisplit:creategroup --> :core:designsystem
  :featurekesisplit:creategroup --> :core:redux
  :featurekesisplit:paymentdetail --> :core:designsystem
  :featurekesisplit:paymentdetail --> :core:redux
  :kesiSplitUmbrella --> :core:designsystem
  :datakesisplit:split --> :core:infrastructure
  :featurekesisplit:split --> :core:designsystem
  :featurekesisplit:split --> :core:redux
  :datakesisplit:splitgroup --> :core:infrastructure
  :data:api --> :core:model
  :featurekesisplit:splits --> :core:designsystem
  :featurekesisplit:splits --> :core:redux
  :datakesisplit:api --> :core:model
  :feature:friendlookup --> :core:designsystem
  :feature:friendlookup --> :core:redux
  :data:client:authentication --> :core:infrastructure
  :featurekesisplit:createanonymousmember --> :core:designsystem
  :featurekesisplit:createanonymousmember --> :core:redux
  :feature:getstarted --> :core:designsystem
  :feature:getstarted --> :core:redux
  :featurekesisplit:createsplit --> :core:designsystem
  :featurekesisplit:createsplit --> :core:redux
  :featurekesisplit:home --> :core:designsystem
  :featurekesisplit:home --> :core:redux
  :data:server --> :core:infrastructure
  :core:infrastructure --> :domain:misc
  :feature:nomms --> :core:designsystem
  :feature:nomms --> :core:redux
  :featurekesisplit:splitbalance --> :core:designsystem
  :featurekesisplit:splitbalance --> :core:redux
  :featurekesisplit:splitdetail --> :core:designsystem
  :featurekesisplit:splitdetail --> :core:redux
  :featurekesisplit:submitpayment --> :core:designsystem
  :featurekesisplit:submitpayment --> :core:redux
  :data:client:ktor --> :core:model

classDef focus fill:#769566,stroke:#fff,stroke-width:2px,color:#fff;
class :core:infrastructure focus
class :core:designsystem focus
class :core:redux focus
class :core:model focus
Loading

πŸ”§ Development Tools

  • Module Graph Plugin - Visualizes module dependencies (see graph above)
  • Gradle Convention Plugins - Standardizes build configuration
  • Type-Safe Project Accessors - Compile-time safe module references
  • Gradle Build Cache - Speeds up incremental builds

🀝 Contributing

Suggestions and feedback are welcome! Feel free to:

  • Open issues for bugs or suggestions
  • Submit pull requests
  • Provide architectural feedback

πŸ“„ License

This project is open source and available for reference and learning purposes.


Built with ❀️ using Kotlin Multiplatform

About

This is a collection of projects manage by a build-logic gradle scripting to share and reuse features and common modules across apps

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages