Skip to content

seatlayer/seatlayer-react-native

Repository files navigation

SeatLayer for React Native

npm React Native Expo License: MIT

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.1.x using a SeatLayer test event and physical iOS and Android devices before production rollout.

Install

Expo

npm install @seatlayer/react-native
npx expo install react-native-webview

No custom native SeatLayer module is used, so this SDK works with Expo Go when the installed Expo SDK includes react-native-webview.

React Native Community CLI

npm install @seatlayer/react-native react-native-webview
npx pod-install

React Native autolinks react-native-webview on Android and iOS.

Quick start

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);
  }
}

Commands

hold · resumeHold · extendHold · release · releaseLabels · bestAvailable · holdGA · setSeatTier · getSelection · getCurrentHold · getGAAreas · getFloors · setFloor · setColorblindSafe · 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.

Events

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 · error · hint · gaClick · seatHover · deckTap · checkout · unknownEvent

Unknown future events remain observable through unknownEvent; adding a bundle event does not crash an older app.

Security boundary

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 holdId and 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.

How the bridge works

The npm package embeds the verified seatlayer-js@0.30.1 bundle in generated inline HTML. This avoids the inconsistent local-file behavior of iOS and Android WebViews while keeping the SDK JavaScript independent of a runtime CDN download. Chart data and live inventory still come from the configured SeatLayer API.

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.

Layout and lifecycle

  • Use a fixed-height or full-screen parent; do not put the map inside a vertical ScrollView.
  • Keep configuration stable with useMemo.
  • Change reloadKey to deliberately rebuild the WebView.
  • useSeatLayerController disposes the controller automatically.
  • Persist an open holdId and call resumeHold after app restoration.

Development

pnpm install
pnpm validate
cd example && pnpm install && pnpm start

pnpm validate regenerates the embedded document, type-checks, runs protocol tests, builds ESM/CommonJS/types, and validates the npm tarball.

Related resources

License

MIT © SeatLayer

About

Official SeatLayer React Native SDK — interactive seat maps, browser holds, typed bridge, and iOS/Android WebView support.

Topics

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages