Skip to content

Getting started

This page assumes you have a Compose Multiplatform project. To create one, follow the official JetBrains documentation or run kotlin init compose-multiplatform.

The library is published on Maven Central. The latest release is v0.20.0. Add it to the version catalog:

libs.versions.toml
[libraries]
maplibre-compose = { module = "org.maplibre.compose:maplibre-compose", version = "0.20.0" }

Declare the dependency in the shared source set:

build.gradle.kts
commonMain.dependencies {
implementation(libs.maplibre.compose)
}

Use the same version for the library and for every runtime artifact below.

Complete the section for each target that your app supports.

Alongside the library, add a runtime for one render backend.

build.gradle.kts
androidMain {
dependencies {
runtimeOnly("org.maplibre.compose:maplibre-compose-runtime-vulkan-android:0.20.0")
}
}

Available runtimes:

Render backendRuntime
OpenGLmaplibre-compose-runtime-opengl-android
Vulkanmaplibre-compose-runtime-vulkan-android

Both Android runtimes support armeabi-v7a, arm64-v8a, and x86_64.

Requires iOS 15.5 or later.

The runtime’s system libraries link when Xcode links your app. Add them to your iOS app target’s Other Linker Flags build setting:

-l"c++"
-lz
-framework CoreFoundation
-framework CoreGraphics
-framework CoreText
-framework Foundation
-framework ImageIO
-framework Metal
-framework QuartzCore

Native macOS support is experimental and requires Apple Silicon. Enable org.jetbrains.compose.experimental.macos.enabled=true in gradle.properties.

Inside the native Compose Window, wrap your content with ProvideMapPresentationHost(window):

@Composable
fun NativeMacWindowContent(window: NSWindow) {
ProvideMapPresentationHost(window) { App() }
}

Desktop requires Java 25 or later.

Alongside the library, add a runtime for your platform and one render backend.

build.gradle.kts
sourceSets {
val jvmMain by getting {
dependencies {
implementation(compose.desktop.currentOs)
implementation("org.maplibre.compose:maplibre-compose:0.20.0")
// Linux x64 with Vulkan, for example.
runtimeOnly("org.maplibre.compose:maplibre-compose-runtime-vulkan-linux-x64:0.20.0")
}
}
}

Available runtimes (package one backend for each target platform):

PlatformMetalVulkanOpenGL
Linux x64—maplibre-compose-runtime-vulkan-linux-x64maplibre-compose-runtime-opengl-linux-x64
Linux arm64—maplibre-compose-runtime-vulkan-linux-arm64maplibre-compose-runtime-opengl-linux-arm64
macOS arm64maplibre-compose-runtime-metal-macos-arm64maplibre-compose-runtime-vulkan-macos-arm64maplibre-compose-runtime-opengl-macos-arm64
Windows x64—maplibre-compose-runtime-vulkan-windows-x64maplibre-compose-runtime-opengl-windows-x64
Windows arm64—maplibre-compose-runtime-vulkan-windows-arm64maplibre-compose-runtime-opengl-windows-arm64

Linux OpenGL also requires a Vulkan driver. Linux and Windows OpenGL require drivers with external-memory support.

On desktop, a ComposeMapPresentationHost supplies the window’s graphics context. For Java AWT windows, use rememberAwtComposeMapPresentationHost. A window that draws Compose another way creates its host with the factory for its operating system and graphics API, such as ComposeMapPresentationHost.macosMetal; the API reference lists them and what their callbacks must do. These factories take Skiko types, which may change in any minor release, so they require opt-in to ExperimentalMaplibreComposeApi.

Main.kt
fun main() {
singleWindowApplication {
ProvideMapPresentationHost(host = rememberAwtComposeMapPresentationHost(window)) {
App()
}
}
}

A custom Metal host supplies its window callbacks:

@OptIn(ExperimentalMaplibreComposeApi::class)
fun customMetalHost(
gpuContext: () -> MetalComposeGpuContext?,
runOnGpuThread: (Runnable) -> Unit,
): ComposeMapPresentationHost =
ComposeMapPresentationHost.macosMetal(
description = "my Metal window",
gpuContext = gpuContext,
runOnGpuThread = runOnGpuThread,
)

Enable native access when you run the desktop app:

build.gradle.kts
compose.desktop {
application {
jvmArgs += "--enable-native-access=ALL-UNNAMED"
}
}

Signing an application can modify LWJGL’s native libraries, particularly when re-signing macOS dylibs. This can cause LWJGL to print Incompatible Java and native library versions detected even though the libraries load and the map works normally.

If signing changes these libraries and triggers the warning, add -Dorg.lwjgl.util.NoHashChecks=true to compose.desktop.application.jvmArgs in build.gradle.kts.

See LWJGL discussion #1007.

Compile the JS target to ES modules. Non-ESM builds are not supported.

build.gradle.kts
kotlin {
js {
useEsModules()
browser()
}
}

Install the browser graphics integration inside onWasmReady, before Compose starts.

main.kt
fun main() {
onWasmReady {
installMaplibreCompose()
ComposeViewport(document.body!!) { App() }
}
}

In your Composable UI, add a map:

App.kt
@Composable
fun MyApp() {
MaplibreMap()
}

When you run your app, the map shows the default demotiles style. To load a full-featured style, proceed to Styling.

Snapshot builds of main are available from Central Portal Snapshots. This site documents the latest release, which may not match the snapshot. If you use snapshots, read the documentation for the latest main instead.

Add the snapshot repository, then set the catalog version to v0.20.1-SNAPSHOT.

settings.gradle.kts
repositories {
maven {
name = "Central Portal Snapshots"
url = uri("https://central.sonatype.com/repository/maven-snapshots/")
mavenContent { snapshotsOnly() }
content {
includeGroup("org.maplibre.compose")
includeGroup("org.maplibre.nativeffi")
}
}
}
libs.versions.toml
[libraries]
maplibre-compose = { module = "org.maplibre.compose:maplibre-compose", version = "0.20.1-SNAPSHOT" }