React
Install: pnpm add @watchtowerobservability/browser
Initialize
import { init } from "@watchtowerobservability/browser";
import { WatchtowerErrorBoundary, useRouteTracking } from "@watchtowerobservability/browser/react";
const wt = init({ endpoint: "https://edge.example", publishableKey: "wtp_...", service: "web" });
// <WatchtowerErrorBoundary client={wt}><App /></WatchtowerErrorBoundary>
// inside a router child: useRouteTracking(useLocation().pathname, useParams())Replay and privacy
Replay is off until enabled in project settings or replay.enabled. Default mask level is strict: all text is masked and inputs are never recorded. Per element:
data-wt-maskmasks the element's text.data-wt-blockremoves the element and its subtree from the recording.data-wt-unmaskre-shows text (only below strict level).
Exclude routes with replay: { excludeRoutes: ["/billing", /^\/admin/] }.
Content Security Policy
Replay chunks are compressed in a worker, and data is sent to your Watchtower edge:
worker-src blob:;
connect-src 'self' https://<your-watchtower-edge>;
script-src 'self';The recorder chunk (replay.js) is served from your own origin.
Source maps
Use the build plugin so errors resolve to original code. The upload key is a secret API key from WT_API_KEY, never the publishable key. Maps are deleted after upload by default.
Vite: watchtower({ api, project }) from @watchtowerobservability/browser/vite-plugin.
Replay, issues and traces
Errors captured by the SDK become issues. An issue links to the replay of the first affected session, and a session's trace_id links to the backend trace. Linking replays to MCP clients is Phase 5.