# Provider setup

URL: https://supapulse.app/docs/react/provider

How SupapulseProvider creates and initializes the tracker, what its context holds, and where to put it.

```tsx
import { SupapulseProvider } from '@supapulse/react';

const config = { apiToken: 'pub_your_token' };

<SupapulseProvider config={config}>{children}</SupapulseProvider>;
```

## Props [#props]

| Prop | Type | Required | Notes |
| --- | --- | --- | --- |
| `config` | `SupapulseConfig` | Yes | Passed to `init()`. Same options as [core](https://supapulse.app/docs/core/configuration). |
| `children` | `ReactNode` | Yes | |

## What it does [#what-it-does]

1. On first render, creates one `Supapulse` instance and keeps it for the provider's lifetime.
2. In an effect after mounting, calls `supapulse.init(config)`. With default options, that sends the first pageview and starts following route changes.
3. Sets `isReady` to `true`, or stores the error if `init()` threw.

The effect re-runs when `config` changes identity, but `init()` ignores repeat calls. Changing the token on a mounted provider has no effect; remount it with a `key` if you need to switch sites.

## The context [#the-context]

```ts
interface SupapulseContextValue {
  supapulse: SupapulseCore; // available from the first render
  isReady: boolean;
  autoPageviews: boolean; // false when config.autoPageviews is false
  error: Error | null;
}
```

Read it directly when you need `isReady` or `error`:

```tsx
import { SupapulseContext } from '@supapulse/react';
import { useContext } from 'react';

function AnalyticsStatus() {
  const context = useContext(SupapulseContext);
  if (context?.error) {
    return <p>Analytics failed to start: {context.error.message}</p>;
  }
  return null;
}
```

## Placement [#placement]

- **One provider per app.** Each provider creates its own tracker, so two providers send every pageview twice.
- **As high as possible.** Above the router, so it isn't remounted on navigation.
- **Client side in Next.js App Router.** Put it in a `'use client'` component; see [SSR support](https://supapulse.app/docs/react/ssr).

## Initialization errors [#initialization-errors]

`init()` only throws when there's no `window`, which can't happen inside an effect. A missing or wrong token doesn't throw: requests fail with `401` and, with `debug: true`, the console logs `[Supapulse] Send failed`.
