# React Router Feature Flags installation - Docs

1.  1

    ## Install the package

    Required

    Install the PostHog JavaScript library and React SDK using your package manager:

    PostHog AI

    ### npm

    ```bash
    npm install --save posthog-js @posthog/react
    ```

    ### yarn

    ```bash
    yarn add posthog-js @posthog/react
    ```

    ### pnpm

    ```bash
    pnpm add posthog-js @posthog/react
    ```

2.  2

    ## Configure Vite

    Required

    Add `posthog-js` and `@posthog/react` to `ssr.noExternal` in your `vite.config.ts` to avoid SSR errors:

    vite.config.ts

    PostHog AI

    ```typescript
    // ... imports
    export default defineConfig({
      plugins: [tailwindcss(), reactRouter(), tsconfigPaths()],
      ssr: {
        noExternal: ['posthog-js', '@posthog/react'],
      },
    });
    ```

3.  3

    ## Add the PostHogProvider

    Required

    Initialize PostHog and wrap your app with the `PostHogProvider` in your `app/entry.client.tsx` file:

    app/entry.client.tsx

    PostHog AI

    ```typescript
    import { startTransition, StrictMode } from "react";
    import { hydrateRoot } from "react-dom/client";
    import { HydratedRouter } from "react-router/dom";
    import posthog from "posthog-js";
    import { PostHogProvider } from "@posthog/react";
    posthog.init("<ph_project_token>", {
      api_host: "https://us.i.posthog.com",
      defaults: "2026-01-30",
    });
    startTransition(() => {
      hydrateRoot(
        document,
        <PostHogProvider client={posthog}>
          <StrictMode>
            <HydratedRouter />
          </StrictMode>
        </PostHogProvider>,
      );
    });
    ```

4.  4

    ## Send events

    Click around and view a couple pages to generate some events. PostHog automatically captures pageviews, clicks, and other interactions for you.

    If you'd like, you can also manually capture custom events:

    JavaScript

    PostHog AI

    ```javascript
    posthog.capture('my_custom_event', { property: 'value' })
    ```

5.  5

    ## Client-side rendering

    Required

    **Basic flag implementation**

    ```javascript
    if (posthog.isFeatureEnabled('flag-key')) {
        // Do something differently for this user
        // Optional: fetch the payload
        const matchedFlagPayload = posthog.getFeatureFlagPayload('flag-key')
    }
    ```

    **Multivariate flags**

    ```javascript
    if (posthog.getFeatureFlag('flag-key') == 'variant-key') { // replace 'variant-key' with the key of your variant
        // Do something differently for this user
        // Optional: fetch the payload
        const matchedFlagPayload = posthog.getFeatureFlagPayload('flag-key')
    }
    ```

6.  6

    ## Server-side rendering

    Required

    Use `posthog-node` to evaluate feature flags on the server. You can access PostHog in a React Router loader:

    app/routes/example.tsx

    PostHog AI

    ```typescript
    import { PostHog } from 'posthog-node'
    import type { Route } from './+types/example'
    export async function loader({ request }: Route.LoaderArgs) {
        const posthog = new PostHog(process.env.VITE_PUBLIC_POSTHOG_TOKEN!, {
            host: process.env.VITE_PUBLIC_POSTHOG_HOST
        })
        try {
            // use posthog for feature flags here
        } finally {
            await posthog.shutdown()
        }
    }
    ```

    **Basic flag implementation**

    ```javascript
    const isFeatureFlagEnabled = await client.isFeatureEnabled('flag-key', 'distinct_id_of_your_user')
    if (isFeatureFlagEnabled) {
        // Your code if the flag is enabled
        // Optional: fetch the payload
        const matchedFlagPayload = await client.getFeatureFlagPayload('flag-key', 'distinct_id_of_your_user', isFeatureFlagEnabled)
    }
    ```

    **Multivariate flags**

    ```javascript
    const enabledVariant = await client.getFeatureFlag('flag-key', 'distinct_id_of_your_user')
    if (enabledVariant === 'variant-key') {  // replace 'variant-key' with the key of your variant
        // Do something differently for this user
        // Optional: fetch the payload
        const matchedFlagPayload = await client.getFeatureFlagPayload('flag-key', 'distinct_id_of_your_user', enabledVariant)
    }
    ```

7.  7

    ## Running experiments

    Optional

    Experiments run on top of our feature flags. Once you've implemented the flag in your code, you run an experiment by creating a new experiment in the PostHog dashboard.

8.  8

    ## Next steps

    Recommended

    Now that you're evaluating flags, continue with the resources below to learn what else Feature Flags enables within the PostHog platform.

    | Resource | Description |
    | --- | --- |
    | [Creating a feature flag](/docs/feature-flags/creating-feature-flags.md) | How to create a feature flag in PostHog |
    | [Adding feature flag code](/docs/feature-flags/adding-feature-flag-code.md) | How to check flags in your code for all platforms |
    | [Framework-specific guides](/docs/feature-flags/tutorials.md#framework-guides) | Setup guides for React Native, Next.js, Flutter, and other frameworks |
    | [How to do a phased rollout](/tutorials/phased-rollout.md) | Gradually roll out features to minimize risk |
    | [More tutorials](/docs/feature-flags/tutorials.md) | Other real-world examples and use cases |

### Community questions

Ask a question

### Was this page useful?

HelpfulCould be better