Getting started
You need a Compose Multiplatform project. To create one, follow
the JetBrains guide or run kotlin init compose-multiplatform.
Add the library
Section titled “Add the library”The library is on Maven Central. The latest release is v0.20.0. Add it to your version catalog:
[libraries]maplibre-compose = { module = "org.maplibre.compose:maplibre-compose", version = "0.20.0" }Then add it to the shared source set:
commonMain.dependencies { implementation(libs.maplibre.compose)}dependencies: - $libs.maplibre.composeSet up each target
Section titled “Set up each target”Complete the section for each target that your app supports.
Some targets need a runtime artifact, which contains the native map engine for one graphics API. The steps below pick one runtime per target; Platform setup lists the other options.
Android
Section titled “Android”Add the Vulkan runtime to the Android app:
androidMain.dependencies { runtimeOnly("org.maplibre.compose:maplibre-compose-runtime-vulkan-android:0.20.0")}dependencies: - //shared - org.maplibre.compose:maplibre-compose-runtime-vulkan-android:0.20.0: scope: runtime-onlyiOS needs no runtime artifact. The app must target iOS 15.5 or later.
Add these lines to Other Linker Flags in your iOS app target’s build settings:
-l"c++"-lz-framework CoreFoundation-framework CoreGraphics-framework CoreText-framework Foundation-framework ImageIO-framework Metal-framework QuartzCoreDesktop (JVM)
Section titled “Desktop (JVM)”Desktop apps run on Java 25 or later. These steps use a Compose Desktop window, which runs on AWT. Platform setup covers other windows, including Nucleus, which we recommend.
Add the runtime for each operating system and CPU you ship, and
kotlinx-coroutines-swing, which supplies the main thread that maps deliver
their events on. This example is for Linux on x64:
jvmMain.dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.11.0") runtimeOnly("org.maplibre.compose:maplibre-compose-runtime-vulkan-linux-x64:0.20.0")}dependencies: - //shared - org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.11.0 - org.maplibre.compose:maplibre-compose-runtime-vulkan-linux-x64:0.20.0: scope: runtime-onlyThe map engine calls native code through Java’s foreign function API, so the
JVM must start with --enable-native-access=ALL-UNNAMED:
compose.desktop { application { jvmArgs += "--enable-native-access=ALL-UNNAMED" }}kotlin run --module desktop-app --jvm-args="--enable-native-access=ALL-UNNAMED"Pass the same flag when you start a packaged JAR:
java --enable-native-access=ALL-UNNAMED -jar desktop-app-jvm-executable.jar.
A map draws with the graphics context of its window. Wrap the content of each
window that shows a map in
ProvideMapPresentationHost, and pass it
a host from rememberAwtComposeMapPresentationHost:
fun main() { singleWindowApplication { ProvideMapPresentationHost(host = rememberAwtComposeMapPresentationHost(window)) { App() } }}Native macOS
Section titled “Native macOS”Native macOS (the macosArm64 target) is experimental in Compose. Turn it on in
gradle.properties:
org.jetbrains.compose.experimental.macos.enabled=trueWrap the content of each Window that shows a map in
ProvideMapPresentationHost:
fun openMapWindow() { Window("My app", DpSize(800.dp, 600.dp)) { ProvideMapPresentationHost(window) { App() } }}Web (JS)
Section titled “Web (JS)”Build the JS target as ES modules:
kotlin { js { useEsModules() browser() }}product: type: kmp/lib platforms: [jvm, android, iosArm64, iosSimulatorArm64, js]product: js/app
dependencies: - //sharedCall installMaplibreCompose inside onWasmReady, before
ComposeViewport. Without it, maps load but never appear on screen.
fun main() { onWasmReady { installMaplibreCompose() ComposeViewport(document.body!!) { App() } }}Display a map
Section titled “Display a map”Add a map to your shared UI:
@Composablefun MyMap() { val mapState = rememberMapState( baseStyle = BaseStyle.Uri("https://tiles.openfreemap.org/styles/liberty"), initialCameraPosition = CameraPosition(center = Position(latitude = 45.521, longitude = -122.675), zoom = 13.0), ) MaplibreMap(state = mapState)}rememberMapState creates the map’s state. baseStyle loads a
style from a URL. The style decides what the map shows and how it looks. This
example uses the free OpenFreeMap Liberty style. If you leave out
baseStyle, the map shows the MapLibre demo style, which has
little detail. initialCameraPosition is where the map opens: here, downtown
Portland at zoom 13.
MaplibreMap fills all the space its parent gives it. Users can
pan, zoom, rotate, and tilt the map with touch gestures or a mouse.
Next, choose a style or move the camera.