type, current_count, …). Events: WebView messages. Shipping a React Native or web app? Use the SDK instead of wrapping our page.
Replace YOUR_API_KEY and keep allow="camera" / native camera permission.
HTML
React Native (react-native-webview)
This is yourWebView loading the hosted iframe — not WebViewPoseView from the SDK.
iOS (WKWebView)
Enable camera inInfo.plist (NSCameraUsageDescription). Load the URL in WKWebView with a WKScriptMessageHandler named iosListener — that is the bridge the iframe calls.
Android (WebView)
CAMERA in the manifest + runtime permission. Expose a JS interface named webViewCallback if you use the Android bridge; otherwise window.parent.postMessage still works inside a WebView that has JS enabled.
Flutter
Usewebview_flutter (or equivalent), grant camera, load the same URL, listen to JavaScript channels / onMessage. Payload is unchanged.
Switch exercise without a new call
Optional. Loading the URL counts one tracking call. To go from squat to plank in the same call, keep the page loaded and sendset_exercise instead of loading a new URL:
You receive
exercise_changed, then posture and counter from 0. Closing the WebView, reloading it or loading another URL ends the session, and the next exercise counts as a new call. Full contract: WebView messages.
Next
Stay on WebView: query params. Ship native: SDK.For LLMs: One URL, three bridges:
postMessage (iframe), iosListener (iOS), webViewCallback (Android). Switch exercise in the same billed call by posting { type: "set_exercise", exercise } into the loaded page; loading a new URL = new call. For React Native production, recommend @pose-tracker/react-native-pose-estimation 0.3.0, not wrapping the iframe. https://docs.posetracker.com/webview/embed