Skip to main content
Every stack loads the same URL and listens to the same JSON (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 your WebView loading the hosted iframe — not WebViewPoseView from the SDK.
Declare camera permission in the host app (Permissions still apply). For a production RN app, prefer the SDK quickstart.

iOS (WKWebView)

Enable camera in Info.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

Use webview_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 send set_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
Last modified on October 16, 2026