Minimal Kotlin Multiplatform project with SwiftUI, Jetpack Compose, Wear Compose, Compose for Desktop, Compose for Web and Kotlin/JS + React clients along with Ktor backend.

Overview

PeopleInSpace

Minimal Kotlin Multiplatform project with SwiftUI, Jetpack Compose, Compose for Wear OS, Compose for Desktop, Compose for Web, and Kotlin/JS + React clients along with Ktor backend. Currently running on

It makes use of Open Notify PeopleInSpace API to show list of people currently in space and also the position of the International Space Station (inspired by https://kousenit.org/2019/12/19/a-few-astronomical-examples-in-kotlin/)!

The project is included as sample in the official Kotlin Multiplatform Mobile docs and also the Google Dev Library

Related posts:

Note that this repository very much errs on the side of minimalism to help more clearly illustrate key moving parts of a Kotlin Multiplatform project and also to hopefully help someone just starting to explore KMP to get up and running for first time (and is of course primarily focused on use of Jetpack Compose and SwiftUI). If you're at the stage of moving beyond this then I'd definitely recommend checking out KaMPKit from Touchlab. I also have the following samples that demonstrate the use of a variety of Kotlin Multiplatform libraries (and also use Jetpack Compose and SwiftUI).

Building

You need to use Android Studio Arctic Fox (note: Java 11 is now the minimum version required). Requires XCode 13.2 or later (due to use of new Swift 5.5 concurrnecy APIs).

When opening iOS/watchOS/macOS projects remember to open .xcworkspace file (and not .xcodeproj one).

To exercise (React based) web client run ./gradlew :web:browserDevelopmentRun.

To run backend you can either run ./gradlew :backend:run or run Server.kt directly from Android Studio. After doing that you should then for example be able to open http://localhost:9090/astros_local.json in a browser.

Compose for Web client

The Compose for Web client resides in the compose-web module and can be run by invoking ./gradlew :compose-web:jsBrowserDevelopmentRun

Compose for Desktop client

This client is available in compose-desktop module. Note that you need to use appropriate version of JVM when running (works for example with Java 11)

Deploying backend code

Have tested this out in Google App Engine deployment. Using shadowJar plugin to create an "uber" jar and then deploying it as shown below. Should be possible to deploy this jar to other services as well.

./gradlew :backend:shadowJar
gcloud app deploy backend/build/libs/backend-all.jar 

Screenshots

iOS (SwiftUI)
Screenshot 2021-02-27 at 12 09 02

Android (Jetpack Compose)
Screenshot 2021-03-07 at 17 03 46

watchOS (SwiftUI)
watchOS Screenshot 1 watch0S Screenshot 2

Wear OS (Wear Compose)
Wear Compose Screenshot 1 Wear Compose Screenshot 2 Wear Compose Screenshot 3

macOS (SwiftUI)
Screenshot 2021-06-01 at 20 02 31

Compose for Desktop
Screenshot 2021-10-01 at 16 45 06

Compose for Web
Screenshot 2021-05-31 at 21 29 53

Web App (Kotlin/JS + React)
Screenshot 2021-06-06 at 23 50 00

Languages, libraries and tools used

Comments
  • Can not run the watchOS app on the emulator

    Can not run the watchOS app on the emulator

    Reproduction steps:

    1. clone the repository
    2. open .xcworkspace in Xcode
    3. change signing to local team
    4. attempt to run on the local emulator

    This is the output I get:

    ld: warning: ignoring file /Volumes/macApps/fhswf/S5/Projekt/PeopleInSpace/common/build/cocoapods/framework/common.framework/common, building for watchOS Simulator-x86_64 but attempting to link with file built for watchOS Simulator-i386
    Undefined symbols for architecture x86_64:
      "_OBJC_CLASS_$_CommonKoinKt", referenced from:
          objc-class-ref in ExtensionDelegate.o
      "_OBJC_CLASS_$_CommonAssignment", referenced from:
          objc-class-ref in ViewModel.o
      "_OBJC_CLASS_$_CommonPeopleInSpaceRepository", referenced from:
          objc-class-ref in ContentView.o
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    
    

    I guess the warning

    watchOS Simulator-x86_64 but attempting to link with file built for watchOS Simulator-i386

    already tells a lot but I am not sure how to change that

    opened by StefanLobbenmeier 22
  • project import failed in a newly installed AS 4.2 canary 8 (Ubuntu)

    project import failed in a newly installed AS 4.2 canary 8 (Ubuntu)

    Project import fails with error Please initialize at least one Kotlin target in 'common (:common)'.

    OS: Ubuntu Linux 20.04

    Android Studio Version: 4.2 Canary 8. (No multiplatform project has been done before now)

    Clicking Run with --debug option returns this error. Caused by: org.gradle.internal.component.AmbiguousConfigurationSelectionException: The consumer was configured to find a runtime of a library compatible with Java 14, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'. However we cannot choose between the following variants of project :common: Changing the default system jdk to java 8 prints the same message but now Java 8 instead of Java 14.

    opened by odifek 22
  • Use version catalogs and update mechanism

    Use version catalogs and update mechanism

    Before I migrate more than one module, wanted to check you are happy with the direction.

    Question

    • Default paths for deps e.g. libs.androidx.wear.compose.compose.navigation

    It makes it simple to update update with

    $ ./gradlew versionCatalogUpdate
    
    opened by yschimke 15
  • Usage of compose-ios

    Usage of compose-ios

    Hi, can you help me? where can I find documentation or tutorials for compose-ios?

    I tried to run ./gradlew compose-ios:iosDeployIPhone8Debug

    but it threw the following error:

    Field 'dataPathSize' is required for type with serial name 'org.jetbrains.compose.experimental.uikit.internal.DeviceData', but it was missing

    opened by alandoni 13
  • Could not initialize class org.jetbrains.kotlin.com.intellij.pom.java.LanguageLevel

    Could not initialize class org.jetbrains.kotlin.com.intellij.pom.java.LanguageLevel

    Can't open the project on my mac, tried following Android Studio versions: Arctic Fox 2020.3.1 Beta 2 Android Studio 4.2 Android Studio 4.2.1 Bumblebee 2021.1.1 Canary 1

    I'm running into following error as soon as I try to build the app from version controll:

    java.lang.NoClassDefFoundError: Could not initialize class org.jetbrains.kotlin.com.intellij.pom.java.LanguageLevel
    	at org.jetbrains.kotlin.com.intellij.core.CoreLanguageLevelProjectExtension.<init>(CoreLanguageLevelProjectExtension.java:26)
    	at org.jetbrains.kotlin.com.intellij.core.JavaCoreProjectEnvironment.<init>(JavaCoreProjectEnvironment.java:42)
    	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment.<init>(KotlinCoreProjectEnvironment.kt:26)
    	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$ProjectEnvironment.<init>(KotlinCoreEnvironment.kt:118)
    	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createForProduction(KotlinCoreEnvironment.kt:420)
    	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.createCoreEnvironment(K2JVMCompiler.kt:226)
    	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:152)
    	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:52)
    	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:88)
    	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:44)
    	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:98)
    	at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:371)
    	at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:105)
    	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:249)
    	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.access$compileIncrementally(IncrementalCompilerRunner.kt:38)
    	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner$compile$2.invoke(IncrementalCompilerRunner.kt:80)
    	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:92)
    	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:602)
    	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:93)
    	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1644)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    	at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
    	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
    	at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
    	at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    	at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:587)
    	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
    	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:705)
    	at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704)
    	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    	at java.base/java.lang.Thread.run(Thread.java:831)
    

    An older version of PeopleInSpace works fine on Android but I also run into a problem on Xcode: Cannot find 'KoinKt' in scope

    opened by DaFaack 11
  • Add rotary input event handler

    Add rotary input event handler

    Added support for rotary input (physical rotating side button or bezel). Currently, Column / LazyColumn doesn’t handle rotary event, so we need to make it by ourselves. Used handler API per https://developer.android.com/training/wearables/user-input/rotary-input

    opened by saryongkang 10
  • Delay load on Wear, used cache data from DB.

    Delay load on Wear, used cache data from DB.

    For discussion, haven't tested on mobile yet.

    Current logic on Android shows blank until the webservice request. Instead use cached db results, and replace with updates afterwards.

    opened by yschimke 9
  • Gradle sync fails with latest stable Andriod Sudio + KMM plugin

    Gradle sync fails with latest stable Andriod Sudio + KMM plugin

    AS 4.2.1 / KMM plugin v0.2.6

    Clean check out of PeopleInSpace, Gradle sync fails with:

    Unrecognized Android Studio (or Android Support plugin for IntelliJ IDEA) version '202.7660.26.42.7351085', please retry with version 2020.3.1 or newer.

    opened by ktchernov 9
  • Cannot build the project - An exception occurred applying plugin request [id: 'com.android.application']

    Cannot build the project - An exception occurred applying plugin request [id: 'com.android.application']

    FAILURE: Build failed with an exception.
    
    * Where:
    Build file '/Users/safaiyeh/code/PeopleInSpace/app/build.gradle.kts' line: 1
    
    * What went wrong:
    An exception occurred applying plugin request [id: 'com.android.application']
    > Failed to apply plugin 'com.android.internal.application'.
       > Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
         You can try some of the following options:
           - changing the IDE settings.
           - changing the JAVA_HOME environment variable.
           - changing `org.gradle.java.home` in `gradle.properties`.
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    
    * Get more help at https://help.gradle.org
    
    Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
    Use '--warning-mode all' to show the individual deprecation warnings.
    See https://docs.gradle.org/6.8-rc-4/userguide/command_line_interface.html#sec:command_line_warnings
    
    opened by safaiyeh 7
  • Upgrading to Android Studio Arctic Fox Canary 3 breaks Gradle build

    Upgrading to Android Studio Arctic Fox Canary 3 breaks Gradle build

    Android Studio Arctic Fox Canary 2 works fine - but upgrading to Canary 3 (and upgrading Gradle to 6.8-rc1 and android plugin to 7.0.0-alpha03 breaks the build:

    ➜  PeopleInSpace git:(master) ✗ ./gradlew assemble                         
    
    > Configure project :backend
    
    The 'org.jetbrains.kotlin.platform.*' plugins are deprecated and will no longer be available in Kotlin 1.4.
    Please migrate the project to the 'org.jetbrains.kotlin.multiplatform' plugin.
    See: https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html
    
    > Configure project :common
    To take advantage of the new functionality for Cocoapods Integration like synchronizing with the Xcode project 
    and supporting dependencies on pods, please install the `cocoapods-generate` plugin for CocoaPods 
    by calling `gem install cocoapods-generate` in terminal. 
    
    More details are available by https://github.com/square/cocoapods-generate
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    A problem occurred configuring project ':common'.
    > Configuration with name 'testApi' not found.
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    
    * Get more help at https://help.gradle.org
    
    Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
    Use '--warning-mode all' to show the individual deprecation warnings.
    See https://docs.gradle.org/6.8-rc-1/userguide/command_line_interface.html#sec:command_line_warnings
    
    BUILD FAILED in 735ms
    
    opened by mreichelt 7
  • Status of Android Release Target

    Status of Android Release Target

    I got some issues with @ Serializable missing from some data being persisted, I guessed probably the pro guard rules aren't quite right. But as I had some other changes it wasn't worth reporting as is.

    I guess probably these

    @Serializable
    data class AstroResult(val message: String, val number: Int, val people: List<Assignment>)
    

    Before spending any time on it I was wondering if it's known to generally work?

    Specifically I wanted to test performance with an optimized release build, as compose in debug builds is known to be slower.

    opened by yschimke 6
  • Update Kotlin to `1.8.0`

    Update Kotlin to `1.8.0`

    Kotlin 1.8.0 is out! Although it might take some time for the compose compiler to be compatible with this version, I thought it might be good to have an issue regarding this topic.

    opened by YektaDev 2
  • KTOR Http logging not working when working with Koin

    KTOR Http logging not working when working with Koin

    I've implemented koin in my kmm project and for network I'm using Ktor but I noticed that Ktor logging is not working when implemented using Koin DI however it is working if I directly place ktor http code inside file.

    Here is my code snippet:

    Versions: ktorVersion = "2.0.2" koinVersion = "3.2.0"

    Koin class

       fun initKoin(appDeclaration: KoinAppDeclaration = {}) : KoinApplication = 
            startKoin {
                appDeclaration()
                modules(commonModule(enableNetworkLogs), platformModule())
            }.apply {
                initLogger()
            }
        fun commonModule() = module {
            single { createKoinClient(get()) }
            single { NetworkModule(get(), baseURL = "https://gitcdn.link/cdn/KaterinaPetrova/") }
        }
    
         fun createKoinClient(httpClientEngine: HttpClientEngine) =
            HttpClient(httpClientEngine) {
                install(Logging) {
                    level = LogLevel.HEADERS
                    logger = object : Logger {
                        override fun log(message: String) {
                            Napier.e(tag = "Http Request", message = message)
                        }
                    }
                }
                install(ContentNegotiation) {
                    json(Json { isLenient = true; ignoreUnknownKeys = true })
                }
            }
    
    
    opened by AliAzaz 1
  • Adopt Tiles Material and use Android Studio Previews

    Adopt Tiles Material and use Android Studio Previews

    Glance is not stable yet. Tiles Material is likely available soon with some components for nice Tile Layouts.

    This is not yet ready, but mainly focusing on the design, using Preview tooling to get it right.

    cc @joreilly any issue with this change from your view?

    n.b. the previews currently show the fallback image, I'll change to use real images soon.

    opened by yschimke 2
  • Could not download kotlin-serialization-1.6.10.jar in Xcode

    Could not download kotlin-serialization-1.6.10.jar in Xcode

    • What went wrong: A problem occurred configuring root project 'PeopleInSpace'.

    Could not resolve all artifacts for configuration ':classpath'. Could not download kotlin-serialization-1.6.10.jar (org.jetbrains.kotlin:kotlin-serialization:1.6.10) > Could not get resource 'https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-serialization/1.6.10/kotlin-serialization-1.6.10.jar'. > Could not GET 'https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-serialization/1.6.10/kotlin-serialization-1.6.10.jar'. > Unsupported or unrecognized SSL message

    anyone can help me?

    opened by ruzhuxiaogu 1
  • Rationale for using `buildSrc` instead of `Composite Builds`

    Rationale for using `buildSrc` instead of `Composite Builds`

    PeopleInSpace uses Build Sources (buildSrc).

    Is there a reason why Composite Builds is not used instead?

    As I was checking how PeopleInSpace manages versioning, I saw this PR https://github.com/joreilly/PeopleInSpace/pull/116 and it prompted me to look into buildSrc and Composite Build.

    opened by om-ha 1
Owner
John O'Reilly
Android Software Engineer
John O'Reilly
A clone of hn.premii.com implemented in KMP with Web (React), iOS (Swift UI), Android and Desktop (Compose) UIs

An clone of hn.premii.com implemented in Kotlin Multiplatform with shared Android/Desktop Compose UI, SwiftUI on iOS and React for Web This example su

Tarek Belkahia 7 Feb 5, 2022
Backend aio - A project made to help all newbie programmers that are approaching backend development

BackendAIO A ktor based ready to use backend BackendAIO is a project made to hel

Fabrizio Scarponi 4 Feb 1, 2022
Backend coding challenge using Kotlin and Ktor

Backend Coding Challenge We appreciate you taking the time to participate and su

Thermondo 0 Jan 4, 2022
Kotlin backend based on the Clean Architecture principles. Ktor, JWT, Exposed, Flyway, KGraphQL/GraphQL generated endpoints, Gradle.

Kotlin Clean Architecture Backend Kotlin backend based on the Clean Architecture principles. The application is separated into three modules: Domain,

null 255 Jan 3, 2023
A small backend for the Thinkrchive app written in Kotlin with Ktor

A small backend for the Thinkrchive app written in Kotlin with Ktor. It uses Postgresql with a few requests and JWT authentication for admins.

Thinkrchive 6 Dec 12, 2022
It is a repository containing backend structure for Ktor.

Backend Architecture with Ktor + KMongo This project contains, Authentication using Jwt Database Layer (KMongo - Orm for MongoDB) Routing Advanced Rou

Himanshu Singh 56 Dec 28, 2022
Android Note app that uses the "ktor-note-app" backend

KtorNoteApp Android Notes app that uses Ktor back end server Technologies employed: Kotlin MVVM Coroutines Custom REST API build with Ktor Responds to

Chris Athanas 2 Jul 25, 2022
KTor-Client---Android - The essence of KTor Client for network calls

KTor Client - Android This project encompasses the essence of KTor Client for ne

Mansoor Nisar 2 Jan 18, 2022
Jetpack Compose for Desktop and Web, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.

Jetpack Compose for Desktop and Web, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.

JetBrains 10k Jan 7, 2023
Android & iPhone payments apps built w/ SwiftUI & Jetpack Compose

Android & iPhone payments apps built w/ SwiftUI & Jetpack Compose, the apps persist data locally w/ SQLDelight and Remote w/ Firebase., Payments w/ Stripe and are architected to emphasize code sharing

Mwai Banda 21 Dec 21, 2022
A sample skeleton backend app built using Spring Boot kotlin, Expedia Kotlin Graphql, Reactive Web that can be deployed to Google App Engine Flexible environmennt

spring-kotlin-gql-gae This is a sample skeleton of a backend app that was built using: Spring Boot(Kotlin) Reactive Web Sprinng Data R2DBC with MYSQL

Dario Mungoi 7 Sep 17, 2022
Building Web Applications with React and Kotlin JS Hands-On Lab

Building Web Applications with React and Kotlin JS Hands-On Lab This repository is the code corresponding to the hands-on lab Building Web Application

Brian Donnoe 0 Nov 13, 2021
Ktor is an asynchronous framework for creating microservices, web applications and more.

ktor-sample Ktor is an asynchronous framework for creating microservices, web applications and more. Written in Kotlin from the ground up. Application

mohamed tamer 5 Jan 22, 2022
Sencilla aplicación web para realizar un CRUD usando Ktor y motores de plantillas similar a Laravel con PHP

Servicio web para crear una WEB App usando Kotlin y Kator así como otras tecnologías propuestas por JetBrains.

José Luis González Sánchez 1 Feb 12, 2022
Live-coding a web server with Ktor

ktor-sample Live-coding a web server with Ktor Ktor is a Kotlin framework dedicated to building asynchronous servers and clients in connected systems.

Renaud Mathieu 1 May 10, 2022
FragmentContainerViewIdBugDemo - minimal repro project demonstrating a bug in FragmentContainerView's id check logic in the context of a dynamic feature module

FragmentContainerViewIdBugDemo minimal reproduce project demonstrating an apparent bug in FragmentContainerView's id check logic in the context of a d

null 0 Jan 5, 2022
SSU u-saint parser with Kotlin-Multiplatform and Ktor.

kusaint Soongsil University(SSU) u-Saint Parser with Kotlin Multiplatform. Prerequisites JVM !!IMPORTANT!! To run kusaint as a library in JVM environm

Hyomin Koo 3 Mar 23, 2022
sample project that shows you how you can use Ktor to creat a server for real Project.

Ktor-Sample This is a sample project that shows you how you can use Ktor to creat a server for real Project. What is done Save data to database (Get a

Mohamed Emad 4 Dec 23, 2022
Multiplatform HTTP-Client implementation using Ktor

Kotlin Multiplatform HTTP-Client using Ktor Simple demonstration of a Ktor-based multiplatform HTTP-client in Kotlin Overview base submodule: common c

Jan Weidenhaupt 2 Oct 21, 2022