> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go.gbgplc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript Bridge SDK

> Enable native device capabilities in embedded GBG GO web journeys

The TypeScript Bridge SDK enables bidirectional communication between the GBG GO web journey and the native host app it runs inside. It handles environment detection, capability discovery, and request/response messaging so the web journey can use native device features like camera capture, NFC, and biometrics.

The SDK works across all embedding environments — iOS `WKWebView`, Android `WebView`, iframe, and standalone browser — with automatic environment detection and progressive enhancement.

## Packages

The SDK is published as two npm packages — the core library you can use anywhere, and a thin React wrapper if you're using React 19+:

| Package                                    | Description                                                     |
| ------------------------------------------ | --------------------------------------------------------------- |
| `@gbgplc-internal/ggo-native-bridge`       | Core library — pure TypeScript, zero dependencies               |
| `@gbgplc-internal/ggo-native-bridge-react` | React bindings — context provider and hooks (requires React 19) |

## Installation

To install the SDK, run one of the commands below:

```bash theme={null}
# Core library only
npm install @gbgplc-internal/ggo-native-bridge

# Core + React bindings
npm install @gbgplc-internal/ggo-native-bridge @gbgplc-internal/ggo-native-bridge-react
```

Both packages are ES modules and ship TypeScript declarations.

## Quick start: Core library

Get a singleton bridge instance, check the environment, request a native capability, and listen for host events — all from plain TypeScript:

```typescript theme={null}
import { NativeBridge, BridgeError } from '@gbgplc-internal/ggo-native-bridge';

// Get the bridge singleton
const bridge = NativeBridge.getInstance();

// Check the environment
console.log(bridge.environment); // 'ios' | 'android' | 'iframe' | 'standalone'
console.log(bridge.isEmbedded);  // true if inside a host

// Discover what the host supports
const capabilities = await bridge.discoverCapabilities();

// Request a native capability
if (bridge.hasCapability('camera.document')) {
  try {
    const response = await bridge.request('camera.document.capture', {
      documentType: 'passport',
      side: 'front',
    });
    console.log('Capture result:', response.data);
  } catch (error) {
    if (error instanceof BridgeError) {
      console.error(`[${error.code}]: ${error.message}`);
    }
  }
}

// Emit events to the host
bridge.emit('journey.started', { journeyId: 'abc-123', timestamp: Date.now() });

// Listen for events from the host
const unsubscribe = bridge.on('host.navigation.back', (data) => {
  console.log('Host requested back navigation:', data);
});
```

## Quick start: React

Wrap your app in `<BridgeProvider>` and use the hooks — `useBridge` for environment and capability state, `useNativeCamera` for capture requests with web fallback:

```tsx theme={null}
import { BridgeProvider, useBridge, useNativeCamera } from '@gbgplc-internal/ggo-native-bridge-react';

function App() {
  return (
    <BridgeProvider>
      <JourneyScreen />
    </BridgeProvider>
  );
}

function JourneyScreen() {
  const { environment, isEmbedded, capabilitiesReady } = useBridge();
  const { isNativeAvailable, requestCapture } = useNativeCamera('document');

  if (!capabilitiesReady) return <p>Discovering capabilities...</p>;

  return (
    <div>
      <p>Running in: {environment}</p>
      <button
        onClick={async () => {
          if (isNativeAvailable) {
            const result = await requestCapture({ side: 'front' });
            console.log('Native capture:', result.data);
          } else {
            console.log('Use web fallback camera');
          }
        }}
      >
        Capture Document
      </button>
    </div>
  );
}
```

## Environment behaviour

| Environment        | `environment`  | `isEmbedded` | Capabilities                              | Requests             |
| ------------------ | -------------- | ------------ | ----------------------------------------- | -------------------- |
| iOS WKWebView      | `'ios'`        | `true`       | Queries host via `webkit.messageHandlers` | Sent to iOS host     |
| Android WebView    | `'android'`    | `true`       | Queries host via `GBGBridge.postMessage`  | Sent to Android host |
| iframe             | `'iframe'`     | `true`       | Queries parent via `postMessage`          | Sent to parent frame |
| Standalone browser | `'standalone'` | `false`      | Returns empty `{}`                        | Silently dropped     |

In standalone mode, the bridge is fully functional but reports no capabilities. This enables progressive enhancement — your app works in any environment, and native features activate automatically when a host is present.

## Standard capabilities

| Capability ID        | Description                                |
| -------------------- | ------------------------------------------ |
| `camera.document`    | Document capture (passport, licence, etc.) |
| `camera.selfie`      | Selfie/face capture                        |
| `nfc.read`           | NFC document chip reading                  |
| `biometric.auth`     | Biometric authentication                   |
| `device.attestation` | Device integrity attestation               |
| `location.gps`       | GPS location                               |
| `storage.secure`     | Secure on-device storage                   |
| `analytics.forward`  | Analytics event forwarding                 |

## Common pitfalls

Watch out for these common integration mistakes:

* **Don't use the bridge in SSR**: it requires `window` and browser APIs. In Next.js, ensure bridge code only runs on the client. See the [Next.js usage guide](/docs/go-v2/developer-integration/sdks/typescript/nextjs).
* **Always check capabilities before requesting**: don't assume a capability is available. Use `hasCapability()` or the `useCapability()` hook first.
* **Handle timeouts**: the default request timeout is 30 seconds. Camera requests via `useNativeCamera` use 120 seconds.
* **Call `discoverCapabilities()` early**: `<BridgeProvider>` does this automatically, but if using the core library directly, call it early in your app lifecycle.
* **The bridge is a singleton**: `NativeBridge.getInstance()` always returns the same instance. Options are only used on the first call.

## Guides

* [Configuration](/docs/go-v2/developer-integration/sdks/typescript/configuration) — Bridge options, timeouts, and React provider configuration
* [React hooks](/docs/go-v2/developer-integration/sdks/typescript/react) — `useBridge`, `useCapability`, `useNativeCamera`, `useBridgeEvent`
* [Error handling](/docs/go-v2/developer-integration/sdks/typescript/error-handling) — Typed error codes, recoverability, and handling patterns
* [Security](/docs/go-v2/developer-integration/sdks/typescript/security) — Transport security, iframe origin validation, PII handling
* [Next.js usage](/docs/go-v2/developer-integration/sdks/typescript/nextjs) — App Router and Pages Router integration
* [API reference](/docs/go-v2/developer-integration/sdks/typescript/api-reference) — Complete reference for all public exports
