Skip to main content

Getting started (React Native Navigation SDK)

Contents

The Trimble Maps React Native Navigation SDK wraps the CoPilot Native Nav SDK for Android and iOS. You get turn-by-turn guidance, voice instructions, trip preview, and optional headless navigation while reusing the same @trimblemaps/* packages that power the React Native Maps SDK.

To gain access, contact our Sales team. Your API key must be licensed for Maps SDK and Navigation SDK.

This guide covers installation, authentication, and prerequisites. For your first guided route, see Turn-by-turn navigation.

Packages

Navigation is published as @trimblemaps/navigation-react-native with required peer dependencies. Install and pin one compatible set — do not mix versions across packages.

Package Purpose
@trimblemaps/navigation-react-native NavigationView, TripPreviewView, AllInOneView, trips, and navigation session APIs
@trimblemaps/account-react-native Account initialization and licensing
@trimblemaps/maps-react-native Map rendering inside navigation UI
@trimblemaps/plugins-react-native Route, search, and routing-profile plugins used by navigation
@trimblemaps/services-react-native Routing and webservices support

Use one compatible range for all five packages — do not use * or mix unrelated version lines. The current release is 1.1.0. Install ^1.1.0 on each package (navigation declares matching peer ranges in package.json).

Packages are published to the Trimble JFrog npm registry, not npmjs.org. After install, confirm peerDependencies in @trimblemaps/navigation-react-native/package.json still match the ranges you use.

Yarn:

yarn add @trimblemaps/navigation-react-native@^1.1.0 \
  @trimblemaps/account-react-native@^1.1.0 \
  @trimblemaps/maps-react-native@^1.1.0 \
  @trimblemaps/plugins-react-native@^1.1.0 \
  @trimblemaps/services-react-native@^1.1.0

npm:

npm install @trimblemaps/navigation-react-native@^1.1.0 \
  @trimblemaps/account-react-native@^1.1.0 \
  @trimblemaps/maps-react-native@^1.1.0 \
  @trimblemaps/plugins-react-native@^1.1.0 \
  @trimblemaps/services-react-native@^1.1.0

Expo (development build — not Expo Go; see Expo projects):

npx expo install @trimblemaps/navigation-react-native@^1.1.0 \
  @trimblemaps/account-react-native@^1.1.0 \
  @trimblemaps/maps-react-native@^1.1.0 \
  @trimblemaps/plugins-react-native@^1.1.0 \
  @trimblemaps/services-react-native@^1.1.0

The navigation example app also uses common React Native libraries for gestures and screens. These are example app dependencies, not additional npm peer requirements of @trimblemaps/navigation-react-native. Add versions that match your React Native or Expo template if your UI needs them:

  • react-native-gesture-handler
  • react-native-reanimated
  • react-native-safe-area-context
  • react-native-screens

Requirements

React Native 0.85.x recommended (minimum 0.80 per package peers)
Architecture New Architecture required (Fabric / TurboModules). Set newArchEnabled=true.
Node 24+ (some RN templates warn on Node 25; use 24 or 26+ if you see EBADENGINE)
Android minSdk ≥ 26 for navigation (maps-only apps may use 25; see Maps requirements)
iOS 15+. Use a physical device or the iOS Simulator on Apple silicon for development. Some Metal-heavy map features may still require a physical device.
Access Trimble Maps API key with Maps and Navigation licenses

npm registry

@trimblemaps/* packages are published to the public trimblemaps-npm registry on Trimble JFrog. Configure the @trimblemaps scope before install. Full examples are in React Native Maps — npm registry.

For npm:

# .npmrc
@trimblemaps:registry=https://trimblemaps.jfrog.io/artifactory/api/npm/trimblemaps-npm/

Then run yarn install or npm install.

Expo projects

Navigation requires custom native code on both platforms. Expo Go is not supported — use a development build (npx expo run:ios or npx expo run:android).

The @trimblemaps/maps-react-native config plugin adds $RNTM.post_install(installer) during prebuild. The @trimblemaps/navigation-react-native config plugin adds the account, services, plugins, and navigation Podfile hooks ($RNTM_CORE, $RNTM_SERVICES, $RNTP, $RNTN). Add both plugins when you use navigation:

{
  "expo": {
    "plugins": [
      "@trimblemaps/maps-react-native",
      "@trimblemaps/navigation-react-native",
      [
        "expo-build-properties",
        {
          "android": {
            "minSdkVersion": 26,
            "extraMavenRepos": [
              "https://trimblemaps.jfrog.io/artifactory/android"
            ]
          },
          "ios": {
            "useFrameworks": "dynamic"
          }
        }
      ]
    ]
  }
}

Install expo-build-properties if needed:

npx expo install expo-build-properties

Declare permissions in app.json / app.config.js (android.permissions, ios.infoPlist, and UIBackgroundModes for background location when required).

Recommended order for Expo:

  1. Configure the npm registry (.npmrc) and install all five @trimblemaps/* packages.
  2. On macOS, complete iOS Carthage at the app root before npx expo prebuild. Run prebuild with RNTM_CARTHAGE_BUILD_PATH set (see step 4), or re-run pod install in ios/ with it set afterward.
  3. Run npx expo prebuild, then npx expo run:ios or npx expo run:android.

Do not hand-edit generated native projects for settings that config plugins or expo-build-properties already apply — change app.json / app.config.js and prebuild again.

Android installation

Add the public Trimble JFrog Maven repository so Gradle can resolve native SDK artifacts. Navigation requires minSdk ≥ 26 (maps-only apps may use 25). Use the pattern that matches your React Native template. For Expo, configure Maven and minSdkVersion with expo-build-properties instead of editing Gradle files directly.

allprojects in android/build.gradle

Works with many React Native apps that declare repository blocks on the root project:

allprojects {
    repositories {
        mavenLocal()
        google()
        mavenCentral()
        maven {
            url "https://trimblemaps.jfrog.io/artifactory/android"
        }
    }
}

settings.gradle (newer Gradle layouts)

If your template centralizes repositories in android/settings.gradle, add the Trimble Maven URL there instead (inside pluginManagement.repositories, dependencyResolutionManagement.repositories, or your project’s equivalent block):

maven {
    url "https://trimblemaps.jfrog.io/artifactory/android"
}

Set minSdkVersion = 26 (or higher) in your Android ext block.

The navigation package resolves native artifacts including:

Component Version (resolved by package)
maps-android-sdk 2.4.1
Account / services SDKs 2.2.0
navigation:ui and ui-components 2.2.0

Run yarn install or npm install, then rebuild the Android app.

iOS installation

Navigation requires all five @trimblemaps/* Cartfiles merged, Carthage bootstrap, CocoaPods with RNTM_CARTHAGE_BUILD_PATH set to your Carthage/Build folder, and dynamic frameworks for Trimble xcframeworks. Complete the steps in order. Carthage must finish before pod install.

1. Create a merged Cartfile

After yarn install or npm install, copy binary lines from each package Cartfile under node_modules:

  • @trimblemaps/account-react-native/Cartfile
  • @trimblemaps/maps-react-native/Cartfile
  • @trimblemaps/plugins-react-native/Cartfile
  • @trimblemaps/services-react-native/Cartfile
  • @trimblemaps/navigation-react-native/Cartfile

Keep one line per framework. When the same framework appears in more than one Cartfile, keep a single line using the higher pinned version — for example TrimbleMapsWebservicesClient is listed in both plugins and services. Package Cartfiles contain only binary lines from Trimble JFrog — do not add third-party github entries (older sample Cartfiles may still list removed dependencies such as Polyline). Use only public Carthage URLs on trimblemaps.jfrog.io unless your license agreement directs otherwise.

Navigation-specific public frameworks include TrimbleMapsNavigation, TrimbleMapsCoreNavigation, and TrimbleMapsNavigationNative (see the navigation package Cartfile for pinned versions).

You can merge with a script from your app root:

for f in node_modules/@trimblemaps/*/Cartfile; do
  grep -E '^binary ' "$f"
done | sort -u > Cartfile

2. Run Carthage

From your app root (next to package.json):

carthage bootstrap --platform iOS --use-xcframeworks

Add Carthage/ to .gitignore. See React Native Maps — Run Carthage for Carthage version notes and --project-directory when running from ios/.

3. Podfile, frameworks, and CocoaPods

Set dynamic linking when your template does not already:

export USE_FRAMEWORKS=dynamic

Expo: set "useFrameworks": "dynamic" in expo-build-properties instead of exporting the variable for every shell.

In ios/Podfile post_install, call every Trimble hook that CocoaPods defines for installed packages:

post_install do |installer|
  react_native_post_install(installer, config[:reactNativePath], :mac_catalyst_enabled => false)

  $RNTM.post_install(installer) if defined?($RNTM) && $RNTM
  $RNTM_CORE.post_install(installer) if defined?($RNTM_CORE) && $RNTM_CORE
  $RNTM_SERVICES.post_install(installer) if defined?($RNTM_SERVICES) && $RNTM_SERVICES
  $RNTP.post_install(installer) if defined?($RNTP) && $RNTP
  $RNTN.post_install(installer) if defined?($RNTN) && $RNTN
end

CocoaPods vendors Trimble XCFrameworks from each package’s ios/Frameworks directory. Each @trimblemaps/* podspec runs a prepare_command during pod install that symlinks frameworks from your Carthage build folder. Set RNTM_CARTHAGE_BUILD_PATH to your app-root Carthage/Build when you run CocoaPods (the navigation pod also accepts RNTN_CARTHAGE_BUILD_PATH):

cd ios
RNTM_CARTHAGE_BUILD_PATH="$(cd .. && pwd)/Carthage/Build" pod install

pod install fails with a clear error if a required framework is missing from that folder. Check that your merged Cartfile includes every framework from all five package Cartfiles and re-run Carthage if needed.

For Expo, set the same variable when you run prebuild:

RNTM_CARTHAGE_BUILD_PATH="$(pwd)/Carthage/Build" npx expo prebuild

See React Native Maps — Link XCFrameworks for the same flow on maps-only apps.

Rebuild after pod install.

Permissions overview

Navigation needs location on both platforms. Declare manifest and plist entries, request runtime permission, and enable iOS background location when you navigate while the app is backgrounded. See Permissions and location.

Authentication

Initialize the account before mounting NavigationView or other navigation UI. Request both licensed features and confirm navigation licensing before starting a session. Run initialization from a useEffect (or similar) — do not use top-level await in a React component file (same pattern as React Native Maps — Authentication).

import { useEffect, useState } from "react";
import {
  Account,
  AccountManager,
  APIEnvironment,
  LicensedFeature,
} from "@trimblemaps/account-react-native";

export function App() {
  const [ready, setReady] = useState(false);

  useEffect(() => {
    let cancelled = false;

    (async () => {
      await AccountManager.initialize(
        new Account({
          apiKey: "YOUR_TRIMBLEMAPS_API_KEY",
          apiEnvironment: APIEnvironment.Production,
          licensedFeatures: [
            LicensedFeature.MapsSDK,
            LicensedFeature.NavigationSDK,
          ],
        }),
      );
      await AccountManager.awaitInitialization();

      const [mapsLicensed, navigationLicensed] = await Promise.all([
        AccountManager.isLicensedForMaps(),
        AccountManager.isLicensedForNavigation(),
      ]);

      if (!navigationLicensed) {
        throw new Error("API key is not licensed for Navigation SDK.");
      }

      if (!cancelled) {
        setReady(mapsLicensed && navigationLicensed);
      }
    })();

    return () => {
      cancelled = true;
    };
  }, []);

  if (!ready) {
    return null;
  }

  // Mount NavigationView or request location, then start navigation
  return null;
}

TypeScript and Expo

If tsc reports errors inside @trimblemaps/* source files under node_modules (for example 'react-native' has no exported member 'NativeModule' in account or navigation packages), update to package versions that export a top-level "types" condition (current @trimblemaps/* releases). On older builds, set "customConditions": [] in your app’s tsconfig.json so TypeScript uses the published .d.ts files instead of resolving the react-native export to ./src. This affects type-checking only; Metro bundling is unchanged.

Next steps

Last updated October 19, 2026.
Contents