Skip to content

License setup — React Native

You added @dvai-bridge/react-native to a React Native app — RN ≥ 0.77, Bridgeless ON. You want to ship a release. Here's the licensing path.

TL;DR

Drop dvai-license.jwt into your app's project root. Reference it in the platform bundle configs — iOS Resources, Android assets/. At DVAIBridge.start(...), the SDK reads it from the bundle on the native side, verifies the ES256 signature offline, and unlocks production behaviour. Development builds — Metro dev server — ignore license problems.

Where the file goes

The file needs to reach the native side — the TurboModule reads it from the platform bundle.

iOS — add to ios/<YourApp>/:

ios/MyApp/dvai-license.jwt

In Xcode, add the file to the app target. Confirm it shows up under Copy Bundle Resources (see the iOS page for the file-inspector steps).

Android — add to android/app/src/main/assets/:

android/app/src/main/assets/dvai-license.jwt

Alternative locations the SDK also checks:

  1. Inline JWT via start({ licenseToken: "..." }).
  2. Explicit path via start({ licenseKeyPath: "..." }).
  3. Platform-default bundle resource — auto-discovered.

Code: with vs. without

Default — license bundled on both platforms:

ts
import { DVAIBridge } from "@dvai-bridge/react-native";

const bound = await DVAIBridge.start({
  backend: "llama",
  modelPath: modelPath,
});

console.log(bound.baseUrl);           // http://127.0.0.1:38883/v1
console.log(bound.licenseStatus);     // { kind: "commercial", ... }

Inline JWT — fetched from your account API:

ts
const token = await api.getDvaiLicense();

const bound = await DVAIBridge.start({
  backend: "llama",
  modelPath,
  licenseToken: token,
});

Explicit path — a file saved into RNFS document directory:

ts
import RNFS from "react-native-fs";

const bound = await DVAIBridge.start({
  backend: "llama",
  modelPath,
  licenseKeyPath: `${RNFS.DocumentDirectoryPath}/dvai-license.jwt`,
});

Native license fields land in v3.3

In v3.2.x, the React Native SDK ships without licenseToken / licenseKeyPath on start(). Pure React Native apps in v3.2 ship under a "dev preview" allowance. Native React Native validation arrives in v3.3 — pin to v3.3+ to enforce on React Native.

What happens without a license

In release builds — ./gradlew assembleRelease, xcodebuild archivestart(...) rejects with a LicenseRequiredError-shaped object:

ts
try {
  await DVAIBridge.start(...);
} catch (err: any) {
  if (err.code === "LICENSE_REQUIRED") {
    // err.message is a multi-line string with resolution steps.
    // err.status is "free-prod" | "free-expired".
    Alert.alert("License required", err.message);
  }
}

Testing locally without a license

Metro / dev-server builds — __DEV__ === true — enable dev mode automatically. The native module checks BuildConfig.DEBUG on Android and the DEBUG macro on iOS.

Force dev mode explicitly in a release build:

ts
DVAIBridge.setEnv({ DVAI_FORCE_DEV: "1" });

Rehearse the production code path in a debug build:

ts
DVAIBridge.setEnv({ DVAI_FORCE_PROD: "1" });

When validation fails

Platform-specific failures mirror iOS and Android. The aud audience claim must match the iOS bundle id OR the Android applicationId — whichever is running. Most licenses ship both, plus a "*" fallback.

See also