README.en.md
May 28, 2026 · View on GitHub

A Compose Multiplatform open-source Github client App, sharing a single Kotlin / Compose code base across Android / Desktop JVM (macOS + Windows + Linux) / iOS / macOS Native — 5 targets in total. It aims to better manage and maintain personal Github projects daily, offering a richer feature set and a more consistent cross-platform experience~~Σ( ̄。 ̄ノ)ノ. The repo's rootProject is GSYGithubAppCompose, and various counterparts are provided for comparison:
-
Android Compose Version ( https://github.com/CarGuo/GSYGithubAppCompose )
-
Flutter Version ( https://github.com/CarGuo/GSYGithubAppFlutter )
-
Kotlin View Version ( https://github.com/CarGuo/GSYGithubAppKotlin )
-
ReactNative Version ( https://github.com/CarGuo/GSYGithubApp )
-
Weex Version ( https://github.com/CarGuo/GSYGithubAppWeex )
-
If cloning is too slow or images are not displaying, try downloading from Gitee
| Official Account | Juejin | Zhihu | CSDN | Jianshu |
|---|---|---|---|---|
| GSYTech | Click Me | Click Me | Click Me | Click Me |
A cross-platform App built on Compose Multiplatform 1.10.3 + Kotlin 2.3.20.
A single repository ships Android / Desktop JVM (macOS + Windows + Linux) / iOS / macOS Native at the same time.
The project's goal is to facilitate daily maintenance and browsing of Github,
and it is also a great playground for learning Compose Multiplatform — covering KMP targets,
expect/actual, multiplatform navigation, multiplatform ViewModel/Lifecycle, Ktor networking,
Koin DI, Coil image loading, Apollo GraphQL and more.
Based on usage and feedback, the user experience and features will be updated and improved
from time to time. Feel free to raise issues.
![]() | ![]() | ![]() | ![]() |
The 5 Targets at a Glance (Compose Multiplatform Targets)
| Platform | KMP Target | Entry Module | Key Identifiers |
|---|---|---|---|
| Android | androidTarget | androidApp | applicationId com.shuyu.gsygithubappcompose, minSdk 24, compileSdk 36 |
| Desktop JVM (macOS + Windows + Linux) | jvm | desktopApp | mainClass com.shuyu.gsygithubappcompose.desktop.MainKt, targetFormats Exe / Msi / Dmg / Deb |
| iOS (Device) | iosArm64 | iosApp | XcodeGen + bundle id com.shuyu.gsygithubappcompose, deploymentTarget iOS 15.0 |
| iOS (Simulator) | iosSimulatorArm64 | iosApp | Same as above, runs on Apple Silicon Simulator |
| macOS Native | macosArm64 | composeShared framework + native host | Apple Silicon native framework |
Shared cross-platform code lives in the commonMain of composeShared, core, data and feature; each platform entry module only acts as a minimal host.
How to Compile and Run
Environment Requirements:
- AGP 9.0.0 — Android Studio Otter (2025.1.1) Feature Drop or higher is required to build Android successfully.
- Compose Multiplatform 1.10.3 + Kotlin 2.3.20 — using a matching IntelliJ IDEA / Android Studio toolchain is recommended.
- iOS / macOS Native targets require a macOS host with Xcode 15+,
xcodegenandxcodebuildinstalled. - Desktop JVM packaging (Dmg / Msi / Deb) is provided by Compose Desktop and must run on the corresponding host OS.
Important: You need to configure the local.properties file in the project root (see local.properties.sample) and enter your registered Github client_id and client_secret.
ndk.dir="xxxxxxxx"
CLIENT_ID = "xxxxxx"
CLIENT_SECRET = "xxxxxx"
Portal to register a Github APP , of course, the prerequisite is that you have a Github account (~ ̄▽ ̄)~.
The Github API requires secure (authorized) login, so you must fill in the Authorization callback URL field as follows when registering your Github App:
gsygithubapp://authed
Build Commands for All 5 Targets
# 1) Android (debug apk, installed on [androidApp](file:///Users/guoshuyu/workspace/android/GSYGithubAppCMP/androidApp))
./gradlew :androidApp:assembleDebug
# 2) Desktop JVM run (dev mode: any of macOS / Windows / Linux)
./gradlew :desktopApp:run
# 3) Desktop JVM platform-native installers
./gradlew :desktopApp:packageDmg # macOS → .dmg
./gradlew :desktopApp:packageMsi # Windows → .msi
./gradlew :desktopApp:packageDeb # Linux → .deb
# 4) iOS: generate the Xcode project with XcodeGen, then build with xcodebuild (inside [iosApp](file:///Users/guoshuyu/workspace/android/GSYGithubAppCMP/iosApp))
cd iosApp && xcodegen generate
xcodebuild -project iosApp.xcodeproj -scheme iosApp -configuration Debug \
-destination 'generic/platform=iOS Simulator' build
# 5) Compose Multiplatform Framework artifacts (linked by iOS / macOS hosts)
./gradlew :composeShared:linkDebugFrameworkIosSimulatorArm64
./gradlew :composeShared:linkDebugFrameworkMacosArm64
For a step-by-step developer onboarding flow across all 5 targets, see QUICK_START.md.
Project Structure Diagrams
KeyFeatures

Core Technologies

Layer Structure

Technology Stack

Navigation Flow

Data Flow Architecture

Overall Architecture Diagram
┌─────────────────────────────────────────────────────────────────────────┐
│ GSYGithubAppCompose │
│ (Compose Multiplatform + KMP + MVVM + Koin) │
└─────────────────────────────────────────────────────────────────────────┘
│
┌──────────────┬────────────┼────────────┬──────────────┐
│ │ │ │ │
┌────▼───┐ ┌─────▼────┐ ┌────▼───┐ ┌────▼───┐ ┌─────▼─────┐
│androidApp│ │desktopApp│ │ iosApp │ │macosApp│ │ Web (TBD) │
│(android │ │ (jvm) │ │(iosArm/│ │(macos │ │ (planned) │
│ Target) │ │ │ │ iosSim)│ │ Arm64) │ │ │
└────┬─────┘ └────┬─────┘ └────┬───┘ └────┬───┘ └────────────┘
│ │ │ │
└─────────────┴──────┬──────┴───────────┘
│
┌────────────▼────────────┐
│ composeShared │
│ (cross-platform UI hub) │
└────────────┬────────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
┌──────▼──────┐ ┌────────▼────────┐ ┌─────▼──────┐
│ feature/* │ │ data │ │ core/* │
│ (13 modules)│ │ Repository │ │ network/db │
└─────────────┘ └─────────────────┘ │ common/ui │
└────────────┘
Module Dependency Diagram
┌────────────┐ ┌────────────┐ ┌────────┐ ┌─────────┐
│ androidApp │ │ desktopApp │ │ iosApp │ │macosHost│
└─────┬──────┘ └─────┬──────┘ └────┬───┘ └────┬────┘
│ │ │ │
└──────┬───────┴─────────────┴──────────┘
│
┌─────▼─────┐
│composeShared│
└─────┬─────┘
│
┌────────────────────┼────────────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ feature/* │ │ data │ │ core/ui │
│ │ │ │ │ │
│ All Feature │◄─────┤ Repository │ │ Common UI │
│ Modules │ │ │ │ Components │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ ┌───────┼────────┐ │
│ │ │ │ │
└────────────┼───────┼────────┼──────────────┘
│ │ │
┌───────────▼─┐ ┌──▼────────▼──┐ ┌──────────────┐
│core/network │ │core/database │ │ core/common │
│ │ │ │ │ │
│ Ktor 3.1.0 │ │ Room KMP │ │ DataStore │
│ Apollo │ │ Entity/DAO │ │ Token │
│ Models │ │ │ │ Resources │
└─────────────┘ └──────────────┘ └──────────────┘
Dependency Rules:
androidApp / desktopApp / iosApp / macosHost → composeShared
composeShared → feature/*, core/ui, data
feature/* → data, core/ui, core/common
data → core/network, core/database, core/common
core/ui → core/common
core/network → (Independent Module)
core/database→ (Independent Module)
core/common → (Independent Module)
Detailed Module Structure
GSYGithubAppCompose/
│
├── androidApp/ # Android entry host (applicationId com.shuyu.gsygithubappcompose)
│ ├── MainActivity.kt # Main entry, mounts composeShared
│ ├── GSYApplication.kt # Application, Koin startup
│ └── di/AppModule.kt # Android-specific module
│
├── desktopApp/ # Desktop JVM entry (mainClass com.shuyu.gsygithubappcompose.desktop.MainKt)
│ ├── Main.kt # singleWindowApplication entry
│ ├── language/JvmLanguageDataStore.kt # JVM DataStore adapter
│ ├── session/DesktopUserSession.kt # Desktop session
│ └── diagnostics/StartRouteDiagnostics.kt# Startup route diagnostics
│
├── iosApp/ # iOS entry host (XcodeGen + Swift shell)
│ ├── project.yml # XcodeGen project description
│ ├── iosApp/iOSApp.swift # SwiftUI App entry
│ ├── iosApp/ContentView.swift # Hosts composeShared MainViewController
│ └── iosApp/Assets.xcassets/ # AppIcon / launch_image (shared with Android)
│
├── composeShared/ # Cross-platform UI hub + iOS glue
│ └── src/iosMain/kotlin/.../MainViewController.kt
│
├── core/ # Core base modules (commonMain-first)
│ │
│ ├── network/ # Network layer (Ktor 3.1.0 + Apollo GraphQL)
│ │ ├── api/GitHubApiService.kt # GitHub REST API interface (commonMain)
│ │ ├── graphql/ # Apollo schema + queries
│ │ └── di/NetworkModule.kt # Koin 4.2.1 module
│ │
│ ├── database/ # Database layer (Room KMP)
│ │ ├── entity/ # Entities (commonMain)
│ │ ├── dao/ # DAOs
│ │ └── AppDatabase.kt
│ │
│ ├── common/ # Common resources / DataStore / i18n
│ │ ├── composeResources/ # Compose Multiplatform resources (drawable / files / values)
│ │ │ ├── drawable/ic_launcher.png # Single source of truth for AppIcon (5 targets)
│ │ │ ├── drawable/launch_image.png # Single source of truth for LaunchScreen (5 targets)
│ │ │ └── files/launcher_lottie.json
│ │ └── androidMain/res/ # Android mipmap resources (mirrored from commonMain)
│ │
│ └── ui/ # UI components / theme / navigation
│ ├── components/ # GSYPullRefresh / GSYTopAppBar etc.
│ ├── theme/ # Material 3
│ └── navigation/ # Built on jetbrains-navigation-compose 2.9.1
│
├── data/ # Data layer (Repository + expect/actual Dispatcher)
│ ├── commonMain/.../repository/ # Cross-platform Repository implementations
│ ├── androidMain/.../Dispatchers.android.kt
│ ├── jvmMain/.../Dispatchers.jvm.kt
│ ├── iosMain/.../Dispatchers.ios.kt
│ └── macosMain/.../Dispatchers.macos.kt
│
└── feature/ # 13 feature modules (all commonMain)
├── welcome/ # Welcome screen
├── login/ # OAuth login
├── home/ # Home (bottom navigation)
├── dynamic/ # Dynamic (event stream)
├── trending/ # Trending
├── profile/ # Profile
├── search/ # Search
├── detail/ # Repository detail
├── code/ # Code browsing
├── issue/ # Issue management
├── push/ # Push management
├── list/ # List
├── notification/ # Notifications
├── info/ # Info
└── history/ # Browsing history
Per-module build scripts: androidApp/build.gradle.kts, desktopApp/build.gradle.kts, composeShared/build.gradle.kts, iosApp/project.yml; the version catalog is at gradle/libs.versions.toml.
Technology Architecture Diagram
┌─────────────────────────────────────────────────────────────────────┐
│ Tech Stack │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Cross-platform Compose Multiplatform 1.10.3 │
│ Kotlin 2.3.20 + AGP 9.0.0 │
│ KMP targets: androidTarget / jvm / │
│ iosArm64 / iosSimulatorArm64 / macosArm64 │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │
│ UI Layer Compose Multiplatform + Material 3 │
│ jetbrains-navigation-compose 2.9.1 │
│ jetbrains-lifecycle 2.10.0 │
│ Coil 2.7.0 (Image Loading) │
│ Lottie (Complex Animations) │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │
│ State Management StateFlow + ViewModel (KMP) │
│ Kotlin Coroutines + Flow │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │
│ Dependency Injection Koin 4.2.1 (unified across 5 targets) │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │
│ Network Layer Ktor 3.1.0 (commonMain) │
│ Apollo GraphQL │
│ Kotlinx Serialization │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │
│ Database Layer Room KMP │
│ DataStore (replaces SharedPreferences) │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │
│ Architecture MVVM + Repository Pattern │
│ Clean Architecture │
│ Unidirectional Data Flow │
│ expect / actual platform dispatch │
│ │
└─────────────────────────────────────────────────────────────────────┘
Data Flow Diagram
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ │ │ │ │
│ Screen │◄───────┤ ViewModel │◄───────┤ Repository │
│ (Compose MP)│ State │ (KMP) │ Flow │ (commonMain) │
│ │ │ │ │ │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
│ User Action │ Business Logic │ Data Source
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ │ │ │ │
│ onClick │───────►│ loadData() │───────►│ Ktor 3.1.0 / │
│ onRefresh │ Event │ refresh() │ Call │ Room KMP │
│ │ │ │ │ │
└──────────────┘ └──────────────┘ └──────────────┘
Data Flow:
1. User actions trigger UI events (one Composable across 5 targets).
2. ViewModel handles business logic (KMP commonMain).
3. Repository coordinates data sources (Ktor network / Room KMP).
4. Data is returned to the ViewModel via Flow.
5. ViewModel updates UiState.
6. The UI auto-recomposes (consistent on Android / Desktop / iOS / macOS).
Layer Responsibilities
| Layer | Module | Responsibility | Key Technologies |
|---|---|---|---|
| Presentation | feature/ | UI rendering, user interaction | Compose Multiplatform, jetbrains-navigation-compose 2.9.1 |
| Business | data (ViewModel) | Business logic, state management | StateFlow, Coroutines, jetbrains-lifecycle 2.10.0 |
| Data | data (Repository) | Data access, caching strategy | Repository Pattern, expect/actual |
| Network | core/network | API calls, network requests | Ktor 3.1.0, Apollo GraphQL |
| Storage | core/database | Local caching, data persistence | Room KMP, DataStore |
| Foundation | core/common / core/ui | Common utilities, UI components | composeResources, Koin 4.2.1, Coil 2.7.0 |
Manual Test Playbooks
Copy-runnable manual regression playbooks across Android / iOS / macOS-Desktop / Windows-Desktop / Linux-Desktop:
| Platform | Entry | Toolchain |
|---|---|---|
| Android (uiautomator) | testing/uiautomator/playbook.md | adb + input swipe x y x y 80 + screencap |
| iOS Simulator | testing/ios/playbook.md | xcrun simctl + idb ui tap + pasteboard |
| macOS Desktop (DMG) | testing/macos-desktop/playbook.md | cliclick + osascript + screencapture |
E2E dual-track scripts (13 routes, all PASS):
- iOS: testing/ios/scripts/e2e_all_routes.sh
- macOS Desktop: testing/macos-desktop/scripts/e2e_all_routes.sh
- Android: testing/uiautomator/
13 routes covered: welcome / login / home / dynamic / profile / trending / search / repodetail / code / issue / push / notification / history / info — dual-track screenshots + logs all PASS, with artifacts under tools/screenshots/ios, tools/screenshots/macos, tools/logs/ios, tools/logs/macos.
The iOS AppIcon and LaunchScreen now share a single source of truth with Android (both come from ic_launcher / launch_image in core/common); see iosApp/iosApp/Assets.xcassets/AppIcon.appiconset and iosApp/iosApp/Assets.xcassets/launch_image.imageset.
Start here: cross-platform diff cheatsheet → testing/PLATFORM_DIFF.md
Each P-XX play (P-00 Cold Boot / P-01 Login / P-02 Dynamic / P-03 RepoDetail / P-04 PushDetail / P-05 Trending / P-06 Profile / P-08 Notification) shares identical structure and verification points across the three playbooks; only the underlying tool commands differ. Each platform's device / window metadata lives in its own device.md, and per-screen element coordinates in its own screen_map.md.
⚠️ "This document matters more than the README" — after a UI change, the first thing to update is screen_map, then run regression.
Download
APK Download Link: APK Download Link
Desktop Dmg / Msi / Deb and iOS ipa are published alongside Releases on a rolling basis; if a particular release is missing, please build locally with the 5-target commands above.
Sample Images (Screenshots may not be fully up-to-date)
Thanks
https://deepwiki.com/CarGuo/GSYGithubAppCompose
LICENSE
CarGuo/GSYGithubAppFlutter is licensed under the
Apache License 2.0
A permissive license whose main conditions require preservation of copyright and license notices.
Contributors provide an express grant of patent rights.
Licensed works, modifications, and larger works may be distributed under different terms and without source code.



