React Native Integration Skill
Integration conventions for the StreamLayer React Native SDK that keep an AI agent's diff small and correct — where to initialize, where to render StreamLayerView, callback wiring, auth forwarding, and minimal-diff placement.
StreamLayer React Native SDK Integration
How to wire StreamLayer into an existing React Native or Expo app cleanly. Follow the rules — they prevent the common over-integration mistakes.
This page is the human-readable form of the streamlayer-react-native-integration agent skill. Reference it from your AI agent alongside the streamlayer-docs MCP — see Integrate with an AI Agent.
Pick the package
react-native-sl-sdk— the React Native SDK, published to npm. ImportStreamLayer,StreamLayerView, and the supporting types/enums from it:import { StreamLayer, StreamLayerView, StreamLayerViewConfiguration, StreamLayerViewNotificationFeature, StreamLayerViewOverlayLandscapeMode, StreamLayerTheme } from 'react-native-sl-sdk';- New Architecture only. The SDK ships on the React Native New Architecture (Fabric / TurboModules). Install it (
npm install react-native-sl-sdk) and runpod install— it can't be added to an old-bridge app without migrating. - Main UI element:
StreamLayerView— the StreamLayer Element. It renders your player through itsplayerViewprop and scales it down when the L-bar layout arrives; it is not a standalone floating panel. - Companion packages:
expo-screen-orientation(Expo, for rotation) andreact-native-config(to read the SDK API Key from.env) — follow the Integration Guide for the exact native setup. - Requirements: React Native 0.76+ / Expo SDK 52+, iOS 15+, Android min SDK 24, Xcode 15.3+.
Rules (do this)
-
Initialize once and high; render the view low, gated on init. Call
StreamLayer.initSdk({ sdkKey, theme, isLoggingEnabled }, false)exactly once — in a mountuseEffectat the app/player-screen root, not on every render. Track completion in state (const inited = await StreamLayer.isInitialized(); setInitialized(inited)) and renderStreamLayerViewonly whenisInitializedis true. Put it inside the player screen — the component that owns the video and its play/pause state — not in a global provider mounted app-wide.- ❌ Rendering
StreamLayerViewbeforeinitSdkresolves — the native view has no initialized SDK context. - ❌ Calling
initSdkinsiderender/ on every effect run — it's a one-time call; guard it. - ✅
initSdkin a[]-dependencyuseEffect;StreamLayerViewrendered under anisInitializedgate.
- ❌ Rendering
-
Wrap your player in the
playerViewprop; don't render it separately.StreamLayerViewtakes your existing player element as itsplayerViewprop and resizes it for L-bar and sidebar layouts. Pass a stableplayerobject (aStreamLayerViewPlayerwith avolumegetter/setter) so the SDK can bridge audio. Keep auseRef<StreamLayerView>for imperative calls. Style it withStyleSheet.absoluteFillObjectover your player container, not the whole screen. -
Build
configonce and wire only the callbacks your features use. Compute theStreamLayerViewConfigurationfrom a stable helper (getViewConfig()), not inline in JSX, so it isn't rebuilt every render. WireonRequestAudioDucking(level)/onDisableAudioDucking()to your player's volume for the audio bridge,onLBarStateChanged(slideX, slideY)to resize theplayerViewwhen the L-bar slides in, andonRequestStream(id)to switch events — leave out the ones you don't handle. SetoverlayHeightSpace/overlayLandscapeModein the config to control portrait/landscape placement. -
Forward authentication after init. For logged-in users, call
await StreamLayer.authorizationBypass(schema, token)with a token from your backend; for guests useawait StreamLayer.useAnonymousAuth(). Check first withStreamLayer.isUserAuthorized()and do it once, afterinitSdk. Both are async and can reject — alwaystry/catch. Start a session for your event withawait StreamLayer.createEventSession(eventId)when the user opens or switches a stream; callStreamLayer.releaseEventSession()when leaving. -
Keep credentials and the diff simple. The SDK API Key is a public, client-side value from StreamLayer Studio. This SDK's documented pattern reads it from
.envviareact-native-config(SL_SDK_API_KEY) — use that existing mechanism, don't invent a new secrets layer or hardcode the key in source. FitStreamLayerViewaround your existing player and screen — don't restructure navigation, add wrapper providers, or refactor unrelated component code.
Gotchas
StreamLayerViewrenders nothing. Almost always theisInitializedgate is missing orinitSdkhasn't resolved yet, or your player was rendered outside theplayerViewprop instead of inside it.- Native build fails after install. Missing
pod install, an iOS deployment target below 15, the New Architecture not enabled, or theexpo-screen-orientationplugin not added toapp.json. - Player covers or clips the L-bar.
onLBarStateChangedisn't resizing theplayerView— subtractslideX/slideYfrom your player's width/height as the L-bar slides in. - Audio doesn't duck.
onRequestAudioDucking/onDisableAudioDuckingaren't wired to your player's volume, or theplayerobject passed toStreamLayerViewhas no workingvolumesetter. - Auth call throws.
authorizationBypass/useAnonymousAuthare async and reject on failure — alwaysawaitinsidetry/catch. - Wrong architecture. This SDK requires the New Architecture; an old-bridge app must migrate first — don't try to add it to a Paper-only project.
- Authoritative API details: the
streamlayer-docsMCP (search/fetch) and the API Reference.
Related
- Integrate with an AI Agent — Connect the MCP and prompt your agent to run this integration
- React Native & Expo Integration Guide — Complete New Architecture setup and configuration
- Authentication Forwarding — Bypass and anonymous auth flows
- Sample Integrations — Fully functional reference projects
- API Reference —
StreamLayermethods andStreamLayerViewprops in full
Updated 15 days ago
