What's new in Kotlin 2.3.20
The Kotlin 2.3.20 release is out! Here are the main highlights:
Gradle: Compatibility with Gradle 9.3.0 and Kotlin/JVM compilation uses BTA by default
Kotlin compiler plugins: Lombok is in Alpha and improved JPA support in the
kotlin.plugin.jpapluginStandard library: New API for creating immutable copies of
Map.EntryKotlin/Native: New interoperability mode for C and Objective-C libraries
Update to Kotlin 2.3.20
The latest version of Kotlin is included in the latest versions of IntelliJ IDEA and Android Studio.
To update to the new Kotlin version, make sure your IDE is updated to the latest version and change the Kotlin version to 2.3.20 in your build scripts.
New features
The following feature is Stable in this release:
Simplified setup for Kotlin projects
Kotlin 2.3.20 makes it easier to set up Kotlin in Maven projects. Now Kotlin supports the automatic configuration of source roots and Kotlin's standard library.
With the new automatic configuration, when you create a new Kotlin project with the Maven build system or introduce Kotlin to your existing Java Maven project, you don't need to manually specify source root paths or add the kotlin-stdlib dependency in your POM build file.
How to enable
In your pom.xml file, add <extensions>true</extensions> to the <build><plugins> section of the Kotlin Maven plugin:
The new extension automatically:
Registers
src/main/kotlinandsrc/test/kotlindirectories as source roots in case they already exist but are not specified in the plugin configuration.Adds the
kotlin-stdlibdependency in case it's not explicitly defined already.
You can also opt out of the automatic addition of Kotlin's standard library. For that, add the following to the <properties> section:
Note that the property disables all simplified setup features, including the registration of source root paths.
For more information on configuring Kotlin Maven projects, see Configure a Maven project.
New features
The following pre-stable features are available in this release. This includes features with Beta, Alpha, and Experimental status:
Standard library: New API for creating immutable copies of
Map.EntryKotlin/Native: New interoperability mode for C or Objective-C libraries
Lombok is now in Alpha
Kotlin 1.5.20 introduced the experimental Lombok compiler plugin, which lets you generate and use Java's Lombok declarations in modules that mix Kotlin and Java code.
In 2.3.20, the Lombok compiler plugin has been promoted to Alpha because we plan to make this functionality production-ready, but it's still under development.
Name-based destructuring
Kotlin 2.3.20 introduces name-based destructuring declarations, which match variables to property names instead of relying on position-based componentN() functions.
Previously, destructuring declarations used position-based destructuring:
In this example, because destructuring relies on the order of componentN() functions, email receives the value of username, and username receives the value of email.
Starting with Kotlin 2.3.20, you can use name-based destructuring where each variable refers to a property by name:
Name-based destructuring is Experimental. You can control how the compiler interprets destructuring declarations with the -Xname-based-destructuring compiler option.
It has the following modes:
only-syntaxenables the explicit form of name-based destructuring without changing the behavior of existing destructuring declarations.name-mismatchreports warnings when position-based destructuring in data classes uses variable names that don't match the property names.completeenables short-form name-based destructuring with parentheses and continues supporting position-based destructuring with square bracket syntax.
If you use complete mode, the short-form destructuring syntax with parentheses matches variables to property names instead of relying on position:
How to enable
To use named-based destructuring in your project, add the compiler option to your build configuration file:
Opting in to name-based destructuring also introduces a new syntax for position-based destructuring using square brackets:
We plan to gradually move toward destructuring declarations using name-based matching by default, while preserving position-based destructuring with the new square bracket syntax.
For more information, see the feature's KEEP.
We would appreciate your feedback in YouTrack.
New API for creating immutable copies of Map.Entry
Kotlin 2.3.20 introduces the Map.Entry.copy() extension function for creating an immutable copy of a Map.Entry. This function allows you to reuse entries obtained from Map.entries after modifying the map by copying them first.
Map.Entry.copy() is Experimental. To opt in, use the @OptIn(ExperimentalStdlibApi::class) annotation or the compiler option:
Here's an example of using Map.Entry.copy() to remove entries from a mutable map:
New interoperability mode for C or Objective-C libraries
If you use C or Objective-C libraries in your Kotlin Multiplatform (KMP) libraries or applications, we invite you to test the new interoperability mode and share the results.
In general, Kotlin/Native enables importing C and Objective-C libraries into Kotlin. However, for KMP libraries, this functionality is currently affected by the KMP compatibility issues with older compiler versions.
In other words, if you publish a KMP library compiled with one Kotlin version, importing C or Objective-C libraries might make it impossible to use that Kotlin library in projects with an earlier Kotlin version.
To address this and other issues, the Kotlin team has been revising the interoperability mechanism used under the hood. Starting with Kotlin 2.3.20, you can try the new mode through a compiler option.
How to enable
In your Gradle build file, check whether you have a
cinterops {}block or apod()dependency. If these are present, your project uses C or Objective-C libraries.Ensure your project uses
2.3.20or a later version.In the same build file, add the
-Xccall-modecompiler option to the cinterop tool invocation:kotlin { targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>().configureEach { compilations.configureEach { cinterops.configureEach { extraOpts += listOf("-Xccall-mode", "direct") } } } }Build and test your project as usual by running unit tests, the app, and so on. You can also use the
--continueoption to allow Gradle to continue executing tasks even after failures, helping to find more problems at once.
Report your results
The new interoperability mode is supposed to be a drop-in replacement in most cases. We're planning to eventually enable it by default. But to achieve that, we need to ensure it works as well as possible and test it on a wide range of projects, because:
Some C and Objective-C declarations aren't yet supported in the new mode (mostly because of compatibility issues). We'd like to better understand the real-world impact of this and prioritize future steps accordingly.
There may be bugs or things we haven't considered. Testing languages with numerous interacting features is challenging, and testing the interaction between languages (each with a unique set of features) is even more so.
Help us examine real-world projects and identify challenging cases. Whether you encounter any issues or not, share your results in the comments to in YouTrack.
Language
Kotlin 2.3.20 adds name-based destructuring declarations that match variables to property names instead of relying on position. It also introduces changes to overload resolution for declarations with context parameters.
Changes to overload resolution for context parameters
Kotlin 2.3.20 introduces changes to overload resolution for declarations with context parameters.
Previously, overload resolution treated declarations with context parameters as more specific than those without them.
Starting with Kotlin 2.3.20, this rule no longer applies, making overload selection more uniform. As a result, calls that previously resolved now become ambiguous, resulting in a compilation error when overloads differ only by context parameters. In such cases, the compiler warns about potential ambiguity.
Here's an example:
Additionally, Kotlin 2.3.20 reduces the number of kotlin.context overloads from 22 to 6 to reduce excessive overload candidates during resolution and code completion.
Name-based destructuring
Kotlin 2.3.20 introduces name-based destructuring declarations, which match variables to property names instead of relying on position-based componentN() functions.
Previously, destructuring declarations used position-based destructuring:
In this example, because destructuring relies on the order of componentN() functions, email receives the value of username, and username receives the value of email.
Starting with Kotlin 2.3.20, you can use name-based destructuring where each variable refers to a property by name:
Name-based destructuring is Experimental. You can control how the compiler interprets destructuring declarations with the -Xname-based-destructuring compiler option.
It has the following modes:
only-syntaxenables the explicit form of name-based destructuring without changing the behavior of existing destructuring declarations.name-mismatchreports warnings when position-based destructuring in data classes uses variable names that don't match the property names.completeenables short-form name-based destructuring with parentheses and continues supporting position-based destructuring with square bracket syntax.
If you use complete mode, the short-form destructuring syntax with parentheses matches variables to property names instead of relying on position:
How to enable
To use named-based destructuring in your project, add the compiler option to your build configuration file:
Opting in to name-based destructuring also introduces a new syntax for position-based destructuring using square brackets:
We plan to gradually move toward destructuring declarations using name-based matching by default, while preserving position-based destructuring with the new square bracket syntax.
For more information, see the feature's KEEP.
We would appreciate your feedback in YouTrack.
Standard library
Kotlin 2.3.20 includes a new experimental feature for the standard library.
New API for creating immutable copies of Map.Entry
Kotlin 2.3.20 introduces the Map.Entry.copy() extension function for creating an immutable copy of a Map.Entry. This function allows you to reuse entries obtained from Map.entries after modifying the map by copying them first.
Map.Entry.copy() is Experimental. To opt in, use the @OptIn(ExperimentalStdlibApi::class) annotation or the compiler option:
Here's an example of using Map.Entry.copy() to remove entries from a mutable map:
Kotlin compiler plugins
Kotlin 2.3.20 brings important updates to the Lombok and kotlin.plugin.jpa compiler plugins.
Improved JPA support in the kotlin.plugin.jpa plugin
The kotlin.plugin.jpa plugin now automatically applies the all-open compiler plugin with the newly added built-in JPA preset, in addition to applying the existing no-arg compiler plugin.
Previously, using kotlin("plugin.jpa") enabled only the no-arg plugin with JPA presets.
In this release, we improved the kotlin.plugin.jpa preset so the all-open plugin is configured automatically. This ensures that lazy associations work as expected instead of causing eager loading and triggering extra queries.
Starting with Kotlin 2.3.20:
The
all-opencompiler plugin provides a JPA preset.The Gradle
org.jetbrains.kotlin.plugin.jpaplugin automatically applies theorg.jetbrains.kotlin.plugin.all-openplugin with the JPA preset enabled.The Maven JPA setup enables
all-openwith the JPA preset by default. (Support in IntelliJ IDEA is available from 2026.1.)The Maven dependency
org.jetbrains.kotlin:kotlin-maven-noargnow implicitly includesorg.jetbrains.kotlin:kotlin-maven-allopen, so you no longer need to add it explicitly in the<plugin><dependencies>block.
As a result, JPA entities annotated with the following annotations are automatically treated as open and receive no-argument constructors without additional configuration:
javax.persistence.Entityjavax.persistence.Embeddablejavax.persistence.MappedSuperclassjakarta.persistence.Entityjakarta.persistence.Embeddablejakarta.persistence.MappedSuperclass
This change simplifies build configuration and improves the out-of-the-box experience when using Kotlin with JPA frameworks.
Lombok is now in Alpha
Kotlin 1.5.20 introduced the experimental Lombok compiler plugin, which lets you generate and use Java's Lombok declarations in modules that mix Kotlin and Java code.
In 2.3.20, the Lombok compiler plugin has been promoted to Alpha because we plan to make this functionality production-ready, but it's still under development.
Kotlin/JVM
Kotlin 2.3.20 introduces several improvements to Java interoperability. The compiler now recognizes the Vert.x @Nullable annotation for nullability checks. This release also adds support for the Java @Unmodifiable and @UnmodifiableView annotations to treat annotated collections as read-only in Kotlin.
Support for Vert.x @Nullable annotation
Kotlin 2.3.20 adds support for the io.vertx.codegen.annotations.Nullable annotation. The compiler now recognizes this annotation and reports nullability mismatches as warnings by default.
To enforce strict nullability checks and upgrade these warnings to errors, add the following compiler option to your build file:
Support for Java unmodifiable collection annotations
Kotlin 2.3.20 adds support for the org.jetbrains.annotations.Unmodifiable and org.jetbrains.annotations.UnmodifiableView Java annotations.
Starting from Kotlin 2.3.20, collections returned from Java declarations marked with these annotations are treated as read-only in Kotlin. Assigning them to a mutable collection type results in a type mismatch warning. This warning is scheduled to become an error in Kotlin 2.5.0.
Here's an example:
Kotlin/Native
Kotlin 2.3.20 introduces a new experimental interoperability mode for C and Objective-C libraries, a cross-compilation checker, and a new DSL for disabling the compilation cache in Kotlin/Native projects.
Cross-compilation checker
Kotlin 2.3.20 introduces a way to determine if cross-compilation is supported for the given target. This can be useful for third-party plugins that follow the status of compilation tasks.
Generally, Kotlin/Native allows cross-compilation, meaning that any supported host can produce .klib artifacts for supported targets. However, artifact production for Apple targets is still limited if your project uses cinterop dependencies.
The new crossCompilationSupported API now checks whether cross-compilation is supported: the target should be enabled by the host manager, and none of the target's compilations should involve cinterop dependencies. The checker is enabled by default.
For more information on supported targets and hosts, see the Kotlin/Native documentation.
New DSL for disabling compilation cache
Kotlin 2.3.20 comes with a new DSL for disabling the compilation cache in Kotlin/Native projects. It's intended to make the decision of disabling the cache more considered and explicit.
Since disabling the cache makes Kotlin/Native builds significantly slower, it should be used only temporarily and in exceptional cases. That's why disabling the cache is now tied to a specific Kotlin version and must include a reason, which acts as documentation.
If you do need to disable the compilation cache in your project, update the binaries {} block in your Gradle build file as follows:
version– the Kotlin version for which the compilation cache is disabled.reason(mandatory) – the reason why the compilation cache is disabled.issue(optional) – a URL to the corresponding issue in your bug tracker.
The new DSL replaces the deprecated kotlin.native.cacheKind Gradle property. You can safely remove it from your gradle.properties file.
For more tips on improving compilation times, see the Kotlin/Native documentation.
New interoperability mode for C or Objective-C libraries
If you use C or Objective-C libraries in your Kotlin Multiplatform (KMP) libraries or applications, we invite you to test the new interoperability mode and share the results.
In general, Kotlin/Native enables importing C and Objective-C libraries into Kotlin. However, for KMP libraries, this functionality is currently affected by the KMP compatibility issues with older compiler versions.
In other words, if you publish a KMP library compiled with one Kotlin version, importing C or Objective-C libraries might make it impossible to use that Kotlin library in projects with an earlier Kotlin version.
To address this and other issues, the Kotlin team has been revising the interoperability mechanism used under the hood. Starting with Kotlin 2.3.20, you can try the new mode through a compiler option.
How to enable
In your Gradle build file, check whether you have a
cinterops {}block or apod()dependency. If these are present, your project uses C or Objective-C libraries.Ensure your project uses
2.3.20or a later version.In the same build file, add the
-Xccall-modecompiler option to the cinterop tool invocation:kotlin { targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>().configureEach { compilations.configureEach { cinterops.configureEach { extraOpts += listOf("-Xccall-mode", "direct") } } } }Build and test your project as usual by running unit tests, the app, and so on. You can also use the
--continueoption to allow Gradle to continue executing tasks even after failures, helping to find more problems at once.
Report your results
The new interoperability mode is supposed to be a drop-in replacement in most cases. We're planning to eventually enable it by default. But to achieve that, we need to ensure it works as well as possible and test it on a wide range of projects, because:
Some C and Objective-C declarations aren't yet supported in the new mode (mostly because of compatibility issues). We'd like to better understand the real-world impact of this and prioritize future steps accordingly.
There may be bugs or things we haven't considered. Testing languages with numerous interacting features is challenging, and testing the interaction between languages (each with a unique set of features) is even more so.
Help us examine real-world projects and identify challenging cases. Whether you encounter any issues or not, share your results in the comments to in YouTrack.
Kotlin/Wasm
Kotlin 2.3.20 improves the performance of string operations, compilation time, and memory usage. It also adds support for the experimental @nativeInvoke annotation, which lets you call Kotlin objects or classes like JavaScript functions.
Improved string performance
Kotlin/Wasm now uses JS String builtins for operations on kotlin.String values. This allows Kotlin/Wasm to benefit from JavaScript engine string optimizations in browsers and Wasm runtimes supporting the proposal. The optimization applies to operations such as concatenation, interpolation, StringBuilder.append(), and number-to-string conversion.
It results in:
Up to 4.6 times faster string interpolation in targeted benchmarks.
Approximately 5% smaller Wasm binaries in the KotlinConf application build.
Around 1% median improvement across all Wasm benchmarks.
At least 20% faster
StringBuilder.append()and concatenation ofkotlin.Stringinstances in append-heavy workloads.
Improved compilation time and memory optimizations
Kotlin 2.3.20 adds compiler optimizations that significantly reduce memory consumption during compilation, especially in large projects. These optimizations also improve incremental build performance.
In our testing, we observed a 65% improvement in clean build times and a 21% improvement in incremental build times.
Support for @nativeInvoke annotation
Kotlin 2.3.20 introduces support for the @nativeInvoke annotation for the wasmJs target. This annotation allows you to treat a Kotlin object or a class as if it were a function in JavaScript. It's designed to mark a member function of an external declaration (a class or an interface) as the "invoke operator" of a JavaScript object.
When you annotate a function, every call to that function in Kotlin is translated into a direct call of the JavaScript object itself:
This is a temporary solution until stable interoperability between Kotlin/Wasm and JavaScript is designed. It may be modified or removed in future releases, and the compiler reports a warning when you use it.
For more information on the Kotlin/Wasm interoperability with JavaScript, see Interoperability with JavaScript.
Kotlin/JS
Kotlin 2.3.20 makes it possible to implement Kotlin interfaces from TypeScript and introduces experimental support for the SWC compilation platform.
Implementing Kotlin interfaces from JavaScript/TypeScript
Kotlin 2.3.20 lifts the limitation on implementing Kotlin interfaces on the JavaScript/TypeScript side. Previously, it was only possible to export Kotlin interfaces to TypeScript as TypeScript interfaces; implementing them from TypeScript was forbidden.
Now you can implement any Kotlin interface in the following way:
It's also possible to reuse Kotlin default implementations from TypeScript. Even though TypeScript has no concept of default implementations in interfaces, you can work around that by delegating to the DefaultImpls object:
How to enable
In your build file, add the new compiler option:
For more information, see @JsExport annotation.
Support for SWC compilation platform
Starting with Kotlin 2.3.20, Kotlin/JS supports the SWC compilation platform. It helps transpile newer versions of JavaScript/TypeScript code into older and more compatible JavaScript code.
Delegating code conversion to an external tool allows us to reduce the number of variants produced by the Kotlin/JS compiler and speed up compiler modernization, only focusing on supporting the latest JavaScript features. Currently, the latest supported ECMAScript version is still es2015.
Additionally, delegating the transpilation work lets us improve the inlined JavaScript feature. Currently, it only supports ES5 syntax (this will change in 2.4.0). Supporting newer syntax while targeting lower versions would be challenging, as it would require the compiler to transpile the JS code within the inlined JS block itself. With SWC, we'll be able to add modern JS syntax, and the tool will transpile the code to the required syntax for the end-user version.
Migrating to SWC also gives you an opportunity to implement a browserlist-based DSL inside the Kotlin Gradle plugin. This allows you to declare target browsers or environments instead of specific JS versions.
How to enable
In your gradle.properties file, add the following option:
We're planning to stabilize transpilation through SWC in future Kotlin releases. After it becomes the default, the functionality of compiling multiple JS targets will be fully delegated from the Kotlin/JS compiler to the transpiler.
For more information on the SWC platform, see the official documentation.
Gradle
Kotlin 2.3.20 is compatible with new versions of Gradle and includes changes to Kotlin/JVM compilation in the Kotlin Gradle plugin.
Compatibility with Gradle 9.3.0
Kotlin 2.3.20 is fully compatible with Gradle 7.6.3 through 9.3.0. You can also use Gradle versions up to the latest Gradle release. However, be aware that doing so may result in deprecation warnings, and some new Gradle features might not work.
Improvements to binary compatibility validation in KGP
Kotlin 2.2.0 brought support for binary compatibility validation in the Kotlin Gradle plugin for the first time. Kotlin 2.3.20 adds two improvements.
First, the binary compatibility validation Gradle tasks no longer include "Legacy" in their names. We made this change because the old naming convention confused Kotlin developers:
Old name | New name |
|---|---|
|
|
|
|
|
|
The old task names still exist in Kotlin 2.3.20 to ease the transition to the new names.
Second, if you enable binary compatibility validation in your project, Gradle now runs the checkKotlinAbi task automatically when you run the check task. Previously, Gradle didn't run the checkKotlinAbi task, even though the check task is supposed to run all verification tasks. This led to inconsistent behavior in Gradle projects.
Kotlin/JVM compilation uses Build tools API by default
In Kotlin 2.3.20, Kotlin/JVM compilation in the Kotlin Gradle plugin uses the Build tools API (BTA) by default. This change in the internal compilation infrastructure enables faster development of build tool support for the Kotlin compiler.
If you notice any issues, share your feedback in our issue tracker.
Maven
Kotlin 2.3.20 brings an important change to make it easier to set up your Maven projects.
Simplified setup for Kotlin projects
Kotlin 2.3.20 makes it easier to set up Kotlin in Maven projects. Now Kotlin supports the automatic configuration of source roots and Kotlin's standard library.
With the new automatic configuration, when you create a new Kotlin project with the Maven build system or introduce Kotlin to your existing Java Maven project, you don't need to manually specify source root paths or add the kotlin-stdlib dependency in your POM build file.
How to enable
In your pom.xml file, add <extensions>true</extensions> to the <build><plugins> section of the Kotlin Maven plugin:
The new extension automatically:
Registers
src/main/kotlinandsrc/test/kotlindirectories as source roots in case they already exist but are not specified in the plugin configuration.Adds the
kotlin-stdlibdependency in case it's not explicitly defined already.
You can also opt out of the automatic addition of Kotlin's standard library. For that, add the following to the <properties> section:
Note that the property disables all simplified setup features, including the registration of source root paths.
For more information on configuring Kotlin Maven projects, see Configure a Maven project.
Build tools API
Kotlin 2.3.20 introduces more changes for developers who want to integrate their build systems with the Kotlin compiler using the build tools API (BTA).
Improvements to build operations
In this release, the BTA improves how build tools manage build operations. Build operations let build tools interact with the Kotlin compiler. Each build operation is an implementation of the BuildOperation interface.
You can now cancel build operations that implement the CancellableBuildOperation interface with the cancel() function.
The cancel() function works on a "best effort" basis. This means the operation isn't guaranteed to be canceled.
For example:
In addition, build operations are now more robust because you can create them so that they can't be changed once they start. To do this, a build tool must use the builder pattern:
Configure the object using a mutable builder.
Call the
build()function to create an immutable instance of the object.
For example:
Consistent metric collection across build tools
Before Kotlin 2.3.20, the build metrics infrastructure was centered around Gradle, which influenced parts of the infrastructure, like metric names. In addition, not all metrics were available for different compiler execution strategies.
In Kotlin 2.3.20, the BTA provides build-tool-agnostic metric collection for the JVM. The BTA also introduces a consistent set of metrics, regardless of the compiler execution strategy. Metrics that are specific to a particular compilation approach or compiler execution strategy are reported only when applicable. For example, incremental compilation metrics are only available for incremental builds, and daemon-specific metrics are only available when using the Kotlin daemon.
Build tools can now configure a BuildMetricsCollector object for a build operation to capture build metrics that provide the user with insight into build performance:
Easier configuration of compiler plugins by build tools
In Kotlin 2.3.20, the BTA provides a new and simpler way for build tools to configure compiler plugins. This approach allows build tools to propagate the configuration directly to their users.
Instead of configuring compiler plugins through the command line with experimental compiler options, build tools can use the kotlin.buildtools.api.arguments.CommonCompilerArguments.COMPILER_PLUGINS option to configure a list of objects that represent compiler plugin configurations:
Breaking changes and deprecations
This section highlights important breaking changes and deprecations. For more information about deprecations in Kotlin 2.3.0 and 2.3.20, see the Compatibility guide.
In Kotlin 2.3.20, Kotlin/Wasm performs module initialization as part of the Wasm module's instantiation, instead of relying on external JavaScript to call an
_initialize()function afterward. This change makes Kotlin/Wasm more independent and prepares it for the ES module integration proposal.If you use the
@EagerInitializationannotation, related code may fail if it runs before module initialization completes. We recommend avoiding using the@EagerInitializationannotation unless you truly need it.Experimental context receivers are no longer supported and are replaced by context parameters.
This release takes the next step in the deprecation cycle for Intel chip-based Apple targets. Starting with Kotlin 2.3.20, we deprecate the
macosX64,tvosX64, andwatchosX64targets. We plan to completely remove support for these targets in the next Kotlin release.Because many third-party libraries still rely on the
iosX64target, we'll keep it in support tier 3 for now. This means we don't guarantee CI testing, and we may not provide source and binary compatibility between different compiler releases. For more information about support tiers, see Kotlin/Native target support.In Kotlin 2.3.20, stricter dependency matching in Kotlin Multiplatform can cause metadata compilation failures when dependency resolution differs between common and platform source sets. See the issue in YouTrack for details and a workaround.
Documentation updates
We made the following documentation changes in the Kotlin ecosystem:
Kotlin roadmap – See the updated list of Kotlin's priorities on language and ecosystem evolution.
Upgrading to AGP 9 – Explore our advice for migrating your multiplatform projects with Android apps to AGP 9.
Configure CI for a KMP app – Follow a tutorial to configure GitHub Actions for continuous integration in a multiplatform project.
Compose UI previews – Learn how to preview composables in the IDE without running an emulator.
Handling web resources – Find information about how to handle web resources in Compose Multiplatform.
Setting up the viewport – Learn how to use the
ComposeViewport()function to render your UI on an HTML canvas with Compose Multiplatform for web.Custom compiler plugins – Learn how compiler plugins work and what you can do if you can't find one that fits your use case.
Application structure – Choose the best application structure for your Ktor Server app.
HTTP request lifecycle – Learn how to cancel request processing in Ktor when a client disconnects using the HTTP request lifecycle.
Dependency injection – Learn how to configure dependency injection in Ktor Server, with updated guidance and practical examples.
Exposed's Spring Boot integration – Learn how to use Exposed with Spring Boot 3 and 4.