The official React Native SDK for embedding interactive SeatLayer reserved-seating maps in iOS and Android apps. It provides typed selection, holds, best available, general admission, multi-floor controls, errors and events over a versioned WebView bridge.
Developer docs · Live demo · Website · Web SDK · Flutter SDK · iOS SDK · Native Android SDK · AI Toolkit
Public preview: Validate
0.2.xusing a SeatLayer test event and physical iOS and Android devices before production rollout.
npm install @seatlayer/react-native
npx expo install react-native-webviewNo custom native SeatLayer module is used, so this SDK works with Expo Go when
the installed Expo SDK includes react-native-webview.
npm install @seatlayer/react-native react-native-webview
npx pod-installReact Native autolinks react-native-webview on Android and iOS.
Give the map a definite height or a full-screen parent. Keep the configuration object stable so React rerenders do not reload the chart.
import React, { useEffect, useMemo } from 'react';
import { View } from 'react-native';
import {
SeatLayerError,
SeatLayerView,
useSeatLayerController,
} from '@seatlayer/react-native';
export function SeatMapScreen() {
const controller = useSeatLayerController();
const configuration = useMemo(
() => ({
event: 'ev_your_event_key',
currency: 'USD',
maxSelection: 8,
}),
[],
);
useEffect(
() =>
controller.on('selectionChanged', (seats) => {
console.log('Selected seats', seats);
}),
[controller],
);
return (
<View style={{ flex: 1 }}>
<SeatLayerView
style={{ flex: 1 }}
controller={controller}
configuration={configuration}
onReady={(info) => {
console.log(
`SeatLayer ready: protocol=${info.protocolRevision} mode=${info.mode}`,
);
}}
onLoadError={(error) => {
console.error(error.code, error.message);
}}
/>
</View>
);
}Drive checkout-related actions through the controller:
try {
const hold = await controller.bestAvailable(4);
if (hold) {
// Send only the hold id to your trusted backend.
await beginCheckoutOnServer(hold.holdId);
}
} catch (error) {
if (error instanceof SeatLayerError) {
showInventoryMessage(error.code, error.message);
}
}hold · resumeHold · extendHold · release · releaseLabels ·
bestAvailable · holdGA · setSeatTier · getSelection ·
selectObjects · deselectObjects · clearSelection · selectCategories ·
deselectCategories · setSelectableObjects · setMaxSelection ·
getSelectionValidity · refreshAccess · getCurrentHold · getGAAreas ·
getFloors · setFloor · setColorblindSafe · setViewMode ·
getViewMode · zoomIn · zoomOut · zoomToFit · destroy
All asynchronous command failures reject with SeatLayerError. Inventory
outcomes such as sold_out, not_enough_together, expired holds and conflicts
remain distinct codes suitable for buyer-facing recovery.
Subscribe with controller.on(name, listener). The returned function removes
the listener.
useEffect(() => {
const offHold = controller.on('holdChanged', persistOpenHold);
const offExpired = controller.on('holdExpired', returnBuyerToSelection);
const offError = controller.on('error', reportSeatLayerError);
return () => {
offHold();
offExpired();
offError();
};
}, [controller]);Events: ready · selectionChanged · holdChanged · holdRestored ·
holdExpired · selectionValidityChanged · selectionValid ·
selectionInvalid · selectionLimit · accessExpired · accessUnavailable ·
selectedObjectsUnavailable · error · hint · gaClick · seatHover ·
deckTap · checkout · unknownEvent
Unknown future events remain observable through unknownEvent; adding a bundle
event does not crash an older app.
The app selects and holds inventory. Your trusted backend validates payment, inspects the hold and creates the booking.
- Never ship a SeatLayer secret key in JavaScript, the app bundle or WebView.
- Send only
holdIdand normal checkout context to your backend. - Calculate the amount from server-inspected hold items, not device input.
- Use a stable order id as the booking reference for safe retries.
- Do not enable arbitrary navigation inside the SDK WebView.
Read holds and checkout before connecting a payment flow.
The SDK loads the immutable hosted seatlayer-js@0.66.0/mobile.html document
from https://cdn.seatlayer.io. This gives every platform the mintable HTTPS
origin https://cdn.seatlayer.io and lets the browser runtime load its pinned
lazy assets. Buyer-access sessions must be minted for that exact allowed origin;
tokens never belong in a URL, JavaScript source, or app logs.
Configure buyerAccessTokenProvider with a function that calls your own backend
mint endpoint. Private configuration and selection policies fail closed if the
loaded runtime does not advertise the required bridge capabilities.
The protocol guarantees:
- range-negotiated compatibility before rendering;
- one response per command using correlation ids;
- native command timeouts and late-reply rejection;
- monotonic event ordering per event type; and
- forward-compatible unknown events and fields.
See the bridge contract for the wire-level details.
- Use a fixed-height or full-screen parent; do not put the map inside a vertical
ScrollView. - Keep
configurationstable withuseMemo. - Change
reloadKeyto deliberately rebuild the WebView. useSeatLayerControllerdisposes the controller automatically.- Persist an open
holdIdand callresumeHoldafter app restoration.
pnpm install
pnpm validate
cd example && pnpm install && pnpm startpnpm validate type-checks, runs protocol tests, builds ESM/CommonJS/types,
and validates the npm tarball. Production loads the exact hosted runtime; the
package no longer generates or ships an unused inline Web document.
- React Native mobile guide
- Buyer SDK installation
- Complete checkout example
- Agent-readable documentation
- SeatLayer GitHub organization
| Surface | Package or source |
|---|---|
| JavaScript | @seatlayer/js |
| React | @seatlayer/react |
| Flutter | seatlayer |
| iOS | seatlayer-ios |
| Android | seatlayer-android |
| Server SDKs | Node.js, Python, PHP, Ruby, .NET, Java, and Go |
MIT © SeatLayer