---
id: 08-react-provider
epic: product-analytics-channel
title: Add React provider to @repo/core-analytics
type: technical-story
status: done
feature: core-analytics
depends-on: [02-recording-analytics]
blocks: [09-documentation]
created: 2026-05-18T12:07:00Z
updated: 2026-05-18T15:56:54.277Z
---

## Goal

Add a `./react` subpath export to `@repo/core-analytics` containing `<AnalyticsProvider value={IAnalytics}>` and `useAnalytics(): IAnalytics`. `useAnalytics()` throws a clear error when called outside a provider. No auto-wired router events.

## Why

Server-side use cases receive analytics through `BindContext.analytics`. Client-side components need an equivalent contract surface so `analytics.track(...)` reads the same whether called from a use case or a React component. The provider bridges `IAnalytics` from DI land to React's context tree without coupling consumers to a specific vendor.

## Done when

- `@repo/core-analytics/react` subpath exports `AnalyticsProvider` and `useAnalytics`.
- `useAnalytics()` throws a named error (`AnalyticsContextError` or similar) when called outside `<AnalyticsProvider>`.
- React Testing Library test: render a child inside `<AnalyticsProvider value={recordingAnalytics}>`, child calls `useAnalytics().track("test.event")`, assert `recordingAnalytics.tracked` contains the event.
- All gates pass.

## In scope

- `packages/core-analytics/src/react/analytics-provider.tsx` + `useAnalytics.ts` (or colocated).
- `packages/core-analytics/src/react/index.ts` — subpath barrel.
- `package.json` `exports` map: `"./react": "./dist/react/index.js"` (or equivalent for the build config).
- React Testing Library test.

## Out of scope

- Auto-wiring Next App Router or TanStack Router route-change hooks (deferred per PRD).
- SSR hydration concerns — provider is a pure context wrapper; consumers handle hydration.

## Tasks

- [x] Add `AnalyticsProvider` + `useAnalytics()` to `packages/core-analytics/src/react/`, wire `./react` subpath export in `package.json`, write React Testing Library test using `RecordingAnalytics` asserting `track` flows through context — all gates pass on this commit.
