Skip to content

A Kotlin Multiplatform demo application showcasing modern mobile development with shared business logic and part of the UI between iOS and Android. Search GitHub repositories, view details, and save your favorites.

Notifications You must be signed in to change notification settings

goncharik/ReposBrowser-kmp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

ReposBrowser πŸš€

A Kotlin Multiplatform demo application showcasing modern mobile development with shared business logic and part of the UI between iOS and Android. Search GitHub repositories, view details, and save your favorites.

Kotlin Compose Multiplatform Apollo Kotlin SQLDelight Koin Coil

✨ Features

  • πŸ” Search GitHub Repositories - Real-time search using GitHub's GraphQL API
  • πŸ“Š Repository Details - View comprehensive information about any repository
  • ⭐ Favorites - Save and manage your favorite repositories locally
  • 🎨 Native Navigation - SwiftUI TabView on iOS, Compose Navigation on Android
  • πŸ”„ Shared Business Logic - Common code for networking, data storage, and ViewModels
  • πŸ“¦ Modern Architecture - Clean Architecture with Repository pattern and DI

🎯 Purpose

This project demonstrates:

  • Apollo Kotlin v4 integration in a KMP project
  • Koin dependency injection across platforms
  • SQLDelight for local data persistence
  • Compose Multiplatform UI shared between platforms
  • Native navigation integration (SwiftUI for iOS, Compose for Android)
  • Production-quality architecture in a demo context

Perfect for:

  • Learning KMP development
  • Understanding Apollo GraphQL in mobile apps
  • Reference architecture for new KMP projects
  • Portfolio/interview showcase

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Presentation                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚   Android (Compose)  β”‚      β”‚    iOS (SwiftUI)     β”‚     β”‚
β”‚  β”‚  - Compose Navigationβ”‚      β”‚  - TabView           β”‚     β”‚
β”‚  β”‚  - Material3         β”‚      β”‚  - NavigationStack   β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Shared Module (KMP)                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  UI Layer (Compose Multiplatform)                   β”‚    β”‚
β”‚  β”‚  - SearchScreen.kt                                  β”‚    β”‚
β”‚  β”‚  - RepoDetailsScreen.kt                             β”‚    β”‚
β”‚  β”‚  - FavoritesScreen.kt                               β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                              β”‚                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  ViewModel Layer                                    β”‚    β”‚
β”‚  β”‚  - SearchViewModel (StateFlow)                      β”‚    β”‚
β”‚  β”‚  - RepoDetailsViewModel                             β”‚    β”‚
β”‚  β”‚  - FavoritesViewModel                               β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                              β”‚                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Domain Layer                                       β”‚    β”‚
β”‚  β”‚  - Repository, RepositoryDetails (models)           β”‚    β”‚
β”‚  β”‚  - GitHubRepository (interface)                     β”‚    β”‚
β”‚  β”‚  - FavoritesRepository (interface)                  β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                              β”‚                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Data Layer (API)  β”‚   Data Layer (Local)            β”‚   β”‚
β”‚  β”‚  - Apollo Client   β”‚   - SQLDelight                  β”‚   β”‚
β”‚  β”‚  - GraphQL Queries β”‚   - Database Driver             β”‚   β”‚
β”‚  β”‚  - GitHubApiClient β”‚   - FavoritesDatabase           β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                              β”‚                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Dependency Injection (Koin)                        β”‚    β”‚
β”‚  β”‚  - networkModule, databaseModule, viewModelModule   β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tech Stack

Layer Technology
UI Compose Multiplatform
Navigation Compose Navigation (Android), SwiftUI Navigation (iOS)
State Management ViewModel, StateFlow, Coroutines
Networking Apollo Kotlin 4 (GraphQL)
Local Storage SQLDelight
Dependency Injection Koin
Build System Gradle with Kotlin DSL

πŸ“ Project Structure

apollo-kmp-github/
β”œβ”€β”€ composeApp/                 # Shared KMP module
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ commonMain/
β”‚   β”‚   β”‚   β”œβ”€β”€ kotlin/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Secrets.kt           # Gitignored secrets
β”‚   β”‚   β”‚   β”‚   β”‚   └── Secrets.example.kt   # Template
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ data/
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApolloClientFactory.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── GitHubApiClient.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ local/
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ DatabaseDriverFactory.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── FavoritesDatabase.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ model/
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Repository.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── RepositoryDetails.kt
β”‚   β”‚   β”‚   β”‚   β”‚   └── repository/
β”‚   β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ GitHubRepository.kt
β”‚   β”‚   β”‚   β”‚   β”‚       └── FavoritesRepository.kt
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ di/
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ KoinInit.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ NetworkModule.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ DatabaseModule.kt
β”‚   β”‚   β”‚   β”‚   β”‚   └── ViewModelModule.kt
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ui/
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ screens/
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ SearchScreen.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ RepoDetailsScreen.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── FavoritesScreen.kt
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── RepositoryCard.kt
β”‚   β”‚   β”‚   β”‚   β”‚   └── theme/
β”‚   β”‚   β”‚   β”‚   β”‚       └── Theme.kt
β”‚   β”‚   β”‚   β”‚   └── viewmodel/
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ SearchViewModel.kt
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ RepoDetailsViewModel.kt
β”‚   β”‚   β”‚   β”‚       └── FavoritesViewModel.kt
β”‚   β”‚   β”‚   └── graphql/
β”‚   β”‚   β”‚       β”œβ”€β”€ schema.graphqls          # GitHub GraphQL schema
β”‚   β”‚   β”‚       β”œβ”€β”€ SearchRepositories.graphql
β”‚   β”‚   β”‚       └── GetRepositoryDetails.graphql
β”‚   β”‚   β”œβ”€β”€ androidMain/
β”‚   β”‚   β”‚   └── kotlin/
β”‚   β”‚   β”‚       └── data/local/
β”‚   β”‚   β”‚           └── DatabaseDriverFactory.android.kt
β”‚   β”‚   └── iosMain/
β”‚   β”‚       └── kotlin/
β”‚   β”‚           └── data/local/
β”‚   β”‚               └── DatabaseDriverFactory.ios.kt
β”‚   └── build.gradle.kts
β”‚
β”œβ”€β”€ androidApp/                 # Android-specific code
β”‚   β”œβ”€β”€ src/main/
β”‚   β”‚   β”œβ”€β”€ kotlin/
β”‚   β”‚   β”‚   β”œβ”€β”€ MainActivity.kt
β”‚   β”‚   β”‚   └── Navigation.kt
β”‚   β”‚   └── AndroidManifest.xml
β”‚   └── build.gradle.kts
β”‚
β”œβ”€β”€ iosApp/                     # iOS-specific code
β”‚   β”œβ”€β”€ iosApp/
β”‚   β”‚   β”œβ”€β”€ ContentView.swift           # SwiftUI TabView
β”‚   β”‚   β”œβ”€β”€ ComposeViews.swift          # UIViewControllerRepresentable
β”‚   β”‚   └── iosAppApp.swift
β”‚   └── iosApp.xcodeproj
β”‚
β”œβ”€β”€ gradle/
β”‚   └── libs.versions.toml      # Version catalog
β”œβ”€β”€ .gitignore
β”œβ”€β”€ build.gradle.kts
β”œβ”€β”€ settings.gradle.kts
└── README.md

πŸš€ Getting Started

Prerequisites

  • Android Studio (latest stable version)
  • Xcode 16+ (for iOS development)
  • GitHub Personal Access Token

Setup Instructions

1. Clone the repository

   git clone https://github.com/goncharik/reposbrowser-kmp.git
   cd reposbrowser-kmp

2. Configure GitHub Token

This app uses the GitHub GraphQL API and requires a personal access token.

Get a token:

  • Go to GitHub Settings > Tokens
  • Click "Generate new token" β†’ "Generate new token (classic)"
  • Give it a name: ReposBrowser
  • Select scope: public_repo (read access to public repositories)
  • Click "Generate token" and copy it

Add token to project:

   # Navigate to the config directory
   cd composeApp/src/commonMain/kotlin/com/honcharenko/reposbrowser/config/
   
   # Copy the example file
   cp Secrets.example.kt Secrets.kt
   
   # Edit Secrets.kt and replace YOUR_GITHUB_TOKEN_HERE with your token

Your Secrets.kt should look like:

   object Secrets {
       const val GITHUB_TOKEN = "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
   }

3. Build the Project

./gradlew build

4. Run on Android

Option A: Android Studio

  1. Open the project in Android Studio
  2. Select androidApp configuration
  3. Choose an emulator or connected device
  4. Click Run ▢️

Option B: Command Line

./gradlew :androidApp:installDebug

5. Run on iOS

Requirements: macOS with Xcode installed

Option A: Xcode

  1. Open iosApp/iosApp.xcodeproj in Xcode
  2. Select a simulator or device
  3. Click Run ▢️

Option B: Command Line

# Build the KMP framework first
./gradlew :composeApp:embedAndSignAppleFrameworkForXcode

# Open in Xcode
open iosApp/iosApp.xcodeproj

πŸ“š Learning Resources

Kotlin Multiplatform

Apollo Kotlin

Compose Multiplatform

SQLDelight

Koin

πŸ“§ Contact

Eugene Honcharenko - @honcharenko_eu

Project Link: https://github.com/goncharik/reposbrowser-kmp


Built with ❀️ using Kotlin Multiplatform

About

A Kotlin Multiplatform demo application showcasing modern mobile development with shared business logic and part of the UI between iOS and Android. Search GitHub repositories, view details, and save your favorites.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published