Skip to main content

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.

A minimal integration that loads a web-based identity journey inside a native iOS app. This example compiles and runs as a standalone SwiftUI app.

What This Example Demonstrates

  • Initializing a BridgeHost with typed capability slots
  • Declaring document capture support via handler assignment
  • Displaying a journey using BridgeWebView
  • Observing bridge errors

Complete Source

import GBGBridge
import SwiftUI

// MARK: - App Entry Point

@main
struct HelloJourneyApp: App {
    var body: some Scene {
        WindowGroup {
            JourneyView()
        }
    }
}

// MARK: - Journey View

struct JourneyView: View {
    // 1. Create the bridge host
    @StateObject private var host = BridgeHost(hostVersion: "1.0.0")

    // 2. Set the journey URL
    private let journeyURL = URL(string: "https://journey.example.com")!

    var body: some View {
        NavigationStack {
            VStack(spacing: 0) {
                // 3. Embed the bridge-connected WebView
                BridgeWebView(url: journeyURL, host: host)

                // 4. Show errors if any
                if let error = host.lastError {
                    ErrorBanner(message: error) {
                        host.clearError()
                    }
                }
            }
            .navigationTitle("Identity Verification")
            .navigationBarTitleDisplayMode(.inline)
            .onAppear {
                // 5. Declare document capture support by setting a handler
                host.documentCapture.handler = { [weak host] request in
                    guard let host else { return .cancelled(reason: "Host deallocated") }
                    return await host.documentCapture.awaitCompletion()
                }

                // 6. Detect and report camera permission state
                let camera = CameraDetector.check()
                host.documentCapture.permissionState = camera.permissionState
            }
        }
    }
}

// MARK: - Error Banner

struct ErrorBanner: View {
    let message: String
    let onDismiss: () -> Void

    var body: some View {
        HStack {
            Image(systemName: "exclamationmark.triangle.fill")
                .foregroundColor(.white)
            Text(message)
                .font(.caption)
                .foregroundColor(.white)
                .lineLimit(2)
            Spacer()
            Button(action: onDismiss) {
                Image(systemName: "xmark.circle.fill")
                    .foregroundColor(.white.opacity(0.7))
            }
        }
        .padding(.horizontal)
        .padding(.vertical, 8)
        .background(Color.red)
    }
}

How It Works

  1. BridgeHost(hostVersion:) creates a host with typed capability slots. No separate configuration dictionary is needed.
  2. Setting a handler on documentCapture declares the capability as supported. The handler uses awaitCompletion() to suspend until the UI layer calls complete().
  3. CameraDetector.check() detects camera hardware and permission state. The permissionState is included in capability query responses.
  4. BridgeWebView creates a WKWebView, injects the bootstrap script, registers the message handler, attaches the WebView to the host, and loads the journey URL.
  5. Error observation — host.lastError is @Published, so the error banner appears and disappears reactively.

What Happens at Runtime

1. App launches -> JourneyView renders
2. BridgeWebView creates and configures WKWebView
3. Bootstrap script injected (window.GBGBridge namespace created)
4. Journey URL loads, handler set on documentCapture slot
5. Web journey sends: capability.query request
6. Built-in handler responds: { environment: "ios", capabilities: { camera.document: { supported: true, permissionState: "granted" } } }
7. Web journey adapts its flow based on available capabilities and permissions

Required Info.plist Entries

For this minimal example, no special Info.plist entries are needed beyond the defaults. If your journey URL uses HTTP during development, add:
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsLocalNetworking</key>
    <true/>
</dict>

Next Steps