Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,37 @@ export const INTEGRATION_CONFIG = {
nextSteps:
'• Call posthog.identify() when a user signs into your app\n• Call posthog.capture() to capture custom events in your app\n• Use posthog.isFeatureEnabled() for feature flags',
},
[Integration.reactRouter]: {
name: 'React Router',
filterPatterns: ['**/*.{tsx,ts,jsx,js}'],
ignorePatterns: [
'node_modules',
'dist',
'build',
'public',
'static',
'assets',
],
detect: async (options) => {
const packageJson = await getPackageDotJson(options);
return hasPackageInstalled('react-router', packageJson);
},
generateFilesRules: '',
filterFilesRules: '',
docsUrl:
'https://posthog-git-react-post-hog.vercel.app/docs/libraries/react-router',
defaultChanges:
'• Installed posthog-js package\n• Added PostHogProvider to the root of the app\n• Integrated PostHog with React Router for pageview tracking',
nextSteps:
'• Call posthog.identify() when a user signs into your app\n• Call posthog.capture() to capture custom events in your app',
},
} as const satisfies Record<Integration, IntegrationConfig>;

export const INTEGRATION_ORDER = [
Integration.nextjs,
Integration.astro,
Integration.svelte,
Integration.reactNative,
Integration.reactRouter,
Integration.react,
] as const;
7 changes: 7 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ export enum Integration {
svelte = 'svelte',
reactNative = 'react-native',
astro = 'astro',
reactRouter = 'react-router',
}

export enum FeatureFlagDefinition {
ReactRouter = 'wizard-react-router',
}

export function getIntegrationDescription(type: string): string {
Expand All @@ -18,6 +23,8 @@ export function getIntegrationDescription(type: string): string {
return 'Svelte';
case Integration.astro:
return 'Astro';
case Integration.reactRouter:
return 'React Router';
default:
throw new Error(`Unknown integration ${type}`);
}
Expand Down
5 changes: 2 additions & 3 deletions src/nextjs/nextjs-wizard-agent.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* Simplified Next.js wizard using posthog-agent with PostHog MCP */
import type { WizardOptions } from '../utils/types';
import type { FrameworkConfig } from '../lib/framework-config';
import { enableDebugLogs } from '../utils/debug';
import { runAgentWizard } from '../lib/agent-runner';
import { Integration } from '../lib/constants';
Expand All @@ -21,7 +20,7 @@ import {
*/
const MINIMUM_NEXTJS_VERSION = '15.3.0';

const NEXTJS_AGENT_CONFIG: FrameworkConfig = {
const NEXTJS_AGENT_CONFIG = {
metadata: {
name: 'Next.js',
integration: Integration.nextjs,
Expand All @@ -44,7 +43,7 @@ const NEXTJS_AGENT_CONFIG: FrameworkConfig = {

environment: {
uploadToHosting: true,
getEnvVars: (apiKey, host) => ({
getEnvVars: (apiKey: string, host: string) => ({
NEXT_PUBLIC_POSTHOG_KEY: apiKey,
NEXT_PUBLIC_POSTHOG_HOST: host,
}),
Expand Down
147 changes: 147 additions & 0 deletions src/react-router/react-router-wizard-agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/* React Router wizard using posthog-agent with PostHog MCP */
import type { WizardOptions } from '../utils/types';
import type { FrameworkConfig } from '../lib/framework-config';
import { enableDebugLogs } from '../utils/debug';
import { runAgentWizard } from '../lib/agent-runner';
import { Integration } from '../lib/constants';
import { getPackageVersion } from '../utils/package-json';
import { getPackageDotJson } from '../utils/clack-utils';
import clack from '../utils/clack';
import chalk from 'chalk';
import * as semver from 'semver';
import {
getReactRouterMode,
getReactRouterModeName,
getReactRouterVersionBucket,
ReactRouterMode,
} from './utils';

/**
* React Router framework configuration for the universal agent runner.
*/
const MINIMUM_REACT_ROUTER_VERSION = '6.0.0';

const REACT_ROUTER_AGENT_CONFIG: FrameworkConfig = {
metadata: {
name: 'React Router',
integration: Integration.reactRouter,
docsUrl: 'https://posthog.com/docs/libraries/react',
unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/react',
abortMessage:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, we can start to see the parts that are generalizable. We can probably live without a per-framework abort message. It's probably the same message each time, with the docs URL piped in for that framework

'This wizard uses an LLM agent to intelligently modify your project. Please view the docs to setup React Router manually instead: https://posthog.com/docs/libraries/react',
gatherContext: async (options: WizardOptions) => {
const routerMode = await getReactRouterMode(options);
return { routerMode };
},
},

detection: {
packageName: 'react-router',
packageDisplayName: 'React Router',
getVersion: (packageJson: any) =>
getPackageVersion('react-router', packageJson),
getVersionBucket: getReactRouterVersionBucket,
},

environment: {
uploadToHosting: false,
getEnvVars: (apiKey: string, host: string) => ({
REACT_APP_POSTHOG_KEY: apiKey,
REACT_APP_POSTHOG_HOST: host,
}),
},

analytics: {
getTags: (context: any) => {
const routerMode = context.routerMode as ReactRouterMode;
return {
routerMode: routerMode || 'unknown',
};
},
},

prompts: {
getAdditionalContextLines: (context: any) => {
const routerMode = context.routerMode as ReactRouterMode;
const modeName = routerMode
? getReactRouterModeName(routerMode)
: 'unknown';

// Map router mode to framework ID for MCP docs resource
const frameworkIdMap: Record<ReactRouterMode, string> = {
[ReactRouterMode.V6]: 'react-react-router-6',
[ReactRouterMode.V7_FRAMEWORK]: 'react-react-router-7-framework',
[ReactRouterMode.V7_DATA]: 'react-react-router-7-data',
[ReactRouterMode.V7_DECLARATIVE]: 'react-react-router-7-declarative',
};

const frameworkId = routerMode
? frameworkIdMap[routerMode]
: ReactRouterMode.V7_FRAMEWORK;

return [
`Router mode: ${modeName}`,
`Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,
];
},
},

ui: {
welcomeMessage: 'PostHog React Router wizard (agent-powered)',
spinnerMessage:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably can share these between frameworks too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True

'Writing your PostHog setup with events, error capture and more...',
successMessage: 'PostHog integration complete',
estimatedDurationMinutes: 8,
getOutroChanges: (context: any) => {
const routerMode = context.routerMode as ReactRouterMode;
const modeName = routerMode
? getReactRouterModeName(routerMode)
: 'React Router';
return [
`Analyzed your React Router project structure (${modeName})`,
`Created and configured PostHog initializers`,
`Integrated PostHog into your application`,
];
},
getOutroNextSteps: () => [
'Start your development server to see PostHog in action',
'Visit your PostHog dashboard to see incoming events',
],
},
};

/**
* React Router wizard powered by the universal agent runner.
*/
export async function runReactRouterWizardAgent(
options: WizardOptions,
): Promise<void> {
if (options.debug) {
enableDebugLogs();
}

// Check React Router version - agent wizard requires >= 6.0.0
const packageJson = await getPackageDotJson(options);
const reactRouterVersion = getPackageVersion('react-router', packageJson);

if (reactRouterVersion) {
const coercedVersion = semver.coerce(reactRouterVersion);
if (
coercedVersion &&
semver.lt(coercedVersion, MINIMUM_REACT_ROUTER_VERSION)
) {
const docsUrl =
REACT_ROUTER_AGENT_CONFIG.metadata.unsupportedVersionDocsUrl ??
REACT_ROUTER_AGENT_CONFIG.metadata.docsUrl;

clack.log.warn(
`Sorry: the wizard can't help you with React Router ${reactRouterVersion}. Upgrade to React Router ${MINIMUM_REACT_ROUTER_VERSION} or later, or check out the manual setup guide.`,
);
clack.log.info(`Setup React Router manually: ${chalk.cyan(docsUrl)}`);
clack.outro('PostHog wizard will see you next time!');
return;
}
}

await runAgentWizard(REACT_ROUTER_AGENT_CONFIG, options);
}
Loading
Loading