GLMap brings native maps, search and routing to React Native and Expo apps on Android and iOS. Embed an interactive map, draw markers and routes, search for places, and use downloaded data offline. Search and routing also work without a map view.
This repository contains four npm packages and a demo catalog with 20 API examples.
- React Native 0.86, Expo 57 and React 19. The example pins React Native 0.86.3.
- An Expo development build or a React Native app with Expo Modules installed. Expo Go and web are not supported by these native modules.
- Android API 24 or later, Java 17 and NDK 29.
- iOS 16.4 or later, Xcode and CocoaPods on macOS.
- A suitable GLMap API key and network access for online maps, search, routing and downloads. Offline operations need data covering the requested area.
The packages and demo pin the released native GLMap SDK 2.2.0 from the public Maven repository on Android and GLMapSwift on iOS. The npm packages are versioned independently of the native SDK.
Run npm install, regenerate the host with npx expo prebuild and rebuild the
native app; a JavaScript/OTA update alone cannot update native frameworks. Back
up any custom native-project changes before regeneration. Keep Core, Map, Search
and Route on the same native release. Initialize Core before mounting a map or
using headless services. Vector-layer creation succeeds only after native
Ready; superseded/cancelled updates reject with cancelled, and failed updates
with sdk_error. Ready does not certify presentation of a rendered frame.
From an Expo app, install Map, Core and the development client:
npx expo install @globus-software/glmap@beta @globus-software/glmap-core@beta expo-dev-clientMap depends on Core. Listing Core directly also lets your app import its initialization API. Add Search or Route separately when you need those APIs. For an existing React Native app, first follow the Expo Modules setup.
Add the Map config plugin to your existing app.json:
{
"expo": {
"plugins": ["@globus-software/glmap"]
}
}List a plugin for every feature package you install. For example, an app using
Map and Search lists @globus-software/glmap and @globus-software/glsearch.
Feature plugins include Core setup; a Core-only app lists
@globus-software/glmap-core instead.
The plugins configure native integration, framework embedding and uncompressed map/font assets. On iOS, Core owns the shared Swift conveniences and resources; feature packages add only their own frameworks. Regenerate and rebuild the native app after adding or removing packages or plugins:
npx expo prebuildCommit or back up your own native-project changes before regenerating them. For apps that maintain native projects manually, apply the corresponding config-plugin changes to the host; JavaScript imports alone do not configure native dependencies.
iOS host ownership: the SDK plugins do not change your AppDelegate,
UIApplicationSceneManifest, or location permission text. Configure the scene
lifecycle appropriate to your Expo version and application (including scene
support when targeting iOS 27); GLMap does not migrate it for you. The demo's
explicit with-expo-scenes plugin adapts its pinned Expo blank template and is
not part of the SDK plugins.
If your app calls Core's foreground-location APIs, add your own explanation to
ios.infoPlist in app.json, for example:
{
"NSLocationWhenInUseUsageDescription": "Show your position on the map while you use the app."
}Map display, search and routing without device location do not require that permission. Preserve any existing location wording and custom scene configuration. When upgrading a host generated with an earlier GLMap plugin, review its native changes: the plugin does not undo previously written AppDelegate or Info.plist changes. Restore your app's settings from version control, or regenerate only when all native customizations are represented in your app config/plugins.
Use this as App.tsx in an Expo app with a single root component:
import React, { useEffect, useRef, useState } from 'react';
import { Text, View } from 'react-native';
import { GLMapSdk } from '@globus-software/glmap-core';
import { GLMapView, type GLMapViewRef } from '@globus-software/glmap';
export default function App() {
const map = useRef<GLMapViewRef>(null);
const [ready, setReady] = useState(false);
const [failure, setFailure] = useState('');
useEffect(() => {
let active = true;
async function initialize() {
try {
await GLMapSdk.initialize(process.env.EXPO_PUBLIC_GLMAP_API_KEY ?? '');
await GLMapSdk.setTileDownloadingAllowed(true);
if (active) setReady(true);
} catch (error) {
if (active) setFailure(String(error));
}
}
void initialize();
return () => { active = false; };
}, []);
if (failure) return <Text>{failure}</Text>;
if (!ready) return <Text>Loading map…</Text>;
return (
<View style={{ flex: 1 }}>
<GLMapView
ref={map}
style={{ flex: 1 }}
onMapReady={() => {
void map.current?.moveCamera(
{ center: { latitude: 42.4341, longitude: 19.26 }, zoom: 13 },
null,
).catch(error => setFailure(String(error)));
}}
/>
<Text style={{ textAlign: 'center' }}>© OpenStreetMap contributors</Text>
</View>
);
}Initialize Core before rendering a map or using the services. onMapReady runs
when the native view is attached and sized. A view ref and its drawing handles
belong to that mounted view; do not reuse them after unmounting.
Create .env.local in your app and add it to .gitignore:
EXPO_PUBLIC_GLMAP_API_KEY=your-demo-keyBuild and launch on an Android emulator/device or an iOS simulator/device:
npx expo run:android
# Or, on macOS:
npx expo run:iosExpo's EXPO_PUBLIC_ values are embedded in the JavaScript bundle. Use an
appropriate client key; do not put server secrets there or commit keys.
This example uses online tiles. For offline data registration and downloads,
see the Core guide.
Clone the repository and install its workspace dependencies:
git clone https://github.com/GLMap/react-native.git glmap_rn
cd glmap_rn
npm install
cd example
npx expo prebuildBuild and open GLMap React Native Demo:
npx expo run:android
# Or, on macOS:
npx expo run:iosThe catalog is the default entry point; no mode flag is needed. Its screens use
the same TypeScript/React implementation on Android and iOS. Expo generates the
platform hosts under example/android/ and example/ios/.
The catalog also has Lifecycle checks and API checks actions. Both exercise
the public SDK's GLMapView, not a separate test map. Benchmarks are an explicit
opt-in mode; see the demo code guide.
To start Metro separately for an installed development build, run npm run demo
from example/.
Use Search with its offline option to explore the bundled Montenegro data.
Online features and downloads require a suitable key. Enter one with the
catalog's API key button for the current session, or create the ignored
example/config/local.json before running the helper:
{"GLMAP_API_KEY":"your-demo-key"}To load that configuration, run
node scripts/demo-env.mjs npx expo run:android (or expo run:ios) from example/.
The helper embeds the key in the bundle; a key entered through the UI is not
persisted. The bundled map supports display and search, not offline road routing
or terrain; download navigation/elevation data for those features.
See the demo code guide for the startup flow, shared UI, feature screens and lifecycle conventions.
Use only the modules your app needs. Map, Search and Route depend on Core, not on one another; Search and Route do not pull in the map renderer.
| npm package | Purpose |
|---|---|
| @globus-software/glmap-core | Initialization, shared types, datasets, downloads and foreground location |
| @globus-software/glmap | Map view, camera, gestures, vectors and drawing handles |
| @globus-software/glsearch | Search, autocomplete and map-object queries |
| @globus-software/glroute | Road routing, custom routes, maneuvers and tracking |
See SOURCE.md for package structure and API development.
See LICENSE.txt and each package's license. Native SDK and map-data terms also apply; bundled map data is © OpenStreetMap contributors.