> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dojah.io/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native

> Launch Dojah's verification flow in a React Native app — with the bare CLI package or the Expo package, including EAS Build for iOS without Xcode.

Launch Dojah’s verification flow in a React Native app — one codebase for iOS and Android. There are two packages: one for bare React Native CLI projects and one for Expo projects.

<Note>
  Mobile SDKs launch by **WidgetID** — you design the flow in [EasyOnboard](/dashboard-guide/workflows/easyonboard) and its WidgetID identifies it. See [Choosing an SDK](/api-reference/widget-sdks/choosing-an-sdk).
</Note>

## Pick your package

| Your project            | Package                      | Launch with            |
| ----------------------- | ---------------------------- | ---------------------- |
| React Native CLI (bare) | `dojah-kyc-sdk-react_native` | `launchDojahKyc()`     |
| Expo                    | `dojah-kyc-sdk-react-expo`   | `DojahKycSdk.launch()` |

<Warning>
  Both packages contain native code, so **the flow cannot run in Expo Go**. Expo projects need a [development build](#build-with-eas-no-xcode-required) — either from EAS Build or from a local `npx expo run:ios` / `run:android`.
</Warning>

Requirements are the same either way: **iOS 14+** and **Android SDK 21+**.

## React Native CLI

### Install

```bash Terminal theme={null}
npm install dojah-kyc-sdk-react_native
# or
yarn add dojah-kyc-sdk-react_native
```

### iOS setup

Add the Dojah pods to your app target in `ios/Podfile`, then install them:

```ruby ios/Podfile theme={null}
target 'YourApp' do
  # ...
  pod 'Realm', '~> 10.52.2', :modular_headers => true
  pod 'DojahWidget', :git => 'https://github.com/dojah-inc/sdk-swift.git', :branch => 'pod-package'
end
```

```bash Terminal theme={null}
cd ios && pod install
```

Add the usage descriptions your flow needs to `Info.plist`: `NSCameraUsageDescription`, `NSMicrophoneUsageDescription` (video), and `NSLocationWhenInUseUsageDescription` (address/location checks).

<Accordion title="Wrap your root view in a UINavigationController">
  The SDK presents itself from a navigation controller, so your root view must be inside one. In `AppDelegate.mm`:

  ```objc AppDelegate.mm theme={null}
  #import <React/RCTBridge.h>
  #import <React/RCTRootView.h>

  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];

    RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                     moduleName:@"YourApp"
                                              initialProperties:nil];

    UIViewController *rootViewController = [UIViewController new];
    rootViewController.view = rootView;

    UINavigationController *navigationController =
        [[UINavigationController alloc] initWithRootViewController:rootViewController];

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = navigationController;
    [self.window makeKeyAndVisible];

    return YES;
  }
  ```

  Replace `@"YourApp"` with your app’s registered module name.
</Accordion>

### Android setup

Add JitPack to your repositories — in `android/build.gradle` or `android/settings.gradle`:

```groovy android/build.gradle theme={null}
allprojects {
  repositories {
    maven { url "https://jitpack.io" }
  }
}
```

Permissions ship with the package, so there’s nothing to add to your manifest.

### Launch the flow

```js App.js theme={null}
import { launchDojahKyc } from 'dojah-kyc-sdk-react_native'

launchDojahKyc(
  "your_widget_id",   // required
  "DJ-123456",        // optional reference ID
  "user@email.com"     // optional email
)
```

Pass `null` for the reference ID and email if you aren’t using them.

## Expo

### Install

```bash Terminal theme={null}
npx expo install dojah-kyc-sdk-react-expo expo-build-properties
```

### Configure app.json

Add the Dojah config plugin, the iOS usage descriptions, and the extra pods the native SDK needs:

```json app.json theme={null}
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSCameraUsageDescription": "We use the camera to capture your ID and selfie.",
        "NSMicrophoneUsageDescription": "We use the microphone to record liveness videos.",
        "NSPhotoLibraryUsageDescription": "We use your photo library to upload documents.",
        "NSLocationWhenInUseUsageDescription": "We use your location to verify your address."
      }
    },
    "plugins": [
      "dojah-kyc-sdk-react-expo",
      [
        "expo-build-properties",
        {
          "android": {
            "compileSdkVersion": 36,
            "targetSdkVersion": 36,
            "buildToolsVersion": "36.0.0"
          },
          "ios": {
            "deploymentTarget": "15.1",
            "extraPods": [
              { "name": "Realm", "version": "~> 10.52.2", "modular_headers": true },
              {
                "name": "DojahWidget",
                "git": "https://github.com/dojah-inc/sdk-swift.git",
                "branch": "pod-package"
              }
            ]
          }
        }
      ]
    ]
  }
}
```

<Note>
  The Dojah config plugin already raises `compileSdkVersion`, `targetSdkVersion`, `buildToolsVersion`, the Android Gradle Plugin (8.9.1+) and the Gradle wrapper during prebuild — it never lowers values you set higher. The `expo-build-properties` Android block above just pins them explicitly.
</Note>

Then generate the native projects:

```bash Terminal theme={null}
npx expo prebuild
```

Skip this step if you build with EAS and don’t keep `ios/` and `android/` in your repo — EAS runs prebuild on the build worker for you.

### Launch the flow

`DojahKycSdk.launch()` returns a promise that resolves to the flow’s exit status:

```js App.js theme={null}
import DojahKycSdk from 'dojah-kyc-sdk-react-expo'

const status = await DojahKycSdk.launch(
  "your_widget_id",   // required
  "DJ-123456",        // optional reference ID
  "user@email.com",    // optional email
  {
    userData: { firstName: "John", lastName: "Doe", dob: "1990-01-01" },
    govData: { bvn: "", nin: "" },
    metadata: { user_id: "121" },
  }
)

switch (status) {
  case 'approved': break  // all steps completed
  case 'pending':  break  // awaiting review
  case 'failed':   break  // a check did not pass
  case 'closed':   break  // user exited the flow
}
```

The optional fourth argument also accepts `govId`, `location`, `businessData`, and `address`.

<Warning>
  **Don’t trust the client for the final decision.** `approved` means the user finished the flow, not that they passed every check. Confirm the outcome server-side with the `reference_id` — via [Get verification](/api-reference/verifications/get-verification) or a [webhook](/api-reference/core-concepts/webhooks-signatures) — before granting access.
</Warning>

## Build with EAS (no Xcode required)

[EAS Build](https://docs.expo.dev/build/introduction/) compiles your app on Expo’s hosted macOS and Linux workers. That means you can produce an installable — and store-ready — iOS build from Windows or Linux without a Mac or a local Xcode install. It’s the recommended path for Expo projects using the Dojah SDK, since the SDK’s native code rules out Expo Go.

<Steps>
  <Step title="Install the tooling">
    ```bash Terminal theme={null}
    npm install -g eas-cli
    npx expo install expo-dev-client
    eas login
    ```

    `expo-dev-client` is what makes a custom build usable as a development client — you keep fast refresh and the dev menu while running your own native code.
  </Step>

  <Step title="Create your build profiles">
    Generate `eas.json`, then define the profiles you need:

    ```bash Terminal theme={null}
    eas build:configure
    ```

    ```json eas.json theme={null}
    {
      "build": {
        "development": {
          "developmentClient": true,
          "distribution": "internal"
        },
        "ios-simulator": {
          "extends": "development",
          "ios": { "simulator": true }
        },
        "production": {
          "autoIncrement": true,
          "ios": { "resourceClass": "large" }
        }
      },
      "submit": { "production": {} }
    }
    ```

    Use `ios-simulator` when you just want to run the flow on an iOS Simulator — those builds need no Apple Developer account. The `development` profile produces a device build, which does. `resourceClass: "large"` is optional; it speeds up the long CocoaPods step (Realm plus the Dojah pod) and isn’t available on the free plan.
  </Step>

  <Step title="Register test devices (iOS device builds only)">
    ```bash Terminal theme={null}
    eas device:create
    ```

    This registers a device UDID with your Apple team so the ad hoc provisioning profile covers it. Skip it for simulator builds.
  </Step>

  <Step title="Check what EAS will build from">
    EAS runs `npx expo prebuild` on the worker, so everything in the `app.json` plugin block above is applied there — you don’t need to commit native folders.

    If you *have* committed `ios/` and `android/`, EAS uses them as-is and skips prebuild. In that case run `npx expo prebuild --clean` locally and commit the result whenever you change your Dojah or build-properties config.
  </Step>

  <Step title="Run the build">
    ```bash Terminal theme={null}
    # iOS, installable on registered devices
    eas build --platform ios --profile development

    # iOS Simulator build (.app)
    eas build --platform ios --profile ios-simulator

    # Android .apk for devices and emulators
    eas build --platform android --profile development
    ```

    On the first iOS build, EAS offers to generate and store your distribution certificate and provisioning profile — accept it, or supply your own credentials. Build logs stream in the terminal and stay available on your project’s page at [expo.dev](https://expo.dev).
  </Step>

  <Step title="Install it and start developing">
    When the build finishes, the CLI prompts to install it on a connected device or a running simulator. Then start the bundler:

    ```bash Terminal theme={null}
    npx expo start --dev-client
    ```

    Your app now launches the real Dojah flow. JavaScript changes reload instantly — you only rebuild when native dependencies change.
  </Step>

  <Step title="Ship to the stores">
    ```bash Terminal theme={null}
    eas build --platform ios --profile production
    eas submit --platform ios --latest
    ```

    `eas submit` uploads the binary to App Store Connect (or Google Play with `--platform android`) from the same machine — again, no Xcode or Transporter needed.
  </Step>
</Steps>

<Warning>
  **Native changes need a new build.** `eas update` ships JavaScript over the air only. Installing or upgrading `dojah-kyc-sdk-react-expo`, or editing the plugin config, always requires a rebuild.
</Warning>

### ProGuard / R8 rules for Android release builds

EAS production builds run R8 minification. If you’ve enabled shrinking, add keep rules or the SDK will fail at runtime with `ClassNotFoundException`, `NoSuchMethodError`, or a blank WebView. In Expo, set them through `expo-build-properties` — no `proguard-rules.pro` file needed:

```ts app.config.ts theme={null}
android: {
  enableProguardInReleaseBuilds: true,
  enableShrinkResourcesInReleaseBuilds: true,
  extraProguardRules: [
    '-keep class com.dojah.** { *; }',
    '-keep class com.dojah_inc.** { *; }',
    '-keepclassmembers class com.dojah.** { *; }',
    '-dontwarn com.dojah.**',
    '-keepclassmembers class * { @android.webkit.JavascriptInterface <methods>; }',
    '-keepattributes JavascriptInterface',
    '-keepattributes Signature,InnerClasses,EnclosingMethod',
    '-keepattributes RuntimeVisibleAnnotations,RuntimeVisibleParameterAnnotations',
    '-keepclassmembers,allowshrinking,allowobfuscation interface * { @retrofit2.http.* <methods>; }',
    '-if interface * { @retrofit2.http.* <methods>; }',
    '-keep,allowobfuscation interface <1>',
    '-keep,allowobfuscation,allowshrinking interface retrofit2.Call',
    '-keep,allowobfuscation,allowshrinking class retrofit2.Response',
    '-keep class com.google.gson.** { *; }',
    '-keep public class * implements com.bumptech.glide.module.GlideModule',
    '-dontwarn okhttp3.**',
    '-dontwarn okio.**',
  ].join('\n'),
}
```

Bare CLI projects add the same rules to `android/app/proguard-rules.pro` instead.

### Troubleshooting EAS builds

<AccordionGroup>
  <Accordion title="CocoaPods can't find DojahWidget, or picks up a stale version">
    The `DojahWidget` pod is fetched from a Git branch, and EAS caches it between builds. Force a fresh checkout:

    ```bash Terminal theme={null}
    eas build --platform ios --profile development --clear-cache
    ```
  </Accordion>

  <Accordion title="Android build fails at :app:checkDebugAarMetadata">
    The error mentions compiling against API 36 or needing AGP 8.9.1+. Make sure `"dojah-kyc-sdk-react-expo"` is listed in your `plugins` array — the plugin raises those versions during prebuild. If you keep native folders in the repo, re-run `npx expo prebuild --clean` and commit.
  </Accordion>

  <Accordion title="iOS build fails on the deployment target">
    The native SDK requires iOS 14 or later. Set `ios.deploymentTarget` in the `expo-build-properties` plugin config (`"15.1"` is a safe value for recent Expo SDKs) and rebuild.
  </Accordion>

  <Accordion title="The camera or microphone screen crashes on iOS">
    A usage description is missing. Every permission your flow touches needs an `infoPlist` entry in `app.json` — iOS terminates the app when one is absent.
  </Accordion>

  <Accordion title="The flow is blank in a release build but fine in development">
    Almost always R8 stripping the SDK. Add the ProGuard rules above. To confirm the cause quickly, temporarily disable shrinking and rebuild.
  </Accordion>
</AccordionGroup>

## WebView fallback

If you need a UI the native launcher doesn’t provide, render the hosted flow in a WebView:

```jsx Verify.jsx theme={null}
<WebView
  originWhitelist={['*']}
  source={{ uri: 'https://identity.dojah.io?widget_id=your_widget_id' }}
  allowsInlineMediaPlayback
  mediaPlaybackRequiresUserAction={false}
  startInLoadingState
  javaScriptEnabled
/>
```

You can prefill the flow with query parameters such as `user_data[first_name]`, `user_data[email]`, `user_data[dob]`, and `metadata[user_id]`.

## Resources

**React Native CLI**

* [npm — dojah-kyc-sdk-react\_native](https://www.npmjs.com/package/dojah-kyc-sdk-react_native)
* [GitHub — dojah-inc/dojah-react-native-sdk](https://github.com/dojah-inc/dojah-react-native-sdk) (example app)

**Expo**

* [npm — dojah-kyc-sdk-react-expo](https://www.npmjs.com/package/dojah-kyc-sdk-react-expo)
* [GitHub — dojah-inc/dojah\_kyc\_sdk\_rn\_expo](https://github.com/dojah-inc/dojah_kyc_sdk_rn_expo) (example app)
* [Expo — EAS Build documentation](https://docs.expo.dev/build/introduction/) · [eas.json reference](https://docs.expo.dev/eas/json/)

**Underlying native SDKs**

* [GitHub — dojah-inc/sdk-swift](https://github.com/dojah-inc/sdk-swift) · [releases](https://github.com/dojah-inc/sdk-swift/releases)
* [GitHub — dojah-inc/sdk-kotlin](https://github.com/dojah-inc/sdk-kotlin) · [JitPack](https://jitpack.io/#dojah-inc/sdk-kotlin)
