@bigradar/bigradar-react-native
v1.2.0
Published
BigRadar in-app messaging SDK for React Native
Readme
bigradar-react-native
In-app messaging for React Native apps, powered by BigRadar — the same conversations, team, and AI agent as your BigRadar web widget, reachable from your own mobile app. No separate API key pair to manage — just the workspace ID you already use for the web widget.
- One workspace, two channels. This SDK attaches to the exact same workspace as your BigRadar web widget — same conversations, same team, same AI agent. It's not a separate product to configure.
- Rich messages. Bold, italic, links, lists, code blocks — the same sanitized rich-text messages agents and your AI send on web render natively here too, not as plain text.
- Image and file previews. Images open full-screen in-app; PDFs and other files preview in the OS's own viewer — both with a download action.
- In-app reply toast. A visitor elsewhere in your app notices a reply too — not just when backgrounded.
- Push notifications. Visitors get notified when an agent or your AI replies while the app is backgrounded.
- Deep linking. Tapping a notification opens straight to that conversation.
- No native code to maintain. Pure JS — nothing to link, no Podfile changes, no Gradle config.
Installation
npm install @bigradar/bigradar-react-native
# or
yarn add @bigradar/bigradar-react-nativeYou also need two peer dependencies most RN apps already have — @react-native-async-storage/async-storage (persists an anonymous visitor ID across app launches) and react-native-svg (renders the launcher bubble's icon, only needed if you use <BigRadarLauncher />):
npx expo install @react-native-async-storage/async-storage react-native-svg
# or, bare RN:
npm install @react-native-async-storage/async-storage react-native-svgQuick start
import { useEffect } from 'react';
import { BigRadar, BigRadarMessenger } from '@bigradar/bigradar-react-native';
function App() {
useEffect(() => {
BigRadar.initialize({ workspaceId: 'your-workspace-id' });
BigRadar.loginUnidentifiedUser();
}, []);
return (
<>
{/* ... your app ... */}
<BigRadarMessenger />
</>
);
}Mount <BigRadarMessenger /> once, near the root of your app — like a toast provider. It renders nothing until you call BigRadar.present(), typically from your own "Help" or "Support" button — see Launcher bubble, or your own button below for the full pattern, including the unread count.
Find your workspace ID in the BigRadar dashboard under Settings → Widget — it's the same "Workspace App ID" used for the web embed snippet.
Identifying a logged-in user
BigRadar.loginUser({
id: user.id,
name: user.name,
email: user.email,
attributes: { plan: 'growth' }, // any extra custom fields
});
// on sign-out:
BigRadar.logout();Launcher bubble, or your own button
<BigRadarLauncher /> is BigRadar's own floating chat bubble — the same mark as the web widget's launcher, bottom-right by default:
import { BigRadarLauncher, BigRadarMessenger } from '@bigradar/bigradar-react-native';
<BigRadarMessenger />
<BigRadarLauncher />It self-positions with bottomOffset/rightOffset props (pass your own safe-area inset if the default 20/20 lands under a tab bar), tints itself with your workspace's color, and shows the unread badge automatically. Requires react-native-svg (see Installation).
Prefer to trigger the messenger from your own "Help"/"Support" entry point instead? Skip <BigRadarLauncher /> and call BigRadar.present() from any button — the SDK hands you the unread count as plain data either way:
import { useEffect, useState } from 'react';
import { TouchableOpacity, Text, View, StyleSheet } from 'react-native';
import { BigRadar } from '@bigradar/bigradar-react-native';
function SupportButton() {
const [unread, setUnread] = useState(0);
useEffect(() => {
BigRadar.getUnreadConversationCount().then(setUnread);
// addEventListener returns an unsubscribe function — return it straight
// from the effect so it's cleaned up on unmount.
return BigRadar.addEventListener('unreadCountDidChange', setUnread);
}, []);
return (
<TouchableOpacity style={styles.button} onPress={() => BigRadar.present()}>
<Text style={styles.label}>Help</Text>
{unread > 0 && (
<View style={styles.badge}>
<Text style={styles.badgeLabel}>{unread}</Text>
</View>
)}
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
button: { flexDirection: 'row', alignItems: 'center', gap: 6 },
label: { fontWeight: '600' },
badge: {
minWidth: 18, height: 18, borderRadius: 9, paddingHorizontal: 4,
backgroundColor: '#EF4444', alignItems: 'center', justifyContent: 'center',
},
badgeLabel: { color: '#fff', fontSize: 11, fontWeight: '700' },
});present() resets the count to 0 the moment the chat opens — opening it counts as "seen." Nothing here is mobile-only, either: the same unreadCountDidChange listener is also how you'd drive the OS app icon badge (Notifications.setBadgeCountAsync(count)) — see Push notifications. The full working version, badge and all, is in example/src/App.tsx.
Expo setup
Add the config plugin to app.json so your workspace ID lives in one place instead of being hardcoded in both app.json and your BigRadar.initialize() call:
{
"expo": {
"plugins": [
["@bigradar/bigradar-react-native", { "workspaceId": "your-workspace-id" }]
]
}
}Then read it back with expo-constants:
import Constants from 'expo-constants';
BigRadar.initialize({
workspaceId: Constants.expoConfig?.extra?.bigradar?.workspaceId,
});The plugin has no native code to configure (there's nothing to link), so this is purely a config convenience — using it is optional. No expo prebuild step is required just for this SDK.
Bare React Native setup
No native setup needed for messaging itself — just call BigRadar.initialize() with a hardcoded or environment-provided workspaceId. Push notifications (below) are where bare RN needs a couple of manual steps.
Attachments
The SDK doesn't bundle an image/file picker — that way it never forces a dependency (or its native permissions) on an app that doesn't want attachments at all. Wire up whichever picker you already use:
import * as ImagePicker from 'expo-image-picker';
<BigRadarMessenger
onPickAttachment={async () => {
const permission = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (!permission.granted) return null;
const result = await ImagePicker.launchImageLibraryAsync({ quality: 0.8 });
if (result.canceled || !result.assets[0]) return null;
const asset = result.assets[0];
return {
uri: asset.uri,
filename: asset.fileName ?? 'photo.jpg',
mimetype: asset.mimeType ?? 'image/jpeg',
};
}}
/>Omit onPickAttachment and the attach button simply doesn't render.
Permission strings: if you use expo-image-picker (or any camera/photo library picker), your app needs the usual usage-description strings — NSPhotoLibraryUsageDescription/NSCameraUsageDescription on iOS (Info.plist, or ios.infoPlist in app.json for Expo), and READ_MEDIA_IMAGES/READ_EXTERNAL_STORAGE on Android. These belong to your picker library's own setup, not this SDK — see expo-image-picker's installation docs for the exact strings and app.json config.
Viewing and downloading attachments
Images tap open into a full-screen in-app preview; PDFs and other files show as a card that opens in the OS's own viewer (QuickLook on iOS, the platform default handler on Android) — no bundled image viewer or PDF renderer, same "nothing to link" promise. Both carry an explicit download icon.
By default, the download icon just opens the file in that same OS viewer, which has its own save/share affordance — that works with zero setup. For a real one-tap "save to device" instead, pass onDownloadAttachment:
import { File, Paths } from 'expo-file-system';
import * as MediaLibrary from 'expo-media-library';
<BigRadarMessenger
onDownloadAttachment={async ({ url, filename }) => {
const file = await File.downloadFileAsync(url, new File(Paths.cache, filename));
await MediaLibrary.saveToLibraryAsync(file.uri);
}}
/>In-app reply toast
The messenger's socket stays connected in the background even while its UI isn't on screen, so a reply can arrive while the visitor is elsewhere in your app entirely — not backgrounded, just on a different screen. <BigRadarInAppNotification /> is a toast for exactly that: mount it once alongside <BigRadarMessenger />, and it shows itself automatically.
<BigRadarMessenger />
<BigRadarInAppNotification />It auto-dismisses after 5 seconds, and tapping it opens straight to that conversation — the same path a tapped push notification takes. Pass topOffset if the default lands under a status bar or your own header. This is separate from OS push notifications (see below): it only fires while your app is actually running, for the case a push wouldn't even cover.
Push notifications
Visitors get pushed a notification when an agent, bot, or your AI agent replies while the app is backgrounded — same idea as any chat app's "new message" push.
import * as Notifications from 'expo-notifications';
import { Platform } from 'react-native';
// 1. Register a token once notification permission is granted.
const permission = await Notifications.requestPermissionsAsync();
if (permission.granted) {
const { data: token } = await Notifications.getExpoPushTokenAsync();
BigRadar.registerPushToken(token, Platform.OS === 'ios' ? 'ios' : 'android');
}
// 2. Deep-link into the right conversation when a notification is tapped.
Notifications.addNotificationResponseReceivedListener((response) => {
const data = response.notification.request.content.data as { conversationId?: string };
BigRadar.handleNotificationTap(data);
});Notes:
- v1 ships on Expo push tokens (
ExponentPushToken[...]) —expo-notificationscan mint one even in a bare RN app (via a dev client / EAS Build), so this works whether or not the rest of your app uses Expo. Direct native FCM/APNs tokens (no Expo dependency at all) are a planned fast-follow, not yet supported. - Re-registering the same token is a safe no-op — call
registerPushTokenon every app launch rather than trying to track whether it changed. - Permission strings: notifications need
expo-notifications' own config plugin (app.json→"plugins": ["expo-notifications", { ... }]) for the notification icon/color on Android, plus the standardNSUserNotificationsUsageDescription-equivalent permission prompt on iOS (handled automatically byrequestPermissionsAsync()). Seeexpo-notifications' setup docs.
Combine this with the OS app icon badge too, on the same unreadCountDidChange listener:
BigRadar.addEventListener('unreadCountDidChange', (count) => {
Notifications.setBadgeCountAsync(count);
});See Launcher bubble, or your own button for the in-app badge pattern.
API reference
BigRadar.initialize({ workspaceId: string, backendUrl?: string }): void;
BigRadar.loginUser(user?: { id?, name?, email?, phone?, attributes? }): Promise<void>;
BigRadar.loginUnidentifiedUser(): Promise<void>;
BigRadar.updateUser(user: { name?, email?, phone?, attributes? }): Promise<void>;
BigRadar.logout(): Promise<void>;
BigRadar.present(): void;
BigRadar.presentMessageComposer(initialMessage: string): void;
BigRadar.hide(): void;
BigRadar.getUnreadConversationCount(): Promise<number>;
BigRadar.addEventListener('unreadCountDidChange', (count: number) => void): () => void;
BigRadar.trackEvent(name: string, props?: Record<string, unknown>): void;
BigRadar.registerPushToken(token: string, platform: 'ios' | 'android'): void;
BigRadar.handleNotificationTap(data: { conversationId?: string }): void;<BigRadarMessenger onPickAttachment={...} onDownloadAttachment={...} /> — mount once; controlled entirely via present()/hide()/presentMessageComposer() above, never a visible prop.
<BigRadarLauncher bottomOffset={20} rightOffset={20} /> — optional floating bubble; see Launcher bubble, or your own button.
<BigRadarInAppNotification topOffset={54} /> — optional reply toast; see In-app reply toast.
What this isn't (yet)
- No help center / knowledge base UI. BigRadar doesn't have a customer-facing help-center product today, so there's nothing here to surface.
- No proactive in-app messages (banners/popups) yet — those exist on the web widget today and may come to mobile in a later release.
Example app
See example/ for a full working app — messaging, attachments, push registration, notification tap deep-linking, and the unread badge, all wired up.
git clone https://github.com/bigradar/bigradar-react-native
cd bigradar-react-native
yarn
cd example
yarn ios # or yarn androidContributing
License
MIT
Made with create-react-native-library
