@getcobrowse/react-native
v0.1.13
Published
Cobrowse screen sharing SDK for React Native
Readme
@getcobrowse/react-native
React Native SDK for Cobrowse screen sharing. Enables agents to view a customer's mobile screen in real-time with annotations, cursors, and highlights.
Uses native screen capture (ReplayKit on iOS, MediaProjection on Android) via Daily.js.
Installation
# Install the SDK
npm install @getcobrowse/react-native
# Install peer dependencies
npm install @daily-co/react-native-daily-js @daily-co/react-native-webrtc react-native-svgiOS Setup (Expo)
Add the config plugin to your app.json or app.config.js:
{
"expo": {
"plugins": [
["@getcobrowse/react-native/plugin/withCobrowseBroadcast", {
"appGroup": "group.com.yourcompany.yourapp.cobrowse"
}]
]
}
}Then rebuild:
npx expo prebuild --clean
npx expo run:ios --deviceImportant: Screen sharing requires a real device — it does not work in the iOS Simulator. You also need a development build, not Expo Go.
iOS Setup (Bare React Native)
iOS screen sharing requires a Broadcast Upload Extension. Daily's SDK handles all the IPC and frame encoding — you just need to create the target and wire it up.
1. Create the extension target:
In Xcode: File → New → Target → Broadcast Upload Extension. Name it CobrowseBroadcast. Uncheck "Include UI Extension".
2. Replace SampleHandler.swift:
Replace the generated SampleHandler.swift with:
import ReactNativeDailyJSScreenShareExtension
public class SampleHandler: DailyRPHandler {
override init() {
super.init(appGroupIdentifier: "group.com.yourcompany.yourapp.cobrowse")
}
}3. Configure App Groups:
In Xcode, enable the "App Groups" capability for both your main app target and the CobrowseBroadcast extension target. Add the same group identifier to both.
4. Add to Info.plist:
In your main app's Info.plist:
<key>RTCAppGroupIdentifier</key>
<string>group.com.yourcompany.yourapp.cobrowse</string>
<key>DailyScreenCaptureExtensionBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).CobrowseBroadcast</string>5. Install pods and rebuild:
cd ios && pod install && cd ..Important: Screen sharing requires a real device — it does not work in the iOS Simulator.
Android Setup
Add to AndroidManifest.xml:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />Register the foreground service in your manifest:
<service
android:name="com.daily.reactlibrary.DailyOngoingMeetingService"
android:foregroundServiceType="mediaProjection" />Usage
Basic Setup (2 lines)
Wrap your app with CobrowseProvider:
import { CobrowseProvider } from '@getcobrowse/react-native'
export default function App() {
return (
<CobrowseProvider
serverUrl="https://cobrowse.owner.sh"
metadata={{ email: user.email, name: user.name }}
>
<YourApp />
</CobrowseProvider>
)
}That's it. The SDK will:
- Register presence on the cobrowse dashboard
- Show a modal when an agent requests screen sharing
- Handle native screen capture via ReplayKit/MediaProjection
- Display agent annotations (cursor, highlights, pointers) as an overlay
Track Current Screen
Pass screenName to show what screen the user is on in the dashboard:
<CobrowseProvider
serverUrl="https://cobrowse.owner.sh"
metadata={{ email: user.email }}
screenName={currentRouteName}
>Using the Hook
Access cobrowse state and controls from any component:
import { useCobrowse } from '@getcobrowse/react-native'
function SupportButton() {
const { state, agentName, stop } = useCobrowse()
if (state === 'sharing') {
return (
<Button onPress={stop}>
Stop sharing with {agentName}
</Button>
)
}
return null
}Auto-Accept (Kiosk Mode)
Skip the permission modal and auto-accept share requests:
<CobrowseProvider
serverUrl="https://cobrowse.owner.sh"
metadata={{ deviceId: 'kiosk-001' }}
autoAccept
>Floating Sharing Indicator
Use the built-in SharingIndicator component:
import { SharingIndicator } from '@getcobrowse/react-native'
function MyScreen() {
return (
<View>
{/* Your content */}
<View style={{ position: 'absolute', bottom: 40, alignSelf: 'center' }}>
<SharingIndicator />
</View>
</View>
)
}Custom Share Request UI
Disable the built-in modal and handle requests yourself:
import { CobrowseProvider, useCobrowse } from '@getcobrowse/react-native'
function App() {
return (
<CobrowseProvider
serverUrl="https://cobrowse.owner.sh"
metadata={{ email: user.email }}
onShareRequest={(agentName) => {
// Custom notification, bottom sheet, etc.
}}
autoAccept={false}
>
<CustomShareUI />
</CobrowseProvider>
)
}
function CustomShareUI() {
const { state, agentName, acceptShare, declineShare } = useCobrowse()
if (state !== 'share_requested') return null
return (
<BottomSheet>
<Text>{agentName} wants to view your screen</Text>
<Button onPress={acceptShare}>Allow</Button>
<Button onPress={declineShare}>Decline</Button>
</BottomSheet>
)
}Callbacks
<CobrowseProvider
serverUrl="https://cobrowse.owner.sh"
metadata={{ email: user.email }}
onStateChange={(state) => analytics.track('cobrowse_state', { state })}
onShareRequest={(agentName) => console.log(`${agentName} wants to share`)}
onAnnotation={(event) => {
// event.type: 'cursor' | 'highlight' | 'pointer' | 'clear' | 'cursor-hide'
}}
>API Reference
<CobrowseProvider>
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| serverUrl | string | Yes | Cobrowse server URL |
| metadata | Record<string, unknown> | No | User identification metadata |
| screenName | string | No | Current screen name for dashboard |
| autoAccept | boolean | No | Auto-accept share requests |
| onShareRequest | (agentName: string) => void | No | Called when agent requests share |
| onStateChange | (state: CobrowseState) => void | No | Called on state transitions |
| onAnnotation | (event: AnnotationEvent) => void | No | Called when annotation received |
useCobrowse()
Returns a CobrowseHandle:
| Property | Type | Description |
|----------|------|-------------|
| state | CobrowseState | Current SDK state |
| agentName | string \| null | Name of requesting/viewing agent |
| acceptShare | () => void | Accept pending share request |
| declineShare | () => void | Decline pending share request |
| stop | () => Promise<void> | Stop active screen share |
| setMetadata | (metadata) => void | Update user metadata |
| setScreenName | (name) => void | Update current screen name |
| annotations | Annotation[] | Current highlight annotations |
| pointerAnimations | PointerAnimation[] | Current pointer ripples |
| cursor | CursorPosition | Agent cursor position |
CobrowseState
'idle' | 'tracking' | 'share_requested' | 'connecting' | 'sharing' | 'stopping'
