Rheo documentation
Developer Guide

Bare React Native SDK

Install and integrate @getrheo/react-native-bare — RheoProvider, Flow, native video/review adapters, and full API reference.

Package

@getrheo/react-native-bare — bare React Native entry point. Re-exports @getrheo/react-native-core and registers bare adapters:

CapabilityAdapter
Video layersreact-native-video
In-app review buttonsreact-native-in-app-review

Do not install @getrheo/react-native-expo alongside this package.

The public JavaScript API is identical to the Expo flavor — only native adapters and peer dependencies differ. Shared runtime concepts: SDK overview.

Runnable reference: getrheo/rheo-example-bare (public). Full-stack local API testing uses the private Rheo monorepo example via pnpm dev:local:app:react-native.

Install

pnpm add @getrheo/react-native-bare \
  react react-native \
  react-native-permissions react-native-gesture-handler react-native-reanimated \
  react-native-linear-gradient react-native-svg lottie-react-native \
  react-native-vector-icons @react-native-async-storage/async-storage \
  react-native-safe-area-context react-native-in-app-review react-native-video

@react-native-community/slider ships as a direct dependency of core.

Integrations (not SDK peers): react-native-appsflyer, react-native-purchases, react-native-purchases-ui — install only when used.

Native setup

iOS

cd ios && pod install
  1. Permissions — for each permissionKey your flows request, add entries via react-native-permissions setup_permissions in Podfile and matching Info.plist usage strings (NSCameraUsageDescription, NSPhotoLibraryUsageDescription, NSCalendarsFullAccessUsageDescription, etc.).
  2. Videoreact-native-video follows its upstream linking guide (autolinking on RN 0.60+).
  3. Fonts — link custom branding fonts or load at runtime before text renders.

Android

  1. Add AndroidManifest.xml permissions for each capability (CAMERA, RECORD_AUDIO, READ_MEDIA_IMAGES, POST_NOTIFICATIONS on API 33+, etc.).
  2. Rebuild after changing permissions.

Root layout

import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { RheoProvider } from '@getrheo/react-native-bare';

const App = () => (
  <SafeAreaProvider>
    <GestureHandlerRootView style={{ flex: 1 }}>
      <RheoProvider config={rheoConfig}>
        <Navigation />
      </RheoProvider>
    </GestureHandlerRootView>
  </SafeAreaProvider>
);

react-native-gesture-handler must be imported at the app entry (see upstream docs) when using navigators.

OS permissions

Same built-in keys as Expo — notifications, camera, microphone, photo_library, contacts, calendar. The SDK calls react-native-permissions internally; there is no host permission callback.

Configure native projects per the react-native-permissions checklist. Missing setup → outcome denied.

Branding fonts

import { buildBrandingFontLoadMap } from '@getrheo/react-native-bare';

const fontMap = buildBrandingFontLoadMap(branding);
// Load with react-native-asset linking or a runtime loader before Flow mounts

Step-by-step integration

1. Credentials

Copy publishable key from App settings → SDK credentials and channel public id from Channels. See SDK environment.

2. RheoConfig

import type { RheoConfig } from '@getrheo/react-native-bare';

const rheoConfig: RheoConfig = {
  publishableKey: 'ob_pk_test_xxxxxxxx',
  apiBaseUrl: __DEV__ ? 'http://10.0.2.2:4000' : undefined, // Android emulator → host
  userId: persistedUserId, // load from AsyncStorage — do not omit on RN
  sessionId: `sess_${Date.now()}`,
  appVersion: DeviceInfo.getVersion(),
  locale: 'en',
};

Full field reference: Expo SDK — RheoConfig (same type).

3. RheoProvider

import { RheoProvider } from '@getrheo/react-native-bare';

<RheoProvider config={rheoConfig} prefetch={['ch_test_onboarding']}>
  <RootNavigator />
</RheoProvider>

Optional logLevel ("silent" | "warn" | "debug", default silent) controls SDK console diagnostics. See Diagnostics and logging.

4. <Flow />

import { Flow } from '@getrheo/react-native-bare';
import type { FlowTerminalSnapshot } from '@getrheo/react-native-bare';

const PaywallGate = () => (
  <Flow
    channelId="ch_live_paywall_01"
    theme="light"
    onFlowCompleted={(payload: FlowTerminalSnapshot) => {
      navigation.replace('Home');
      analytics.track('onboarding_complete', payload.correlation);
    }}
    fallback={<StaticPaywall />}
  />
);

5. Custom UI with useFlow

Same API as Expo — import from @getrheo/react-native-bare:

import {
  useFlow,
  LayerRenderer,
  ScreenChrome,
} from '@getrheo/react-native-bare';

See Expo SDK — managed vs custom for the full useFlow / LayerRenderer pattern.

Identity

import { useRheoCustomUserId } from '@getrheo/react-native-bare';

const { setCustomUserId } = useRheoCustomUserId();
// After your auth session resolves:
setCustomUserId(backendUser.id);

Persist userId yourself (AsyncStorage) so experiment bucketing stays stable across launches.

Manifest prefetch

Identical to Expo — import from @getrheo/react-native-bare:

import { prefetch, prefetchAll, useRheoPrefetch } from '@getrheo/react-native-bare';

<RheoProvider config={config} prefetch="all" />

// Imperative:
void prefetch('ch_test_…');

In-app review

Requires react-native-in-app-review (listed in install command). Buttons with action.kind: "request_app_review" call the native review API with the same ~1.5s iOS delay behavior as Expo.

Video layers

video layers use react-native-video. Ensure the native module is linked and test on device — simulators may not reproduce all playback edge cases.

Events, terminal payloads, auth, paywalls

Export reference

Same surface as @getrheo/react-native-expo — import from @getrheo/react-native-bare:

CategoryExports
ProviderRheoProvider, useRheo, useRheoCustomUserId, useEventQueue
Flow UIFlow, useFlow, LayerRenderer, ScreenChrome, DefaultResolveError
Prefetchprefetch, prefetchAll, useRheoPrefetch
AuthOAuthLoginProvider, EmailPasswordAuthProvider, useOAuthLogin, useEmailPasswordAuth
IntegrationspresentRevenueCatPaywall, normalizeRcPaywallResult, attribution helpers
TypesRheoConfig, FlowTerminalSnapshot, UseFlowResult, FlowProps, manifest types
ErrorsRheoChannelRequiredError, RheoChannelNotFoundError, RheoChannelArchivedError
CacheclearManifestResolveCache, listManifestResolveCacheEntries, manifestResolveCacheKey

HTTP API

EndpointPurpose
POST /v1/sdk/resolveChannel manifest + assignment
POST /v1/sdk/resolve-allBatch prefetch
POST /v1/sdk/eventsAnalytics batch

Headers: Authorization: Bearer <publishableKey>, X-Rheo-Channel: <channelId> (resolve and per-channel event batches).

Expo vs bare — when to pick bare

Choose bare when…Choose Expo when…
You own ios/ and android/ nativelyYou use Expo Router / dev client
You already depend on react-native-videoYou prefer expo-video + config plugins
You cannot use Expo prebuildYou want npx expo install peer alignment