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

# Integration Checklist

> Step-by-step walkthrough from zero to a working GBGBridge integration.

A step-by-step walkthrough from zero to a working GBGBridge integration. Follow this page in order; each step links to the detailed guide if you need more context.

## Prerequisites

* [ ] Xcode 15.0+ with Swift 5.9+
* [ ] An iOS project targeting iOS 15.0+
* [ ] Access to the GBGBridge SPM package or XCFramework
* [ ] A journey URL from the GBG Go Core SDK (see [Journey URL](/docs/go-v2/developer-integration/sdks/ios/journey-url))

## Step 1: Add the SDK

Add GBGBridge via Swift Package Manager:

1. Navigate to **File** > **Add Package Dependencies...**
2. Enter the GBGBridge package URL.
3. Select **Up to Next Major Version** from `1.0.0`.
4. Click **Add Package** and ensure `GBGBridge` is linked to your app target.

Alternatively, drag the `GBGBridge.xcframework` into your project and set it to **Embed & Sign**.

<Note>See [Getting Started — Installation](/docs/go-v2/developer-integration/sdks/ios/getting-started#installation) for full details.</Note>

## Step 2: Obtain a journey URL

Your app needs a journey URL to load inside the bridge WebView. This URL is generated server-side using the **GBG Go Core SDK** — your backend calls the Core SDK, receives a session URL, and passes it to the iOS app.

<Note>See [Journey URL](/docs/go-v2/developer-integration/sdks/ios/journey-url) for the full pattern, including URL shape, authentication, and configuration options.</Note>

## Step 3: Add Info.plist entries

Add usage descriptions for any device capabilities your integration uses:

```xml theme={null}
<!-- Required for document and selfie capture -->
<key>NSCameraUsageDescription</key>
<string>Camera access is required for document capture.</string>

<!-- Optional: if using photo library fallback -->
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is used to select document images.</string>

<!-- Optional: if using NFC -->
<key>NSNFCReaderUsageDescription</key>
<string>NFC is used to read identity document chips.</string>
```

For NFC, also add the **Near Field Communication Tag Reading** capability in Signing & Capabilities.

## Step 4 — Initialize BridgeHost

Create a `BridgeHost` — this is the coordinator that routes messages between the WebView and your native code.

```swift theme={null}
import GBGBridge

@StateObject private var host = BridgeHost(hostVersion: "1.0.0")
```

## Step 5: Set up capture handlers

Attach handlers to the typed capability slots. Setting a handler declares that your app supports that capability — no separate configuration step.

### Option A: Stub Views (Development / Early Integration)

Use the built-in stub views to prove the bridge works without the SmartCapture SDKs:

```swift theme={null}
host.documentCapture.handler = { [weak host] request in
    guard let host else { return .cancelled(reason: "Host deallocated") }
    return await host.documentCapture.awaitCompletion()
}

host.selfieCapture.handler = { [weak host] request in
    guard let host else { return .cancelled(reason: "Host deallocated") }
    return await host.selfieCapture.awaitCompletion()
}
```

Then present the stub views when a request arrives:

```swift theme={null}
.fullScreenCover(isPresented: $showDocumentCamera) {
    StubDocumentCameraView(
        onCaptured: { result in
            host.documentCapture.complete(.document(result))
        },
        onCancelled: {
            host.documentCapture.complete(.cancelled(reason: "User dismissed"))
        }
    )
}

.fullScreenCover(isPresented: $showSelfieCamera) {
    StubSelfieCameraView(
        onCaptured: { result in
            host.selfieCapture.complete(.selfie(result))
        },
        onCancelled: {
            host.selfieCapture.complete(.cancelled(reason: "User dismissed"))
        }
    )
}
```

<Note>See [Stub Camera Views](/docs/go-v2/developer-integration/sdks/ios/stub-camera-views) for details on the stubs and how to swap them for real SDKs.</Note>

### Option B: SmartCapture SDKs (Production)

Replace the stub views with the GBG SmartCapture document and face camera SDKs. The handler setup is identical — only the view presented inside `fullScreenCover` changes.

<Note>See the SmartCapture Integration Guide (coming soon) for the full walkthrough.</Note>

## Step 6: Set permission state

Report camera permission state so the web journey can check permissions before attempting capture:

```swift theme={null}
let camera = CameraDetector.check()
host.documentCapture.permissionState = camera.permissionState
host.selfieCapture.permissionState = camera.permissionState
```

## Step 7: Display the journey

Use `BridgeWebView` to load the journey URL. It handles WebView creation, bootstrap script injection, and message handler registration automatically.

```swift theme={null}
struct JourneyView: View {
    @StateObject private var host = BridgeHost(hostVersion: "1.0.0")
    let journeyURL: URL

    var body: some View {
        BridgeWebView(url: journeyURL, host: host)
            .onAppear { setupHandlers() }
            .onChange(of: host.documentCapture.activeRequest?.correlationId) { _ in
                showDocumentCamera = host.documentCapture.activeRequest != nil
            }
            .onChange(of: host.selfieCapture.activeRequest?.correlationId) { _ in
                showSelfieCamera = host.selfieCapture.activeRequest != nil
            }
            // Present camera views as fullScreenCovers (see Step 5)
    }
}
```

<Note>See [Embedding Guide](/docs/go-v2/developer-integration/sdks/ios/embedding) for SwiftUI and UIKit integration patterns.</Note>

## Step 8 — Build and Run

1. Build and run on a physical device (camera capture requires real hardware).
2. The web journey loads in the WebView.
3. When the journey reaches a document or selfie step, the bridge sends a capture request.
4. Your handler runs, the camera view presents, the user captures, and the result flows back to the web journey.

### Verify It Works

Check for these signs of a successful integration:

* The web journey loads and renders correctly in the WebView.
* `capability.query` is handled automatically — the journey knows which capabilities your app supports.
* Document capture requests trigger your camera view, and the captured image is returned to the journey.
* Selfie capture requests trigger your selfie view, and the result is returned.
* Cancellation flows work — dismissing the camera sends a `cancelled` response.

### Common Issues

| Symptom                                | Likely Cause                 | Fix                                                                                |
| -------------------------------------- | ---------------------------- | ---------------------------------------------------------------------------------- |
| Blank WebView                          | ATS blocking HTTP URL        | Use HTTPS, or add `NSAllowsLocalNetworking` for local dev                          |
| `capability.query` returns empty       | No handlers set              | Set `handler` on at least one typed slot before loading the URL                    |
| Camera view never appears              | `activeRequest` not observed | Wire up `.onChange(of: host.documentCapture.activeRequest)`                        |
| Capture result not received by journey | `complete()` not called      | Ensure your camera view calls `host.documentCapture.complete()` on every exit path |

<Note>See [Troubleshooting](/docs/go-v2/developer-integration/sdks/ios/troubleshooting) for a comprehensive diagnostic guide.</Note>

## Complete Minimal Example

Putting it all together — a minimal SwiftUI app that loads a journey and handles document capture with a stub view:

```swift theme={null}
import GBGBridge
import SwiftUI

struct JourneyView: View {
    @StateObject private var host = BridgeHost(hostVersion: "1.0.0")
    @State private var showDocumentCamera = false
    let journeyURL: URL

    var body: some View {
        BridgeWebView(url: journeyURL, host: host)
            .onAppear {
                let camera = CameraDetector.check()
                host.documentCapture.permissionState = camera.permissionState

                host.documentCapture.handler = { [weak host] request in
                    guard let host else { return .cancelled(reason: "Host deallocated") }
                    return await host.documentCapture.awaitCompletion()
                }
            }
            .onChange(of: host.documentCapture.activeRequest?.correlationId) { _ in
                showDocumentCamera = host.documentCapture.activeRequest != nil
            }
            .fullScreenCover(isPresented: $showDocumentCamera, onDismiss: {
                if host.documentCapture.activeRequest != nil {
                    host.documentCapture.complete(.cancelled(reason: "Dismissed"))
                }
            }) {
                StubDocumentCameraView(
                    onCaptured: { result in
                        host.documentCapture.complete(.document(result))
                    },
                    onCancelled: {
                        host.documentCapture.complete(.cancelled(reason: "User dismissed"))
                    }
                )
            }
    }
}
```

<Note>See [Hello Journey](/docs/go-v2/developer-integration/sdks/ios/examples/hello-journey) for the full annotated example.</Note>

## What's Next

Once the basic integration is working:

* Add selfie capture — same pattern as document capture, using `host.selfieCapture`.
* Add custom capabilities (NFC, biometrics) — see [Capability Handling](/docs/go-v2/developer-integration/sdks/ios/capability-handling).
* Replace stub views with SmartCapture SDKs for production-quality capture.
* Review the [Security Guide](/docs/go-v2/developer-integration/sdks/ios/security) before shipping to production.
