> ## 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.

# Getting Started

> Install GBGBridge and build your first integration in minutes.

This guide walks you through adding GBGBridge to your web project, configuring it, and loading your first web-based identity journey inside an iframe.

## Requirements

| Requirement     | Minimum                            | Notes                                                                                                                                          |
| --------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Browsers        | ES2020 / modern evergreen browsers | The SDK uses native `postMessage`, `MessageEvent`, optional chaining, and ES modules — supported by current Chrome, Firefox, Safari, and Edge. |
| Node.js (build) | 18+                                | Required by the bundler / package manager. Not required at runtime — the SDK runs in the browser.                                              |
| TypeScript      | 5.x                                | Types ship with both packages. Plain JavaScript also works; the API is the same.                                                               |
| React           | 19.x                               | Only required for `@gbg/go-bridge-web-react`. React is a `peerDependency` — your app provides it.                                              |
| Dependencies    | None at runtime                    | Zero runtime dependencies for both packages. React is the only peer dependency for the React package.                                          |

## Installation

GBGBridge is published as two npm packages — the core library and a React wrapper. Install one or both:

```bash theme={null}
# React app: install both — the React wrapper depends on the core
npm install @gbg/go-bridge-web @gbg/go-bridge-web-react

# Vanilla JS / Vue / Angular / Svelte: core only
npm install @gbg/go-bridge-web
```

<Note>
  **Availability:** these packages will publish to public npm via [GGO-13991](https://gbg.atlassian.net/browse/GGO-13991). The SDK source lives in the [reference build](https://github.com/gbgplc/gbg-go-web-reference) under `packages/` until the public package is available — clone the repo and link the packages into your app with `npm link` (or your package manager's equivalent).
</Note>

Both packages are ES modules and ship TypeScript declarations. No build configuration beyond standard bundler defaults is required.

## Minimal Integration (React)

The steps below take you from an empty screen to a running journey: track the iframe element, declare the capabilities you support, register handlers, and render the provider.

### 1. Add the Imports

```tsx theme={null}
import { BridgeHostProvider, useBridgeCapability } from "@gbg/go-bridge-web-react";
import { useState } from "react";
```

### 2. Track the Iframe Element

`BridgeHostProvider` needs the actual `HTMLIFrameElement`, not a ref. Hold it in component state and pass `setIframe` as the iframe's `ref` callback:

```tsx theme={null}
const [iframe, setIframe] = useState<HTMLIFrameElement | null>(null);
```

This pattern is **required**, not stylistic. `useRef` is not reactive, so the provider's host-creation effect would not fire when the iframe mounts.

### 3. Declare the Capabilities You Support

Pass a `capabilities` map to the provider. Each entry tells the embedded journey "the host can fulfil this":

```tsx theme={null}
const capabilities = {
  "camera.document": { supported: true, version: "1.0" },
  "camera.selfie": { supported: true, version: "1.0" },
};
```

This is the **declaration** half of the two-step pattern. Capability IDs are listed in [`CAPABILITY_IDS`](/docs/go-v2/developer-integration/sdks/web/api-reference#capability_ids) — use the constants to avoid string typos.

### 4. Register Handlers

Register a handler for each capability action. `useBridgeCapability` registers on mount and unregisters on unmount; the action ID is the verb (e.g. `"camera.document.capture"`), not the capability ID (`"camera.document"`):

```tsx theme={null}
function DocumentCaptureHandler() {
  useBridgeCapability("camera.document.capture", {
    handle: async (request, responder) => {
      const image = await captureDocument(); // your camera UI
      responder.success({ image });
    },
  });
  return null;
}
```

The handler receives the inbound `BridgeMessage` and a `BridgeResponder`. Call exactly one terminal method on the responder — `success`, `error`, `cancelled`, or `unsupported` — to send the response. `acknowledge()` is optional and may be called before the terminal response for long-running operations.

### 5. Render the Provider and Iframe

Put it all together:

```tsx theme={null}
import { BridgeHostProvider, useBridgeCapability } from "@gbg/go-bridge-web-react";
import { useState } from "react";

export function JourneyView({ journeyUrl }: { journeyUrl: string }) {
  const [iframe, setIframe] = useState<HTMLIFrameElement | null>(null);
  const allowedOrigins = [new URL(journeyUrl).origin];
  const capabilities = {
    "camera.document": { supported: true, version: "1.0" },
  };

  return (
    <BridgeHostProvider
      iframe={iframe}
      allowedOrigins={allowedOrigins}
      hostVersion="1.0.0"
      capabilities={capabilities}
    >
      <DocumentCaptureHandler />
      <iframe ref={setIframe} src={journeyUrl} allow="camera" />
    </BridgeHostProvider>
  );
}

function DocumentCaptureHandler() {
  useBridgeCapability("camera.document.capture", {
    handle: async (request, responder) => {
      const image = await captureDocument();
      responder.success({ image });
    },
  });
  return null;
}
```

### 6. Run Your App

Start your dev server. The journey loads inside the iframe. When it sends a `capability.query` request, GBGBridge automatically responds with the capabilities map you declared, including `permissionState` if set. When the journey invokes `camera.document.capture`, your handler runs and the responder returns the result.

## Alternative: Framework-agnostic (Vanilla JS / Vue / Angular / Svelte)

If you're not using React, use the core `@gbg/go-bridge-web` package directly. The API is identical to what the React wrapper exposes — the wrapper is a thin React adapter, not a separate runtime.

```typescript theme={null}
import { BridgeHost } from "@gbg/go-bridge-web";

const iframe = document.getElementById("journey-frame") as HTMLIFrameElement;
const journeyUrl = "https://journey.example.com";
iframe.src = journeyUrl;

const host = new BridgeHost({
  iframe,
  allowedOrigins: [new URL(journeyUrl).origin],
  hostVersion: "1.0.0",
  capabilities: {
    "camera.document": { supported: true, version: "1.0" },
  },
});

host.registerHandler("camera.document.capture", {
  handle: async (request, responder) => {
    const image = await captureDocument();
    responder.success({ image });
  },
});

// When the journey screen is removed from the page:
// host.detach();
```

The same `BridgeHost` class powers the React wrapper internally — `BridgeHostProvider` instantiates it and handles `detach()` on unmount automatically. With direct usage, you own the lifecycle: call `host.detach()` when the iframe is no longer in use.

## What Happens Under the Hood

When you mount `BridgeHostProvider` (or call `new BridgeHost(...)`):

1. **Iframe attached** — The provider holds off until `iframe` is non-null. Once attached, it instantiates the underlying `BridgeHost` and snapshots the `allowedOrigins`, `hostVersion`, and `capabilities` props. Only an `iframe` change triggers a rebuild — remount the provider to apply runtime config changes.
2. **Message listener installed** — A single `window` `message` listener is attached. Every inbound event is filtered: `event.source` must equal `iframe.contentWindow`, and `event.origin` must normalize to a value in `allowedOrigins`. Events that fail either check are silently dropped.
3. **Envelope validation** — Surviving events are validated against the wire protocol: required fields (`version`, `correlationId`, `type`, `timestamp`, `payload.action`) must be present and well-typed. Malformed envelopes are silently dropped — they never reach handlers or the delegate.
4. **Capability query auto-registration** — A built-in `CapabilityQueryHandler` is registered for the `capability.query` action. The handler reads the effective capability map (your `capabilities` prop merged with any `registerCustomCapability(...)` calls) and responds automatically. You do not register this yourself.

## Required Page Configuration

GBGBridge runs entirely in your page; there is no global config. However, the iframe and your hosting page need a few things wired up so the browser delegates the right permissions and the SDK can reach the journey origin.

### Content Security Policy

If your page sets a CSP, allow the journey origin in `frame-src`:

```
Content-Security-Policy: frame-src https://journey.example.com;
```

If the journey URL might come from multiple origins (staging vs prod), list each one explicitly. Avoid `frame-src *` in production.

### Iframe `allow` Attribute

For capabilities that require browser permissions (camera, microphone, location), set the iframe `allow` attribute so the parent grants those permissions to the iframe context:

```html theme={null}
<iframe src="https://journey.example.com" allow="camera; microphone"></iframe>
```

This is required even when you're handling capture in the host page — the journey may still call `getUserMedia` for preview frames or fallback flows.

### Origin Allowlist Format

Pass exact origin strings to `allowedOrigins`. Format: `<scheme>://<host>` with no trailing slash, no path, no port if it's the scheme default.

```typescript theme={null}
// Correct
allowedOrigins: ["https://journey.example.com", "https://staging.journey.example.com"]

// Wrong — trailing slash, includes path
allowedOrigins: ["https://journey.example.com/", "https://journey.example.com/start"]
```

The SDK normalizes inbound origins before comparing, so case differences in the host are tolerated, but non-default ports and paths must match exactly. Empty `allowedOrigins` arrays throw at construction time — there is no implicit "allow all".

### HTTPS in Production

Browsers block mixed content: an `https://` parent page loading an `http://` iframe will fail silently in most modern browsers. Always serve the journey over HTTPS in production. Local development on `http://localhost` works in both directions because browsers treat `localhost` as secure.

## Common Integration Pitfalls

A handful of issues catch most teams when first wiring up the bridge — usually around the two-step declare-then-register pattern, the iframe-as-state pattern, and origin allowlist formatting.

### Capability query returns the wrong shape

If the embedded journey calls `bridge.hasCapability("camera.document")` and gets `false` even though you've registered a handler, you forgot to pass `capabilities` to the provider. `useBridgeCapability` only registers the handler — it does not declare the capability. Both calls are required. See [Concepts → Declaring vs. Registering](/docs/go-v2/developer-integration/sdks/web/concepts#declaring-vs-registering-capabilities).

### Provider never builds the host

If `host` is null forever, you're probably using `useRef` instead of `useState` for the iframe. Refs are not reactive, so the provider's `useEffect` watching `iframe` never sees a change. Use `const [iframe, setIframe] = useState<HTMLIFrameElement | null>(null)` and pass `setIframe` as the iframe's `ref` callback.

### Messages dropped silently

The transport layer drops inbound messages on three independent checks: `event.source` not matching `iframe.contentWindow`, origin not in `allowedOrigins`, and envelope validation failure. None of these surface to the delegate or `lastError` — they're filtered defensively. Common causes:

* Trailing slashes or paths in `allowedOrigins` entries (must be exact origin strings).
* Inbound port differs from declared origin (e.g. `:443` vs default).
* Journey URL pointing at a redirect — `iframe.contentWindow` ends up on a different origin than the declared `src`.
* Web journey sending a non-conforming envelope (missing `correlationId`, malformed `payload.action`, etc.).

To debug, attach a `delegate.onMessage` callback — it fires after validation, so absence indicates pre-validation drop. If you need to inspect rejected events, you'll need to temporarily attach your own `window.addEventListener("message", ...)` outside the SDK.

### Action vs capability ID confusion

The protocol uses two related strings:

* **Capability ID** (`camera.document`) — appears in the `capabilities` prop and `capability.query` responses.
* **Action ID** (`camera.document.capture`) — appears in `useBridgeCapability(...)`, `registerHandler(...)`, and inbound request `payload.action`.

Register handlers for **action IDs**, declare support for **capability IDs**. They're related but distinct strings.

### Runtime config changes don't apply

`BridgeHostProvider` snapshots `allowedOrigins`, `hostVersion`, and `capabilities` when the underlying `BridgeHost` is built (i.e., when `iframe` transitions from `null` to non-null). Subsequent prop changes do **not** rebuild the host. To apply runtime changes — adding a new allowed origin, updating capabilities — unmount and remount the provider (`key={...}` change is the easiest way), or call `host.registerCustomCapability(...)` directly for dynamic capability additions.

### Outbound messages dropped before iframe.src is set

`HostIframeChannel` resolves `targetOrigin` from `iframe.src` at send time. If `iframe.src` is empty when `host.sendEvent(...)` or `host.respond(...)` fires, the channel cannot resolve a target and silently drops the outbound with a `console.warn`. In vanilla JS, set `iframe.src` before the first outbound send. In React, this is automatic — the iframe renders with its `src` attribute already set.

## Next Steps

* [Concepts](/docs/go-v2/developer-integration/sdks/web/concepts) — Understand the architecture, message protocol, and design rationale.
* [Embedding](/docs/go-v2/developer-integration/sdks/web/embedding) — Patterns for React, framework-agnostic, and SSR-aware integrations.
* [Capability Handling](/docs/go-v2/developer-integration/sdks/web/capability-handling) — Declaring, registering, and dynamic capability negotiation.
* [Security](/docs/go-v2/developer-integration/sdks/web/security) — CSP, origin allowlist, transport safety, and token-exchange patterns.
* [API Reference](/docs/go-v2/developer-integration/sdks/web/api-reference) — Detailed reference for every public symbol.
