PostHog Handbook Library / Wizard And Docs

993 words. Estimated reading time: 5 min.

# MDX and components for docs

The website's core technical architecture is built and maintained by the . See their handbook pages on the website and MDX components for more information.

### Gatsby and MDX features

#### Snippets for content reuse

Create snippets in a `_snippets/` directory for content you want to reuse across multiple pages.

When to create a snippet:

- Content appears in 2+ pages
- Event schemas or property tables
- Platform-specific code blocks
- Reusable UI components

##### MDX snippets

Create an MDX snippet for static reusable content like tables, callouts, or text blocks.

    The error event includes the following properties:

    | Property | Type | Description |
    |----------|------|-------------|
    | `$exception_message` | string | The error message |
    | `$exception_type` | string | The error type |

Use the snippet in an MDX page like this:

##### TSX snippets

Create a TSX snippet for dynamic content for lightweight components or React hooks.

    // _snippets/installation-platforms.tsx

    export default function InstallationPlatforms() {
      const platforms = usePlatformList('docs/[product]/installation', 'installation')
      return
    }

Use the snippet in an MDX page like this:

If the TSX snippet contains substantial logic, create a reusable component or hook in `/src/components/` or `/src/hooks/` instead.

#### Frontmatter

All `.mdx` pages support frontmatter, which Gatsby uses to configure page metadata.

    ---
    title: Install PostHog for React
    platformLogo: react
    showStepsToc: true
    ---

    This guide walks you through installing PostHog for React.

Here's a table of available frontmatter fields:

| Field | Purpose | Example | |-------|---------|---------| | `title` | Page title | `React installation` | | `platformLogo` | Platform icon key for installation pages | `react`, `python`, `nodejs` | | `showStepsToc` | Show steps in right sidebar TOC | `true` | | `hideRightSidebar` | Hide right sidebar TOC on start-here and changelog pages | `true` | | `contentMaxWidthClass` | Control and customize the width of main content column | `max-w-5xl` | | `tableOfContents` | Override the auto-generated TOC with custom entries | `[{ url: 'section-id', value: 'Section Name', depth: 1 }]` |

#### Magic `<placeholders>`

You can use magic placeholders or strings to replace the project token, project name, app host, region, and proxy path in the code block with values from the user's project.

- If the user is logged into the PostHog app, the placeholder will be replaced with the actual value from their project.
- If the user is not logged into the PostHog app, the placeholder will display as is.

| Placeholder | Description | Default | | -------------------------- | ----------------------------- | ----------------------------------------------- | | `<ph_project_token>` | Your PostHog project token | n/a | | `<ph_project_name>` | Your PostHog project name | n/a | | `<ph_app_host>` | Your PostHog instance URL | n/a | | `<ph_client_api_host>` | Your PostHog client API host | `https://us.i.posthog.com` | | `<ph_region>` | Your PostHog region (us/eu) | n/a | | `<ph_posthog_js_defaults>` | Default values for posthog-js | `2026-05-30` | | `<ph_proxy_path>` | Your proxy path | `relay-XXXX` (last 4 digits of project token) |

You can use these placeholders in the code block like this:

    const client = new PostHog('<ph_project_token>', { host: '<ph_client_api_host>' })

### Docs components

#### Screenshots and gifs

For UI screenshots and gifs with light and dark variants:

    <ProductScreenshot
      imageLight="https://..."
      imageDark="https://..."
      alt="Descriptive alt text"
      classes="rounded"
    />

#### Videos

For videos like `.mp4` or `.mov` files:

    <ProductVideo
      videoLight="https://..."
      videoDark="https://..."
      alt="Descriptive alt text"
      classes="rounded"
      autoPlay={false}
      muted={true}
      loop={true}
      background={false}
    />

#### Multi-language code blocks

For code examples in multiple programming languages:

// JavaScript example

## Python example

#### Callout boxes

You can add callout boxes to documentation to ensure skimmers don't miss essential information.

        Here is some information

Three styles are available:

- `fyi`: this is for stuff that's helpful but not critical
- `action`: these are tasks developers should complete and not miss
- `caution`: these flag the potential for misconfiguration, data loss, and other churn vectors

They look like this:

Provide detail here. You can go on at length if necessary.

Provide detail here. You can go on at length if necessary.

Provide detail here. You can go on at length if necessary.

Valid icons are listed in PostHog's icon library.

#### Steps

Use the `<Steps>` component for content that walks the reader through a strict sequence of instructions. Think how-to guides or step-by-step tutorials.

    Steps are automatically numbered.

    Write the _content_ in **markdown**.

    Add checkpoints to help readers verify their progress.

Our mdx parser does not play nice with certain whitespace. When using the component, make sure you:

- Add a line break after the opening component tags
- Avoid using 4-space indents

#### Decision tree

Use decision trees to help users choose between 2-6 options:

    <DecisionTree
        questions={[
            {
                id: 'platform',
                question: 'What platform are you using?',
                options: [
                    { value: 'web', label: 'Web' },
                    { value: 'mobile', label: 'Mobile' },
                ],
            },
        ]}
        getRecommendation={(answers) => {
            // return recommendation based on answers
        }}
    />

#### PostHog AI components

You can also link to PostHog AI which used to be called Max AI.

Use `<AskMax>` to provide in-context help:

The `<AskMax>` component opens the PostHog AI chat window directly on the website. Use this for documentation pages where users might need help understanding concepts or troubleshooting. Unlike `<MaxCTA>` which links to the PostHog app, this keeps users in the docs context.

    <AskMax
        quickQuestions={[
            'How do I mask sensitive data?',
            'Can I enable recordings only for certain users?',
            'How can I control costs?',
        ]}
    />

Use `<AskAIInput>` for troubleshooting sections:

    ## Have a question? Ask PostHog AI

##### Linking to PostHog AI in the app

The `<MaxCTA>` component renders a callout that sends readers into the PostHog app with a question for PostHog AI:

Under the hood it builds a URL using the `#panel=max:` hash format, which you can also use directly in any link. The question must be URL-encoded (`encodeURIComponent`), and an optional prefix before the question controls what happens when the panel opens:

| URL | Behavior | |-----|----------| | `https://app.posthog.com/#panel=max:What%20changed%3F` | Opens the PostHog AI side panel with "What changed?" pre-loaded, so the user can edit it before sending | | `https://app.posthog.com/#panel=max:!What%20changed%3F` | Auto-runs "What changed?" immediately, without waiting for the user to press enter |

Use the pre-load form when the reader should review or adapt the question first, and the auto-run (`!`) form for CTAs where the question is fully self-contained, like `<MaxCTA>` does. The prefix parsing lives in `parseCommandString` in `maxLogic` in the app repo.

### Platform logos

All platform logos are centralized in `src/constants/logos.ts`. To add a new platform:

1. Upload SVG to Cloudinary
2. Add key to `src/constants/logos.ts` in camelCase
3. Reference in MDX frontmatter: `platformLogo: myPlatform`

Use consistent naming: `stripe`, `react`, `nodejs`, etc.

### Debugging MDX issues

Common MDX parsing issues:

- Avoid deep indentation. Stay at 2 spaces or less
- Add line breaks after opening JSX tags and before closing tags
- Ensure all components are imported correctly
- Empty lines must be completely empty, no spaces
- Snippets can't share file names

Run the formatter to catch issues:

    pnpm format:docs

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

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

Content hash: `ff5f1dcc72014680`

Static reader notes

- `MDX_COMPONENT_STATIC_ADAPTER`: Adapted interactive MDX components for static reading: AskAIInput, AskMax, CalloutBox, DecisionTree, EventProperties, InstallationPlatforms, MaxCTA, MultiLanguage, PlatformList, PrivateLink, ProductScreenshot, ProductVideo, SmallTeam, Step, Steps.