{"id":24801567,"url":"https://github.com/futuredapp/kmp-futured-template","last_synced_at":"2025-10-13T03:30:27.970Z","repository":{"id":211112984,"uuid":"697863131","full_name":"futuredapp/kmp-futured-template","owner":"futuredapp","description":"Template for creating Kotlin Multiplatform applications at Futured.","archived":false,"fork":false,"pushed_at":"2025-01-23T15:26:07.000Z","size":935,"stargazers_count":28,"open_issues_count":5,"forks_count":2,"subscribers_count":6,"default_branch":"develop","last_synced_at":"2025-01-27T20:46:52.364Z","etag":null,"topics":["android","ios","kotlin","kotlin-multiplatform","kotlin-multiplatform-sample"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/futuredapp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-28T16:15:20.000Z","updated_at":"2025-01-24T18:02:50.000Z","dependencies_parsed_at":"2024-03-08T11:24:53.815Z","dependency_job_id":"8518f51c-4926-49f3-8f92-b1eda898adfa","html_url":"https://github.com/futuredapp/kmp-futured-template","commit_stats":null,"previous_names":["futuredapp/kmp-futured-template"],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futuredapp%2Fkmp-futured-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futuredapp%2Fkmp-futured-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futuredapp%2Fkmp-futured-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futuredapp%2Fkmp-futured-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/futuredapp","download_url":"https://codeload.github.com/futuredapp/kmp-futured-template/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236298293,"owners_count":19126500,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","ios","kotlin","kotlin-multiplatform","kotlin-multiplatform-sample"],"created_at":"2025-01-30T04:29:17.874Z","updated_at":"2025-10-13T03:30:27.965Z","avatar_url":"https://github.com/futuredapp.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Futured KMP Template\n\nHey there 👋\n\nThis is our template from which we build Kotlin Multiplatform applications that target Android and\niOS platforms.\nIt is our opinionated way of building KMP apps and shines a light on how we structure our\narchitecture and what tools and libraries we use.\n\nTo give you a short overview of our stack, we use:\n\n- Native UI on both platforms. Jetpack Compose on Android and SwiftUI on iOS. The rest of the\n  application is shared in KMP.\n- [Decompose](https://github.com/arkivanov/Decompose) for sharing presentation logic and navigation\n  state.\n- The presentation layer follows the MVI-like design pattern.\n- [Koin](https://insert-koin.io/) for dependency injection.\n- [SKIE](https://skie.touchlab.co/) for better Kotlin-\u003eSwift interop (exhaustive enums, sealed\n  classes, Coroutines support).\n- [moko-resources](https://github.com/icerockdev/moko-resources) for sharing string (and other types\n  of) resources.\n- [apollo-kotlin](https://github.com/apollographql/apollo-kotlin) network client for apps that call\n  GraphQL APIs.\n- [ktorfit](https://github.com/Foso/Ktorfit) network client for apps that call plain HTTP APIs.\n- [Jetpack DataStore](https://developer.android.com/jetpack/androidx/releases/datastore) as a simple\n  preferences storage (we have JSON-based and primitive implementations).\n- [iOS-templates](https://github.com/futuredapp/iOS-templates) as template which generates a new iOS\n  scene using MVVM-C architecture.\n\nThe template is a sample app with several screens to let you kick off the project with everything\nset up, incl. navigation and some API calls.\n\n-------8\u003c------- CUT HERE AFTER CLONING -------8\u003c-------\n\n# Project Name\n\n![kmp](https://img.shields.io/badge/multiplatform-%237F52FF.svg?style=for-the-badge\u0026logo=kotlin\u0026logoColor=white)\n![compose](https://img.shields.io/badge/jetpack_compose-2bab6b.svg?style=for-the-badge\u0026logo=android\u0026logoColor=white)\n![swiftui](https://img.shields.io/badge/swiftui-%23000000.svg?style=for-the-badge\u0026logo=swift\u0026logoColor=white)\n\n![kotlin-version](https://img.shields.io/badge/kotlin-2.0.0-%237F52FF.svg?style=flat-square\u0026logo=kotlin\u0026logoColor=white)\n![android-minsdk](https://img.shields.io/badge/minsdk-29-2bab6b.svg?style=flat-square\u0026logo=android\u0026logoColor=white)\n![android-targetsdk](https://img.shields.io/badge/targetsdk-34-2bab6b.svg?style=flat-square\u0026logo=android\u0026logoColor=white)\n![ios-target](https://img.shields.io/badge/target-16.0-%23000000.svg?style=flat-square\u0026logo=apple\u0026logoColor=white)\n\n~~Short project description.~~\n\n## Project info\n\n- Deadline: ~~**--. --. ----**~~\n- Design: ~~Figma (add link)~~\n- ~~Backend: GrahlQL / Apiary / OpenAPI (add link)~~\n    - ~~Prod: https://live.app.com~~\n    - ~~Dev: https://staging.app.com~~\n- ~~Localizations: Czech, English – POEditor / Google Sheets (add link)~~\n- [Architecture decision records](doc/adr/README.md)\n\n### KMP\n\n- Product Flavors: dev, prod\n- Use-Cases: Kotlin Coroutines [cr-usecases](https://github.com/futuredapp/arkitekt)\n\n### Android\n\n- ApplicationId: ~~`app.futured.project`~~\n- minSdk: ~~`28`~~\n- targetSdk: ~~`34`~~\n- Supports: ~~**Dark mode, landscape orientation**~~\n- Build Variants: debug, enterprise, release\n\n### iOS\n\n- Deployment target: ~~**16.0**~~\n- Bundle identifier: ~~`app.futured.project`~~\n- Supports: ~~**Dark mode, landscape orientation, iPadOS, watchOS**~~\n- Language: ~~**Swift 5.0**~~\n- IDE: ~~**Xcode 11.0**~~\n- Dependency management: [Swift package manager](https://swift.org/package-manager/)\n- Command line tools: **[Fastlane](https://docs.fastlane.tools)**\n- Code style:\n    - **[SwiftLint](https://swift.org/package-manager/)**\n    - **[Danger](https://github.com/futuredapp/danger)**\n\n## Team:\n\n- ~~Jana Nováková, PM, \u003cjana.novakova@futured.app\u003e~~\n- ~~Jan Novák, iOS developer, \u003cjan.novak@futured.app\u003e~~\n- ~~John Newman, tester, \u003cjohn.newman@futured.app\u003e~~\n\n## Used Tools\n\n- Code style - **[ktlint](https://ktlint.github.io/)**, *\n  *[detekt](https://arturbosch.github.io/detekt/)**, *\n  *[Android lint](http://tools.android.com/tips/lint)**, *\n  *[Danger](https://github.com/futuredapp/danger)**\n- Kotlin -\u003e Swift interop - **[skie](https://skie.touchlab.co/)**\n\n### ~~Test accounts~~\n\n- ~~dev - login: `a@a.com`, password: `hesloheslo`~~\n\n### Security Standard\n\nThis project complies with ~~Standard (F0), High (F1), Highest (F2)~~ security standard.\n\n~~[Project specific standard](www.notion.so)~~\n\n## Gradle tasks\n\n1. `clean` - Remove all `build` folders\n2. `lintCheck` - Run `ktlint`, `detekt` checks. The same runs on CI.\n3. `ktlintFormat` - Reformat source code according to ktlint rules.\n4. `assembleAndCopyDebugSwiftPackage` - Assemble debug KMP XCFramework and copy it into local iOS\n   Swift Package as dependency. (This task shouldn't be used directly, build the KMP target in\n   Xcode, instead.)\n5. `assembleAndCopyReleaseSwiftPackage` - Assemble release KMP XCFramework and copy it into local\n   iOS Swift Package as dependency. (This task shouldn't be used directly, build the KMP target in\n   Xcode, instead.)\n6. `generateMRcommonMain` - Regenerate shared resource IDs.\n7. `:shared:network:graphql:downloadApolloSchemaFromIntrospection` - Download the latest Apollo\n   schema.\n8. `:shared:network:graphql:generateApolloSources` - Generate Apollo sources (rebuilds models after\n   adding modifying queries, mutations, etc.).\n\n## Kotlin Multiplatform Swift Package Integration\n\n### Architecture Overview\n\nThe iOS application integrates with KMP code through a local Swift Package Manager (SPM) package\nlocated at `iosApp/shared/KMP/`. This package wraps the XCFramework generated by the KMP Gradle\nplugin, providing a clean and modern dependency management approach.\n\nKey components:\n\n1. **Swift Package**: Located at `iosApp/shared/KMP/` with `Package.swift` defining the binary\n   target\n2. **XCFramework**: Generated by Gradle and referenced by the Swift Package\n3. **Makefile**: Automates the build process based on environment variables\n4. **Build Configuration**: Environment variables defined in `.xcconfig` files\n\n### Environment Variables\n\nTwo critical environment variables control the build process:\n\n- **`KMP_FRAMEWORK_BUILD_TYPE`**: Specifies the framework build type (`debug` or `release`)\n    - Set in `.xcconfig` files for each Xcode build configuration\n    - Controls optimization level and debug information\n    - Determines which Gradle task to run (`assembleAndCopyDebugSwiftPackage` or\n      `assembleAndCopyReleaseSwiftPackage`)\n\n- **`KMP_BUILD_FLAVOR`**: Specifies the product flavor (see [Product Flavors](#product-flavors))\n    - Set in `.xcconfig` files for each Xcode build configuration\n    - Controls API endpoints and environment-specific configuration\n    - Passed to Gradle as `-P buildkonfig.flavor=$(KMP_BUILD_FLAVOR)`\n\n### Development Workflow\n\nTo build and update the KMP package during development:\n\n1. **Select and build the \"Build KMP\" target in Xcode**:\n    - This target's build phase runs the Makefile with the appropriate environment variables\n    - The Makefile detects the build configuration and runs the corresponding Gradle task\n    - The XCFramework is generated and copied to the Swift Package location\n\n2. **Alternative manual build**:\n    - `./gradlew assembleAndCopyDebugSwiftPackage`\n    - or if you wish to specify product flavor (default is always `dev`):\n      `./gradlew assembleAndCopyDebugSwiftPackage -P buildkonfig.flavor=[dev|prod]`\n\n3. **After KMP code changes**:\n    - Always rebuild the \"KMP Package\" target to update the XCFramework\n    - Then build the main app target to use the updated KMP code\n\n## Navigation Structure\n\nThe app utilizes [Decompose](https://arkivanov.github.io/Decompose/) to share presentation logic and\nnavigation state in KMP.  \nThe following meta-description provides an overview of Decompose navigation tree:\n\n```kotlin\nNavigation(\"RootNavHost\") {\n    Slot {\n        Screen(\"LoginScreen\")\n        Navigation(\"SignedInNavHost\") {\n            // Bottom navigation stack\n            Stack {\n                // Home tab\n                Navigation(\"HomeNavHost\") {\n                    Stack {\n                        Screen(\"FirstScreen\")\n                        Screen(\"SecondScreen\") {\n                            Slot {\n                                Screen(\"Picker\")\n                            }\n                        }\n                        Screen(\"ThirdScreen\")\n                    }\n                }\n                // Profile tab\n                Navigation(\"ProfileNavHost\") {\n                    Stack {\n                        Screen(\"ProfileScreen\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n## Project Setup\n\n### Initial script\n\nUse `init_template.kts` script to set up the template.\nThe script renames directories and package names in files to the given package name.\n\nIt is written in Kotlin. To run it you need to have [kscript](https://github.com/kscripting/kscript)\ninstalled.\n\n#### Usage\n\n```shell\nkscript init_template.kts\n```\n\n#### Note on iOS\n\nThe Swift Package XCFramework has to be build manually for the first time using `./gradlew assembleAndCopyDebugSwiftPackage` in order for XCode to resolve Swift Package as being valid.\n\n### Product Flavors\n\nThe project utilizes [BuildKonfig](https://github.com/yshrsmz/BuildKonfig) plugin for implementing\nbuild flavors in the network module.\nThere are two product flavors: `dev` and `prod`, which select API url used in `:shared:network:rest`\nand `:shared:network:graphql` modules.\n\nIn general, the build flavor can be specified as a Gradle build flag\n\n```shell\n./gradlew whateverTask -P buildkonfig.flavor=dev\n```\n\nPlease, refer to `:shared:network:*` module Gradle configs for more info.\n\n#### Android\n\nDuring local development, the build flavor can be specified in `gradle.properties` file like so:\n\n```properties\nbuildkonfig.flavor=dev\n```\n\n#### Charles Proxy\n\n[Charles Proxy](https://www.charlesproxy.com/documentation/welcome/) is enabled for debug and\nenterprise builds.\n\n#### iOS\n\nOn iOS, we utilize\n.xcconfig [Build Configuration](https://www.kodeco.com/21441177-building-your-app-using-build-configurations-and-xcconfig)\nfiles,\nwhere each file per build configuration specifies a `KMP_BUILD_FLAVOR` environment variable.\n\nThis variable is then used in the \"Build KMP\" target to pass the flavor as Gradle build\nflag.\n\n```shell\n./gradlew assembleAndCopyDebugSwiftPackage -P buildkonfig.flavor=$(KMP_BUILD_FLAVOR)\n```\nSee [Makefile](iosApp/shared/KMP/Makefile) for reference.\n\nCurrently, the `Debug.xcconfig` file sets `KMP_BUILD_FLAVOR=dev` and the `Release.xcconfig` sets\n`KMP_BUILD_FLAVOR=prod`. When adding new build configurations, please make sure to also define the\n`KMP_BUILD_FLAVOR`\nvariable using the aforementioned method.\n\n### Crashlytics\n\nWe can have symbolicated Kotlin crash reports on iOS. We\nuse [NSExceptionKt](https://github.com/rickclephas/NSExceptionKt) to achieve that.\nEverything is set up, but some finishing touches need to be made when you add Crashlytics to your\nproject:\n\n1. Set up Firebase Crashlytics on both platforms as you would usually do.\n2. After dependencies are in place, on each platform uncomment the code in\n   `PlatformFirebaseCrashlyticsImpl` classes (follow comments).\n3. On iOS, do not forget to also upload debug symbols to Crashlytics. The KMP framework is static,\n   so no standalone debug symbols are generated for KMP, instead, they are included in the app\n   itself.\n\n## Deep Linking\n\nDeep links are provided by each platform to common code and parsed using `DeepLinkResolver` class.\nThe (sample) app currently supports the following url scheme: `kmptemplate` and the following links:\n\n- `kmptemplate://home` -- Opens Home tab with default stack.\n- `kmptemplate://profile` -- Opens Profile tab with default stack.\n- `kmptemplate://home/second` -- Opens SecondScreen in Home tab.\n- `kmptemplate://home/third?arg={argument}` -- Opens ThirdScreen in Home tab with provided argument.\n  The `argument` is mandatory.\n- `kmptemplate://home/third/{argument}` -- Opens ThirdScreen in Home tab with provided argument. The\n  `argument` is mandatory.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuturedapp%2Fkmp-futured-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffuturedapp%2Fkmp-futured-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuturedapp%2Fkmp-futured-template/lists"}