Library / SDK
rnmapbox/maps avatar
rnmapbox/maps

@rnmapbox/maps: Mapbox Maps for React Native, and What It Costs You

A Mapbox react native module for creating custom maps

2,915 stars947 forksKotlinMIT

At a glance

What is it?
@rnmapbox/maps wraps the native Mapbox Maps SDK v11 for iOS and Android behind React Native components. It is the right tool when you need Mapbox styling and Mapbox data, and it is not available in Expo Go.
Who is it for?
Adopt @rnmapbox/maps if you already pay for Mapbox and need its styles, terrain, or offline packs inside a React Native app, and you accept that releases are community-driven and that the install is a native build, not an npm-only step. Do not adopt it if you cannot obtain a Mapbox access token, if you depend on Expo Go, or if you want a fully permissive tile stack you control.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What @rnmapbox/maps actually solves

Rendering a Mapbox map in a React Native app is not a JavaScript problem. The tiles, styles, terrain, and offline packs come from the native Mapbox Maps SDK for iOS and for Android, and those SDKs are written in Swift and Kotlin. @rnmapbox/maps is the bridge: it exposes the native SDK as React Native components so you write JSX instead of platform code.

The README describes it as "a community-supported, open-source React Native library for building maps with the Mapbox Maps SDK for iOS and the Mapbox Maps SDK for Android." That word community matters. This is not an official Mapbox product. The repository carries an open call for additional maintainers in its discussion thread, which tells you the bus factor is a live concern rather than a theoretical one.

The audience is narrow but real: teams that have already chosen Mapbox for its styles and data, are building a cross-platform mobile app in React Native, and would otherwise have to write and maintain two native map integrations by hand. If any of those three conditions is false, the library is probably the wrong layer for you.

How the bridge is structured

The library mirrors the native SDK's object model rather than inventing its own. The README's component list splits cleanly into four groups, and that split is the whole architecture.

Sources describe where geometry and imagery come from: VectorSource, ShapeSource, RasterSource, RasterDemSource. Layers describe how that data is painted: FillLayer, LineLayer, SymbolLayer, CircleLayer, HeatmapLayer, FillExtrusionLayer, RasterLayer, BackgroundLayer, SkyLayer, ModelLayer. Components describe things that are not part of the style graph: MapView, Camera, MarkerView, PointAnnotation, Callout, UserLocation, LocationPuck, Images, Models, Light, StyleImport, StyleSheet. Terrain and Atmosphere are separate, as are OfflineManager and SnapshotManager.

If you have used Mapbox GL JS, the source and layer split will be familiar, and that familiarity is the point. Styling decisions live in a style specification, not in React props, so a symbol layer's paint properties are declared the way the native SDK expects them. The style-spec directory at the repository root and the fetch:style:spec script in package.json exist to keep that specification in sync.

The Camera component is where the React model diverges most from the native one. You drive the viewport by rendering a Camera with the properties you want rather than by calling imperative methods, which means camera state participates in the normal React render cycle. For animated transitions this is convenient; for tightly sequenced imperative camera work it can be awkward, and the docs for Camera are the place to check before you design around it.

Installing @rnmapbox/maps and rendering your first map

The README states the prerequisites plainly: a Mapbox account and access token, Node and npm, and React Native 0.79 or higher. It then points to the installation instructions at rnmapbox.github.io/docs/install, with separate guides in ios/install.md and android/install.md. There is no npm-only path. You are adding native code to both platforms.

Start by installing the package:

bash
npm install @rnmapbox/maps

Then follow the platform guide for your target. The README does not inline the native steps, so treat ios/install.md and android/install.md as required reading rather than optional. Once the native side is wired up, running the app uses the standard React Native commands the README lists:

bash
npm run ios
npm run android

The minimal map is short. The README gives this example, which sets the access token at module scope and renders a MapView inside a sized container:

js
import React from 'react';
import { StyleSheet, View } from 'react-native';
import Mapbox from '@rnmapbox/maps';

Mapbox.setAccessToken('<YOUR_ACCESSTOKEN>');

const App = () => {
  return (
    <View style={styles.page}>
      <View style={styles.container}>
        <Mapbox.MapView style={styles.map} />
      </View>
    </View>
  );
};

The container in that example is 300 by 300 with the map filling it, so you should see a square map on a plain background. If you see an empty grey box instead, the token is the first thing to check, because Mapbox styles will not load without a valid one.

If you use Expo, the README is explicit: the package is not available in the Expo Go app, and you need a custom dev client as described in plugin/install.md. That single sentence rules out a large class of quick prototypes. For tests, the package ships a Jest setup file, wired in through setupFilesAfterEach in your Jest config:

json
"jest": {
  "preset": "react-native",
  "setupFilesAfterEnv": ["@rnmapbox/maps/setup-jest"],
  "transformIgnorePatterns": [
      "node_modules/(?!(...|@rnmapbox))"
  ]
}

The token, the account, and the limits that follow

Every map this library draws is billed against a Mapbox account, and the README's prerequisite section is a single instruction: sign up to Mapbox to get an access token. That dependency is not incidental. It determines your pricing, your terms of service, and what happens to your app if your account has a problem.

It also changes what "open source" means here. The library is MIT licensed, but the native SDKs it binds to are not, and neither is the tile service behind them. You can read and modify the bridge. You cannot swap in a different tile provider without leaving the library's core premise.

The offline story has the same shape. OfflineManager and SnapshotManager are documented components, so offline packs and static images are supported features rather than afterthoughts, but they operate on Mapbox data under Mapbox's offline terms. The README does not document the storage limits or the expiry rules for downloaded regions; those live in Mapbox's own documentation, not in this repository.

There is also an operational risk that the README acknowledges indirectly. A community-maintained bridge to a commercial SDK means the maintainers are tracking two upstream release trains, and the version history shows the cadence: v10.3.3, v10.3.4, and v10.3.5 shipped within about ten days of each other in July 2026. That is a good sign for responsiveness and a bad sign for anyone who pins a version and stops paying attention.

Where it breaks, and when it is the wrong tool

The most common failure is the one the search data keeps returning to: "rnmapbox maps native code not available." That error means the JavaScript side loaded but the native module did not, which happens when the package is installed without rebuilding the native app, or when it is run inside Expo Go. The fix is a rebuild or a custom dev client, not a code change, and no amount of editing JSX will resolve it.

Beyond that, three situations argue against this library. First, if your app must run in Expo Go, stop here. Second, if your maps are simple enough that a static image or a WebView-based map would do, you are paying a native dependency cost for very little. Third, and most importantly, if you need a tile stack you fully control, this is not that library. The topics list mentions maplibre, but the README's supported implementations section says only that Mapbox Maps SDK v11 is supported, so do not assume a drop-in MapLibre swap from this document alone.

There is a fourth, softer failure mode worth naming. The repository has an active call for additional maintainers. That is not a reason to avoid the library today, and the last push was on 2026-09-21, which is days before this writing. It is a reason to check whether your team is prepared to read Kotlin and Swift if a fix you need does not land upstream.

How it compares to MapLibre-based React Native maps

The real alternative for most teams is a React Native map library built on MapLibre rather than the Mapbox SDK. The difference is not cosmetic. MapLibre is a fork of the open-source Mapbox GL codebase, so a MapLibre-based library gives you the same source-and-layer styling model without a Mapbox account, without Mapbox billing, and without the native Mapbox SDK as a binary dependency.

What you give up is the Mapbox ecosystem. Mapbox's hosted styles, its terrain and atmosphere data, its offline pack service, and the specific rendering behaviour of SDK v11 all come from Mapbox, and a MapLibre-based library will not reproduce them identically. You would supply your own tile source or a third-party one, and you would own the styling decisions that Mapbox currently makes for you.

For a team already paying Mapbox, the trade is usually not worth making: you would be rewriting your style definitions to save a dependency you have already bought. For a team that has not committed to Mapbox yet, the calculus is different, and it is worth deciding before you write layer definitions rather than after. The source and layer model is portable in principle, but the style specification details are where the porting cost actually lives.

Maintenance, licensing, and what an upgrade costs

The repository is not archived, and the last push was on 2026-09-21. Releases in the v10.3.x line arrived in July 2026, so the project is moving, but the README's own call for maintainers is the honest signal about capacity. Plan for the possibility that a bug you file sits for a while.

The package is MIT licensed, and the LICENSE.md file at the repository root is the authoritative text. That covers the library. It does not cover the Mapbox native SDKs or the Mapbox services you call with your access token, which carry their own separate terms. Nothing here is legal advice; if your organisation has questions about redistributing an app that embeds the Mapbox SDK, those questions belong with Mapbox's terms, not this repository's licence.

Upgrade cost is dominated by the native rebuild, not the JavaScript. Because the library tracks Mapbox Maps SDK v11 and the package ships android, ios, cpp, and a podspec, a version bump usually means re-running pod install on iOS and a Gradle sync on Android, plus whatever the upstream SDK changed. The repository keeps a CHANGELOG.md and a RELEASE.md at the root, and those are the files to read before bumping. The README also carries a README-v10.md, which suggests the v10 line has its own migration notes worth checking if you are coming from an earlier major version.

Editorial conclusion

Adopt @rnmapbox/maps if you already pay for Mapbox and need its styles, terrain, or offline packs inside a React Native app, and you accept that releases are community-driven and that the install is a native build, not an npm-only step. Do not adopt it if you cannot obtain a Mapbox access token, if you depend on Expo Go, or if you want a fully permissive tile stack you control. Before committing, verify three things on your own checkout: that your React Native version is 0.79 or higher, that the platform install guide in ios/install.md or android/install.md matches your build setup, and that the access token you intend to ship is scoped to the platforms you actually build for.

Frequently asked questions

Is @rnmapbox/maps free to use?

The library itself is MIT licensed, but it wraps the native Mapbox Maps SDK and requires a Mapbox access token from a Mapbox account, so your use of the maps themselves is governed by Mapbox's terms rather than the library's licence.

What is @rnmapbox/maps used for?

It is a React Native library for building maps using the Mapbox Maps SDK for iOS and Android, exposing components such as MapView, Camera, sources like ShapeSource and VectorSource, and layers like FillLayer and SymbolLayer.

Does @rnmapbox/maps work with Expo?

The README states the package is not available in the Expo Go app, and that you can use it with custom dev clients as described in plugin/install.md.

Which React Native version does @rnmapbox/maps require?

The README lists React Native 0.79 or higher as a dependency, alongside Node and npm.

How do I fix the @rnmapbox/maps native code not available error?

That message means the JavaScript side loaded without the native module, which happens when the package is installed without rebuilding the native app or when it is run in Expo Go. The README's install guides for iOS and Android cover the native setup steps.

Which Mapbox SDK version does @rnmapbox/maps support?

The README states that Mapbox Maps SDK v11 is supported, with separate setup guides in ios/install.md and android/install.md.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. rnmapbox/maps on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rnmapbox-maps.svg)](https://hysenlabs.com/projects/rnmapbox-maps)