---
title: Announcing the Capacitor MapLibre Plugin
description: Our new free Capacitor MapLibre plugin renders native maps on Android, iOS, and Web with markers, polylines, GeoJSON layers, and user location.
date:
  created: 2026-08-28
  updated: 2026-08-28
authors:
  - robingenz
categories:
  - Announcements
  - Capacitor
  - SDKs
links:
  - Capacitor MapLibre: sdks/capacitor/maplibre.md
faq: true
---

# Announcing the Capacitor MapLibre Plugin

Maps in a Capacitor app have long meant one thing: Google Maps, along with the billing account it requires before the first tile loads. Today we're announcing the [Capacitor MapLibre plugin](../../sdks/capacitor/maplibre.md), the first native [MapLibre](https://maplibre.org/){:target="_blank"} integration for Capacitor. It renders maps with the native MapLibre SDKs on Android and iOS and with MapLibre GL JS on the Web, supports markers, polylines, GeoJSON layers, and user location, and requires no vendor account or API key from the plugin itself. It's free, and you can install it from npm today.

<!-- more -->

<div class="capawesome-z29o10a">
  <a href="https://capawesome.io/" target="_blank">
    <img alt="Build and deploy your Capacitor app with Capawesome Cloud" src="https://capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.png?t=1" />
  </a>
</div>

**Key takeaways:**

- `@capawesome/capacitor-maplibre` is a free plugin that renders native MapLibre maps on Android and iOS and MapLibre GL JS maps on the Web.
- No Google billing account and no API key are required by the plugin; map styles and tiles come from a provider of your choice, some free, some with their own key.
- Markers support custom icons, animated updates, and dragging (Android and Web); polylines and GeoJSON sources with styled line, fill, and circle layers cover routes and areas.
- The native map renders behind the web view; the map element and its ancestors need transparent backgrounds, while other DOM elements can overlay the map as usual.
- Multiple maps can run at the same time, each addressed by its `mapId`, and the native view follows its element through scrolling and resizing automatically.
- Requires Capacitor 8 or later; offline tile management is not part of this version.

## Why a Capacitor MapLibre Plugin?

Until now, showing a native map in a Capacitor app essentially required `@capacitor/google-maps`, and with it a Google Maps Platform account with billing enabled. Since Google dropped the monthly $200 credit in 2025 in favor of tiered subscriptions, that dependency has a price tag attached that many apps never needed for what is, in the end, a map with some markers on it.

MapLibre is the open-source alternative: a BSD-licensed map renderer with native SDKs for Android and iOS and a JavaScript library for the browser, maintained by a community rather than a vendor. What was missing was a Capacitor integration that uses those native SDKs instead of running the JavaScript renderer inside the web view. This plugin is that integration, and because it builds on an open stack, there is no billing account between you and your first map. For a detailed comparison with `@capacitor/google-maps`, including the Android z-order workarounds it requires, read [A Google Maps Alternative for Capacitor Apps](./alternative-to-the-capacitor-google-maps-plugin.md).

One honest note upfront: this is an unofficial plugin, not affiliated with or endorsed by the MapLibre organization.

## How the Native Map Rendering Works

On Android and iOS, the map is a native view rendered behind the web view, positioned and sized by an empty element in your DOM. Your app fulfills a small contract: the map element stays empty, and it and every ancestor covering the map region use `background: transparent`, because otherwise the web view paints over the native map.

That architecture has a pleasant consequence. Any DOM element that isn't an ancestor of the map element renders above the map, so floating action buttons, bottom sheets, and dialogs work exactly as they do everywhere else in your app. The plugin also keeps the native view in sync with the element's position and size automatically, including while the page scrolls or resizes.

## Usage

Here's the path from an empty `div` to a map with markers, routes, and live user location.

### Create a map

Define the position and size of the map with an empty element and a transparent background, then create the map with [`createMap(...)`](../../sdks/capacitor/maplibre.md#createmap):

```typescript
import { MapLibre } from '@capawesome/capacitor-maplibre';

const createMap = async () => {
  await MapLibre.createMap({
    center: { latitude: 48.137154, longitude: 11.576124 },
    elementId: 'map',
    mapId: 'my-map',
    styleUrl: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
    zoom: 12,
  });
};
```

Every method takes the `mapId`, so you can create and control several maps at once. Camera movement works the same way: [`setCamera(...)`](../../sdks/capacitor/maplibre.md#setcamera) animates center, zoom, bearing, and pitch, and [`fitBounds(...)`](../../sdks/capacitor/maplibre.md#fitbounds) frames a bounding box with padding.

### Add markers and polylines

Markers take custom icons with configurable anchor, size, opacity, and rotation, and [`updateMarkerById(...)`](../../sdks/capacitor/maplibre.md#updatemarkerbyid) moves them with a smooth animation, which is exactly what a delivery or fleet tracking app needs:

```typescript
import { MapLibre, MarkerIconAnchor } from '@capawesome/capacitor-maplibre';

const addAndMoveMarker = async () => {
  await MapLibre.addMarker({
    mapId: 'my-map',
    marker: {
      coordinates: { latitude: 48.137154, longitude: 11.576124 },
      iconAnchor: MarkerIconAnchor.Center,
      iconSize: { height: 32, width: 32 },
      iconUrl: 'https://example.com/marker.png',
      id: 'my-marker',
    },
  });
  await MapLibre.updateMarkerById({
    animate: true,
    animationDuration: 1000,
    coordinates: { latitude: 48.370545, longitude: 10.89779 },
    mapId: 'my-map',
    markerId: 'my-marker',
    rotation: 90,
  });
};
```

Routes and tracks are drawn with [`addPolyline(...)`](../../sdks/capacitor/maplibre.md#addpolyline), with color, width, and opacity per line. Markers can also be made draggable on Android and Web.

### Render GeoJSON data

For anything beyond individual markers and lines, add a GeoJSON source from data or a URL and style it with line, fill, or circle layers:

```typescript
import { LayerType, MapLibre } from '@capawesome/capacitor-maplibre';

const addGeoJson = async () => {
  await MapLibre.addGeoJsonSource({
    mapId: 'my-map',
    sourceId: 'my-source',
    url: 'https://example.com/routes.geojson',
  });
  await MapLibre.addLayer({
    layerId: 'my-layer',
    mapId: 'my-map',
    paint: { lineColor: '#3887be', lineWidth: 4 },
    sourceId: 'my-source',
    type: LayerType.Line,
  });
};
```

This is the data-driven path for field service areas, recorded tracks, or anything your backend already stores as GeoJSON.

### Show the user's location

[`enableUserLocation(...)`](../../sdks/capacitor/maplibre.md#enableuserlocation) displays the user on the map and optionally follows them, with tracking modes for course and heading. Request the location permission first:

```typescript
import { MapLibre, UserTrackingMode } from '@capawesome/capacitor-maplibre';

const enableUserLocation = async () => {
  let status = await MapLibre.checkPermissions();
  if (status.location === 'prompt') {
    status = await MapLibre.requestPermissions();
  }
  if (status.location !== 'granted') {
    return;
  }
  await MapLibre.enableUserLocation({
    mapId: 'my-map',
    trackingMode: UserTrackingMode.Follow,
  });
};
```

Events round the API off: `mapClick`, `markerClick`, and `cameraIdle` listeners keep your app in sync with what the user does on the map.

## Where Do Map Styles Come From?

The plugin renders any style that follows the [MapLibre Style Spec](https://maplibre.org/maplibre-style-spec/){:target="_blank"}, loaded from a URL or a JSON string and swappable at runtime. The style, not the plugin, decides where tiles come from, which is why "no API key required by the plugin" is not the same claim as "free tiles": free providers such as [OpenFreeMap](https://openfreemap.org/){:target="_blank"} and [CARTO basemaps](https://github.com/CartoDB/basemap-styles){:target="_blank"} exist, while commercial providers such as MapTiler use their own API keys. Whichever you choose, follow the provider's attribution requirements and terms of service. The default demo style is a test style only; pick a real provider before shipping.

## FAQ

### Is there a MapLibre plugin for Capacitor?

Yes. The [Capacitor MapLibre plugin](../../sdks/capacitor/maplibre.md) is the first native MapLibre integration for Capacitor: it renders maps with the native MapLibre SDKs on Android and iOS and with MapLibre GL JS on the Web, and it's free.

### Do I need an API key to show a map?

Not for the plugin itself. MapLibre is open source and no vendor account is required. Your chosen style and tile provider may require its own key, though free providers exist.

### Why is my map not visible?

The native map renders behind the web view, so the map element and every ancestor covering the map region must have a transparent background. A single opaque `background` on `body` or a wrapper is enough to hide the map.

### Does the plugin work offline?

No. Styles, fonts, sprites, and tiles are loaded from the network. Offline tile management is not part of this version of the plugin.

### Can I use the plugin with Ionic, React, Vue, or Angular?

Yes. The plugin is framework-agnostic and works in any Capacitor app, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects.

## Availability

The Capacitor MapLibre plugin is free and available today for Capacitor 8 and later. To install it, please refer to the [Installation](../../sdks/capacitor/maplibre.md/#installation) section in the plugin documentation.

New plugins and notable releases are announced in the Capawesome newsletter first.

[Subscribe to the Capawesome Newsletter](https://capawesome.io/newsletter/){ .md-button .md-button--primary }

## Conclusion

Native map rendering in Capacitor no longer requires a Google billing account. The Capacitor MapLibre plugin brings the open-source MapLibre stack to Android, iOS, and the Web behind one API, with markers, polylines, GeoJSON layers, user location, and an architecture that lets your existing DOM overlays sit on top of a native map.

**Further reading:**

- [A Google Maps Alternative for Capacitor Apps](./alternative-to-the-capacitor-google-maps-plugin.md) — the full comparison with `@capacitor/google-maps`
- [API Reference](../../sdks/capacitor/maplibre.md#api) — every method, option, and event

**Missing a feature?** [Create a feature request](https://github.com/capawesome-team/capacitor-plugins/issues/new/choose){:target="_blank"} in our GitHub repository.

If you have any questions, join us on the [Capawesome Discord server](https://discord.gg/VCXxSVjefW){:target="_blank"}. To stay updated on the latest news, subscribe to the [Capawesome newsletter](https://capawesome.io/newsletter/){:target="_blank"}.
