PostHog Handbook Library / Docs and Wizard

901 words. Estimated reading time: 5 min.

# Onboarding docs

Onboarding docs, or product installation docs, are special because these instructions are shared between the in-app onboarding flow and the getting started pages on the PostHog website.

These are some of the first pieces of docs a new user will see. They show users how to quickly set up and install a product, so they need to be up to date and accurate.

To help keep in-app and website onboarding docs in sync, there is a single source of truth for the onboarding docs in the `posthog/posthog` repository under the `docs/onboarding` directory. This means you only need to update the in-app onboarding docs in the PostHog monorepo, and the website docs will be updated automatically.

<ProductVideo videoLight= "https://res.cloudinary.com/dmukukwp6/video/upload/posthog_onboarding_docs_13eddf168e.mp4" alt="How shared onboarding docs work" classes="rounded" autoPlay={false} muted={false} />

Video explainer of how onboarding docs and shared rendering work

### Which products have shared onboarding docs

This is a relatively new feature, so we're still migrating old onboarding docs to the new system. As of February 2026:

| Product | Status | |---------|--------| | AI Observability | ✅ Migrated | | Product Analytics | ✅ Migrated | | Web Analytics | ✅ Migrated | | Session Replay | ✅ Migrated | | Feature Flags | ✅ Migrated | | Experiments | ✅ Migrated | | Error Tracking | ✅ Migrated | | Surveys | ✅ Migrated | | Data Pipelines | ⏳ Not yet migrated | | Data Warehouse | ⏳ Not yet migrated | | PostHog AI | ⏳ Not yet migrated | | Workflows | ✅ Migrated | | Logs | ⏳ Not yet migrated | | Endpoints | ⏳ Not yet migrated |

### How it all works

Onboarding content is written once as React components in the `posthog/posthog` repo, then rendered in two places:

1. PostHog monorepo: For in-app onboarding, the PostHog app imports these docs components directly and wraps them with `OnboardingDocsContentWrapper`, which provides UI components like `Steps`, `CodeBlock`, etc.
2. PostHog.com repo: The website pulls the docs components from the monorepo via `gatsby-source-git`, a Gatsby plugin, and then renders them through MDX stub files that use a similar but different `OnboardingContentWrapper` to provide compatible UI components.

Both wrappers provide the same component names (`Steps`, `CodeBlock`, `CalloutBox`, etc.) so the shared content renders correctly in either place. When you merge changes to `master` in `posthog/posthog`, the website automatically pulls the updated content on its next build.

    flowchart LR
        subgraph website["<strong>posthog.com repo</strong>"]
            gatsby["gatsby-source-git<br/>(pulls on build)"]
            mdx["MDX stub files"]
            wrapper2["OnboardingContentWrapper"]
            ui2["Docs pages"]
            gatsby --> mdx --> wrapper2 --> ui2
        end

        subgraph monorepo["<strong>posthog/posthog repo</strong>"]
            docs["docs/onboarding/*.tsx<br/>product installation docs"]
            wrapper1["OnboardingDocsContentWrapper"]
            ui1["In-app onboarding flow"]
            docs --> wrapper1 --> ui1
        end
        docs -.->|"auto-sync"| gatsby

If you need some help with structuring your files, this is the architecture for each repo:

    posthog/posthog
    ├── docs/onboarding/
    │   └── your-product/
    │       ├── index.ts              # Barrel file re-exports all Installation components + snippets
    │       ├── sdk-name.tsx          # getSteps + createInstallation
    │       └── _snippets/
    │           └── reusable-snippet.tsx
    │
    └── frontend/src/scenes/onboarding/
        └── sdks/your-product/
            └── YourProductSDKInstructions.tsx  # withOnboardingDocsWrapper

    posthog/posthog.com
    └── contents/docs/your-product/
        └── installation/
            ├── sdk-name.mdx          # MDX stub
            └── _snippets/
                ├── prefix-installation-wrapper.tsx  # Single file with ALL wrappers
                └── shared-helpers.tsx               # modifySteps helpers

For a complete working example, see the Session Replay implementation:

| Repo | File | |------|------| | posthog/posthog | `docs/onboarding/session-replay/` | | posthog.com | `react.mdx` | | posthog.com | `sr-installation-wrapper.tsx` (single file with all wrappers) |

### How to create/migrate new onboarding docs

#### Step 1: Create the shared component in posthog/posthog

1. Navigate to the product directory in `docs/onboarding/`. If it doesn't exist, create it: `docs/onboarding/your-product/`
2. Create a new `.tsx` file: `docs/onboarding/your-product/filename.tsx`
3. Export a step function and Installation component. Use `createInstallation` to automatically handle the rendering:

       // Step function receives a single context object with all components
       export const getPythonSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => {
           const { CodeBlock, Markdown, dedent, snippets } = ctx

           // Reuse installation steps from product-analytics
           const installationSteps = getPythonStepsPA(ctx)

           // Add feature-flag-specific steps
           const flagSteps: StepDefinition[] = [
               {
                   title: 'Evaluate feature flags',
                   badge: 'required',
                   content: (
                       <>
                           Check if a feature flag is enabled:
                           {snippets?.BooleanFlagSnippet && <snippets.BooleanFlagSnippet />}
                       </>
                   ),
               },
           ]

           return [...installationSteps, ...flagSteps]
       }

       // createInstallation wraps your step function into a ready-to-use component
       export const PythonInstallation = createInstallation(getPythonSteps)

- You can reuse installation steps from product analytics by calling their step function with the same context.
- Step badges include `required`, `optional`, or `recommended`.

1. For reusable snippets, create them in `docs/onboarding/<product>/_snippets/` and export a named component.
2. Create the in-app wrapper in `frontend/src/scenes/onboarding/sdks/your-product/`. Use the `withOnboardingDocsWrapper` helper:

       const PYTHON_SNIPPETS = {
           PythonEventCapture,
           BooleanFlagSnippet,
           MultivariateFlagSnippet,
       }

       const FeatureFlagsPythonInstructionsWrapper = withOnboardingDocsWrapper({
           Installation: PythonInstallation,
           snippets: PYTHON_SNIPPETS,
       })

       export const FeatureFlagsSDKInstructions: SDKInstructionsMap = {
           [SDKKey.PYTHON]: FeatureFlagsPythonInstructionsWrapper,
           // ... other SDKs
       }

1. Test in the app by running the monorepo locally and navigate to `localhost:8010/onboarding`. From this page, you can select your product and test.

#### Step 2: Create the website stub in posthog/posthog.com

1. To test your changes locally, use the `GATSBY_POSTHOG_BRANCH` environment variable to point to your branch:

       GATSBY_POSTHOG_BRANCH=your-branch-name pnpm start

This tells `gatsby-source-git` to pull from your branch instead of `master`.

1. Create a single TSX wrapper file at `contents/docs/<product>/installation/_snippets/<prefix>-installation-wrapper.tsx` that exports all SDK wrappers:

           JSWebInstallation,
           ReactInstallation,
           NextJSInstallation,
           // ... import all SDK installations
           SessionReplayFinalSteps,
       } from 'onboarding/session-replay'

       const SNIPPETS = {
           SessionReplayFinalSteps,
       }

       // Export a wrapper for each SDK
       export const SRJSWebInstallationWrapper = () => (
       )

       export const SRReactInstallationWrapper = () => (
       )

       export const SRNextJSInstallationWrapper = () => (
       )

       // ... repeat for all SDKs

The `modifySteps` prop lets you add website-specific steps (like "Next steps") that aren't needed in-app.

1. Create an MDX stub file for each SDK at `contents/docs/<product>/installation/<name>.mdx`:

       ---
       title: React session replay installation
       platformLogo: react
       showStepsToc: true
       ---

       <!--
       This page imports shared onboarding content from the main PostHog repo.
       Source: https://github.com/PostHog/posthog/blob/master/docs/onboarding/session-replay/react.tsx
       -->

1. Test locally: Run `pnpm start` and verify the page renders correctly at the expected URL.
2. Commit and merge both the `posthog/posthog` and `posthog/posthog.com` PRs.

### Exceptions to the standard pattern

The architecture described above works well for products that have their own SDK installation steps – but not every product fits this mold. Some products are exceptions, and that's fine. The shared onboarding pattern should only be used when it makes sense.

#### Workflows

Installing an SDK for Workflows is optional. Because of this, Workflows doesn't define its own shared doc components. There are no files in `docs/onboarding/workflows/`.

Instead, Workflows reuses the Product Analytics `Installation` components directly and transforms them with a `modifySteps` function at the in-app level:

    // Filter out product-analytics-specific steps and add a workflows-specific final step
    function workflowsModifySteps(steps: StepDefinition[]): StepDefinition[] {
        const installationSteps = steps.filter(
            (step) => !['Send events', 'Send an event', 'Send events via the API'].includes(step.title)
        )
        return [
            ...installationSteps,
            {
                title: 'Set up workflows',
                badge: 'recommended',
                content: ,
            },
        ]
    }

    const WorkflowsReactWrapper = withOnboardingDocsWrapper({
        Installation: ReactInstallation,
        modifySteps: workflowsModifySteps,
    })

This pattern works because Workflows only needs a PostHog SDK installed (the same installation steps as Product Analytics), then swaps the final "send events" step for a "set up Workflows" step. Everything lives in a single `WorkflowsSDKInstructions.tsx` file – no shared docs directory, no website stubs.

If your product's onboarding is essentially "install the PostHog SDK + do one product-specific thing," consider reusing existing Installation components with `modifySteps` instead of creating a full set of shared doc files. This avoids unnecessary duplication.

Canonical URL: https://posthog.com/handbook/docs-and-wizard/onboarding-docs

GitHub source: contents/handbook/docs-and-wizard/onboarding-docs.mdx

Content hash: `5562fd52599b8ad2`

Static reader notes

- `MDX_COMPONENT_STATIC_ADAPTER`: Adapted interactive MDX components for static reading: CalloutBox, Caption, JSWebInstallation, Markdown, NextJSInstallation, OnboardingContentWrapper, ProductVideo, ReactInstallation, SRReactInstallationWrapper, WorkflowsFinalStepContent.