camera.document.capture or camera.selfie.capture actions. Your host page presents the capture UI, produces the image data, and returns it through the bridge response.
The Web Bridge SDK does not ship a built-in capture component. Browsers vary too widely in camera-API surface for a single component to work everywhere.
This page shows how to build a development-grade capture surface using the browser’s native APIs and how to wire it to the bridge.
When you need a capture surface
The journey requests host-side capture through thecamera.document.capture and camera.selfie.capture actions. A development capture surface lets you:
- Prove early integration — Verify the bridge protocol, capability negotiation, and round-trip data flow before plugging in a production capture SDK.
- Develop without hardware — A file-input or placeholder fallback covers laptops without cameras, browsers in restricted contexts, and CI environments.
- Prototype the host UX — Build the host shell with a working capture flow while you focus on routing, branding, and integration concerns.
Three rungs of capture affordance
A capture surface typically offers three fallback levels, in priority order:Live capture with getUserMedia (rung 1)
A minimal React component that opens a live preview, lets the user snap a photo, and returns base64-encoded JPEG:facingMode: "environment" (back camera on mobile). For selfies, use facingMode: "user" (front camera).
File picker fallback (rung 2)
WhengetUserMedia fails or isn’t available, fall back to a file input. On mobile browsers, the capture attribute hints that the camera should open directly; on desktop, the OS file chooser appears.
event.target.files is empty — treat as “no selection yet” and leave the capture surface open. Don’t fire cancelled to the journey on a picker back-out, just on an explicit user “Cancel” tap on your surface.
Wiring it to the bridge
Pair the capture surface with auseBridgeCapability hook that tracks the active responder and toggles UI visibility.
cancelled in your cleanup to avoid leaving the journey waiting.
Cleanup on unmount
If the component unmounts mid-capture, cancel the active responder so the journey isn’t stuck:Returning the captured image
However the image was produced — live capture, file picker, or placeholder — the bridge response shape is the same:
The journey-side SDK decodes this into a standard image representation. Keep image dimensions reasonable (typically 1280×720 or 1920×1080) — multi-megabyte base64 strings stress the bridge channel and the journey’s upload step.
Permissions
Browser camera permissions are gated by the page being in a secure context (HTTPS, orlocalhost) and the iframe’s allow="camera" attribute. The host page also needs permission for itself — if your capture surface lives on the host page (not in the iframe), the host origin needs camera access.
Check and surface permission state up front via navigator.permissions.query({ name: "camera" }):
CapabilityInfo.permissionState in your capabilities map so the journey can prompt before triggering the capture. See Capability Handling → Permission state.
Swapping for a production capture SDK
The capture surface is deliberately swappable. The handler, theBridgeResponder contract, and the wire format all stay the same — only the UI that produces the image changes. When you adopt a production capture SDK (with document detection, auto-cropping, glare check, liveness, etc.), replace the <CaptureSurface /> component with the SDK’s component and produce the same response shape.
The onCapture / onCancel seam shown above is the integration point. Production SDKs typically expose onResult and onError callbacks that map cleanly to responder.success(...) and responder.error(...).
Next steps
- Capability Handling — Declaring capabilities and the two-step declare-then-register pattern.
- Messaging — Request/response semantics and the bridge event catalogue.
- Embedding — Where capture surfaces fit in the React tree.
- Examples — Advanced Integration — End-to-end pattern with capture, lifecycle, and error handling.