# react-native-map-link: opening a location in whichever map app the user has

> react-native-map-link is a React Native library that opens a location in the map app of the user's choice by detecting which ones are installed, across roughly two dozen apps on iOS and Android. The detection side is the interesting part, because on both platforms it depends on native manifest configuration you have to add by hand.

**tschoffelen/react-native-map-link** — 🗺 Open the map app of the user's choice.

- Repository: https://github.com/tschoffelen/react-native-map-link
- Stars: 823 · Forks: 153
- Language: TypeScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/tschoffelen-react-native-map-link

## The choice of map app belongs to the user

Every app that shows an address faces an unglamorous question: which map app should open? The most common answer is to hardcode one provider, usually Google Maps, and link straight to it. That works until the user has a different navigation app, which in many markets they do.

react-native-map-link takes the other approach. It detects which map and transit apps are installed on the device and lets the user pick from those, then opens the chosen one with the location in hand. The supported list covers Apple Maps, Google Maps, Citymapper, Uber, and a dozen other apps, and the library's own description is that it opens a location in a map app of the user's choice based on the apps they have installed.

The audience is React Native developers whose app has a location and wants to hand it to navigation without deciding for the user. The package is TypeScript, its peer dependencies are react at 16.8.0 or newer and react-native at 0.40.0 or newer, and it is published to npm as react-native-map-link. The licence is MIT.

What the library does not do is compute a route. It opens a map application at a coordinate, and everything that follows, the turn by turn directions, the map tiles, the arrival estimate, lives in the app it opened.

## Detection is a native permission problem on both platforms

This is where the library earns its keep, because on modern mobile operating systems you are not allowed to simply ask which apps are installed. Both platforms restrict that query, and the library cannot bypass either restriction. It needs you to declare in advance which apps you intend to interact with.

On iOS the mechanism is the LSApplicationQueriesSchemes key. Your app has to list the URL schemes it wants to interact with inside ios/{my-project}/Info.plist, and the documentation is blunt about the consequence of skipping it: omitting the schemes may mean the library cannot detect some of the maps apps installed by the user. A partial list means a partial chooser, and a partial chooser is a bug report later.

On Android the restriction arrived with Android 11 and SDK 30, which the documentation links to the package visibility feature. The library does not work out of the box there, and you have to add a queries statement to the top level of your AndroidManifest.xml, inside the manifest element, so the system allows the app to see the other packages.

So the real cost of this library is not the JavaScript call, it is maintaining two native manifests. Every app you add to the supported list has to be added in three places: the iOS scheme list, the Android queries list, and the library's own source.

## Installing the package and declaring the schemes

The install itself is a single npm command:

```bash
npm i -S react-native-map-link      # or yarn add react-native-map-link
```

After that, the native side. On iOS, the LSApplicationQueriesSchemes key goes into your Info.plist, and the beginning of the documented list looks like this:

```xml
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>comgooglemaps</string>
    <string>citymapper</string>
    <string>uber</string>
    <string>lyft</string>
    <string>transit</string>
    <string>truckmap</string>
    <string>waze</string>
    <string>yandexnavi</string>
    <string>moovit</string>
    <string>yandextaxi</string>
    <string>yandexmaps</string>
    <string>kakaomap</string>
```

The full list in the documentation is longer, and you are expected to add only what you need, so trimming it to the apps you actually offer is a deliberate choice rather than an oversight.

On Android, the same principle applies to the queries block in AndroidManifest.xml, which opens with a few general intent filters:

```xml
<queries>
  <intent>
    <action android:name="android.intent.action.VIEW" />
    <data android:scheme="http"/>
  </intent>
  <intent>
    <action android:name="android.intent.action.VIEW" />
    <data android:scheme="https"/>
  </intent>
  <intent>
    <action android:name="android.intent.action.VIEW" />
    <data android:scheme="geo" />
  </intent>
```

The geo and google.navigation entries are the ones that matter most for a maps library, since they cover the generic geo links and Google's navigation scheme, and the rest follow the same pattern for each supported app.

## Two dozen apps, and three that are not on both platforms

The supported list is long enough that it is worth reading as a map of the navigation market rather than as a feature list. It spans the obvious entries, Apple Maps, Google Maps, Waze and MapQuest, the transit and ride services such as Citymapper, Uber, Lyft, Gett, Moovit and The Transit App, the regional players such as Yandex.Navi, Yandex Maps, Yandex Taxi, Kakao Map, TMAP, Mapy.cz, Naver Map, 2GIS and DashTag Maps, and the specialist tools TruckMap, Trucker Path, OsmAnd, Maps.me, Sygic, Liftago and Outmap.

Three of them carry a platform restriction in the documentation. Petal Maps is marked Android only, while TomTom GO and Outmap are marked iOS only. That is not a rounding detail: it means a single cross-platform build cannot assume the same chooser on both platforms, and any analytics around which app users pick will be split by platform.

The other thing to notice is that each entry has an identifier, for example apple-maps, google-maps, citymapper, waze, and the scheme strings in the manifest snippets line up with those identifiers rather than with the display names. The identifiers are the vocabulary of the library, so they are worth keeping straight when you map a user's choice to a piece of your own configuration.

## Expo is handled by a config plugin in the package

Expo deserves its own paragraph because it changes the shape of the problem.

Expo projects do not have a hand written Info.plist or AndroidManifest.xml, so the two native steps above cannot be done by hand. The repository handles this with an Expo config plugin: app.plugin.js is listed among the published files in package.json, and @expo/config-plugins appears among the development dependencies. A config plugin is the standard way for a React Native library to modify native project files during a prebuild, which means the Info.plist key and the Android queries block get written for you at build time.

The documentation also points Expo users at a separate file, docs/expo.md, for the instructions. That is a sensible arrangement, because the manifest edits differ enough from the manual path that mixing them up is easy.

The repository itself is a Yarn Berry setup, with a .yarn directory and a .yarnrc.yml, and the scripts section of package.json shows a conventional pipeline: a build that copies images and runs tsc against tsconfig.build.json, jest for the tests, eslint for linting, and semantic-release for publishing. The docs directory and an example application under example/, with an App.tsx, round out the tree.

## Releases are automated, and the version field tells you not to trust it

Versioning is handled by semantic-release, which derives the published version from commit messages rather than from a number in package.json. That is why the version field in the checked-in package.json reads 3.1.0 while the published releases are far ahead of it, with v3.14.0 on 2026-10-04 and both v3.12.0 and v3.13.0 published on 2026-05-19. The last push to the repository was on 2026-10-19.

Two implications follow for anyone integrating this. Pinning is done by npm version, not by reading the repository, and upgrades are decided by commit history, so the changelog in the release notes is the reference for what changed between versions. The near-simultaneous v3.12.0 and v3.13.0 releases in May suggest a batch of changes published in one pass, which is a pattern worth expecting when a single maintainer runs the release tool.

The peer dependency ranges are wide and stable, react at 16.8.0 or newer and react-native at 0.40.0 or newer, so the library does not force you onto a recent React Native. That lowers the upgrade barrier, and it also means you will not get a compatibility fix from a peer dependency bump.

## What it does not do, and how it differs from a plain link

The limits are clear once the scope is stated. The library opens a map application at a location; it does not compute a route, does not return an estimated travel time, and does not draw the map itself. If your feature needs a path or a duration, this package is not the source of that data and the documentation does not present it as one. The supported app list is also a set of launch targets, not integrations, so a provider's own API features are not surfaced through it.

The alternative to using this library is to build the link yourself with the platform's own linking call and a URL scheme, for example a geo: link or a provider specific deep link. The difference in approach is detection and choice. A hand built link opens one app and, if that app is missing, fails or lands on a web page. This library checks what is installed, and offers the user the apps that are actually there, which is a different user experience and a different amount of work for you.

The cost of that convenience is the maintenance of the native declarations. Every new app you add needs an iOS scheme entry, an Android queries entry, and a source change in the library, and the queries block in particular is long and easy to get wrong. If you ship one provider and never intend to offer a choice, that work buys you nothing.

## Conclusion

react-native-map-link fits an app that wants to hand a location to whichever navigation app the user prefers rather than hardcoding one provider, and it is the wrong choice for a product that needs routing, an estimated arrival time, or a guaranteed Apple Maps or Google Maps target, since the library only opens a map app. Verify first which schemes you actually need to declare, because the detection depends entirely on the LSApplicationQueriesSchemes entries on iOS and the queries block on Android, and confirm the Expo setup in docs/expo.md if you are on Expo, where the native manifests are generated for you.

## FAQ

### How do I install react-native-map-link in a React Native project?

Run npm i -S react-native-map-link, or yarn add react-native-map-link. The package is published as react-native-map-link on npm, requires react 16.8.0 or newer and react-native 0.40.0 or newer as peer dependencies, and is released under MIT.

### Why does react-native-map-link not work on Android 11?

Because of the package visibility restriction introduced in Android 11 and SDK 30. You have to add a queries statement to the top level of your AndroidManifest.xml, inside the manifest element, so the system lets your app query for the other installed apps.

### What do I need to add to my iOS Info.plist?

An LSApplicationQueriesSchemes key listing the URL schemes of the apps you want to detect, inside ios/{my-project}/Info.plist. Without those entries the library may not be able to detect some of the map apps installed by the user.

### Does react-native-map-link work with Expo?

Yes. The package ships an Expo config plugin, app.plugin.js, and the documentation points Expo users to a separate file, docs/expo.md, with the instructions for the Expo path.

### Which map apps does react-native-map-link support?

Around two dozen, including Apple Maps, Google Maps, Citymapper, Uber, Lyft, Waze, Moovit, Yandex.Navi, Kakao Map, Mapy.cz, OsmAnd, 2GIS and MapQuest. Petal Maps is listed as Android only, while TomTom GO and Outmap are listed as iOS only.

## Sources

- [Issues](https://github.com/tschoffelen/react-native-map-link/issues)
- [License: MIT](https://github.com/tschoffelen/react-native-map-link/blob/master/LICENSE)
- [README](https://github.com/tschoffelen/react-native-map-link/blob/master/README.md)
- [Releases](https://github.com/tschoffelen/react-native-map-link/releases)
- [tschoffelen/react-native-map-link on GitHub](https://github.com/tschoffelen/react-native-map-link)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/tschoffelen-react-native-map-link
