diff --git a/llm-prompts/migrate-amplitude/1.0-begin.md b/llm-prompts/migrate-amplitude/1.0-begin.md new file mode 100644 index 0000000..68bb854 --- /dev/null +++ b/llm-prompts/migrate-amplitude/1.0-begin.md @@ -0,0 +1,87 @@ +--- +title: Amplitude Migration - Begin +description: Scan the project for Amplitude SDK usage and create a migration plan +--- + +You are migrating this project from Amplitude Analytics to PostHog. + +## Step 1: Detect Amplitude Installation + +Check `package.json` for any of these Amplitude packages: +- `@amplitude/analytics-browser` +- `@amplitude/analytics-node` +- `@amplitude/analytics-react-native` +- `amplitude-js` + +Note which packages are installed and their versions. + +## Step 2: Scan for Amplitude Code + +Search the codebase for files containing Amplitude usage: + +1. **Import statements** - Look for: + - `from '@amplitude/analytics-browser'` + - `from 'amplitude-js'` + - `from '@amplitude/analytics-node'` + - `from './ampli'` (generated Amplitude SDK) + +2. **Initialization code** - Look for: + - `init('AMPLITUDE_API_KEY')` + - `amplitude.getInstance().init()` + - `ampli.load()` + +3. **Tracking calls** - Look for: + - `track()`, `logEvent()` + - `identify()`, `setUserId()` + - `setGroup()`, `groupIdentify()` + - `revenue()`, `Revenue` + - Ampli type-safe methods like `ampli.buttonClicked()` + +4. **Configuration files** - Check for Amplitude environment variables: + - `AMPLITUDE_API_KEY` + - `REACT_APP_AMPLITUDE_API_KEY` + - `NEXT_PUBLIC_AMPLITUDE_API_KEY` + - `VITE_AMPLITUDE_API_KEY` + +## Step 3: Create Migration Plan + +Create a file `.posthog-migration.json` at the project root with: + +```json +{ + "sourceProvider": "amplitude", + "detectedPackages": ["@amplitude/analytics-browser"], + "filesToMigrate": [ + { + "path": "src/index.tsx", + "patterns": ["initialization", "provider-setup"] + }, + { + "path": "src/components/Button.tsx", + "patterns": ["event-tracking"] + } + ], + "hasAmpliSdk": false, + "ampliDirectory": null, + "environmentVariables": { + "remove": ["AMPLITUDE_API_KEY"], + "add": ["POSTHOG_KEY", "POSTHOG_HOST"] + } +} +``` + +## Step 4: Determine PostHog Package + +Map Amplitude packages to PostHog equivalents: +- `@amplitude/analytics-browser` → `posthog-js` +- `amplitude-js` → `posthog-js` +- `@amplitude/analytics-node` → `posthog-node` + +## Status + +Report these status updates as you work: + +- [STATUS] Checking for Amplitude installation +- [STATUS] Scanning for Amplitude usage patterns +- [STATUS] Found X files with Amplitude code +- [STATUS] Creating migration plan diff --git a/llm-prompts/migrate-amplitude/1.1-migrate.md b/llm-prompts/migrate-amplitude/1.1-migrate.md new file mode 100644 index 0000000..8078590 --- /dev/null +++ b/llm-prompts/migrate-amplitude/1.1-migrate.md @@ -0,0 +1,376 @@ +--- +title: Amplitude Migration - Execute +description: Transform Amplitude SDK code to PostHog equivalents following the API mapping reference +--- + +For each file in `.posthog-migration.json`, apply the transformations below. + +## Package Changes + +First, update dependencies: + +1. **Uninstall Amplitude packages**: + ```bash + npm uninstall @amplitude/analytics-browser amplitude-js @amplitude/analytics-node + ``` + +2. **Install PostHog**: + ```bash + npm install posthog-js + ``` + +--- + +## Import Replacements + +**BEFORE (Amplitude):** +```javascript +import { init, track, identify, setUserId, Identify, Revenue } from '@amplitude/analytics-browser'; +import amplitude from 'amplitude-js'; +import * as amplitude from '@amplitude/analytics-browser'; +import { ampli } from './ampli'; +``` + +**AFTER (PostHog):** +```javascript +import posthog from 'posthog-js'; +import { PostHogProvider, usePostHog } from 'posthog-js/react'; // For React +``` + +--- + +## Initialization + +**BEFORE (Amplitude):** +```javascript +import { init } from '@amplitude/analytics-browser'; +init('AMPLITUDE_API_KEY'); + +// or +amplitude.getInstance().init('AMPLITUDE_API_KEY'); + +// or with Ampli +ampli.load({ client: { apiKey: 'AMPLITUDE_API_KEY' } }); +``` + +**AFTER (PostHog):** +```javascript +import posthog from 'posthog-js'; + +posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, { + api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST, + defaults: '2025-05-24', + capture_exceptions: true, +}); +``` + +Use the appropriate environment variable prefix for the framework: +- Next.js: `process.env.NEXT_PUBLIC_POSTHOG_KEY` +- Vite: `import.meta.env.VITE_PUBLIC_POSTHOG_KEY` +- Create React App: `process.env.REACT_APP_POSTHOG_KEY` + +--- + +## Event Tracking + +**BEFORE (Amplitude):** +```javascript +import { track } from '@amplitude/analytics-browser'; +track('Button Clicked', { buttonName: 'signup' }); + +// or +amplitude.getInstance().logEvent('Button Clicked', { buttonName: 'signup' }); + +// or with Ampli +ampli.track({ event_type: 'Button Clicked', event_properties: { buttonName: 'signup' } }); +ampli.buttonClicked({ buttonName: 'signup' }); +``` + +**AFTER (PostHog):** +```javascript +posthog.capture('Button Clicked', { buttonName: 'signup' }); +``` + +--- + +## User Identification + +**BEFORE (Amplitude):** +```javascript +import { identify, setUserId, Identify } from '@amplitude/analytics-browser'; + +setUserId('user-123'); +const identifyObj = new Identify(); +identifyObj.set('email', 'user@example.com'); +identify(identifyObj); + +// or +amplitude.getInstance().setUserId('user-123'); +amplitude.getInstance().setUserProperties({ email: 'user@example.com' }); + +// or with Ampli +ampli.identify('user-123', { email: 'user@example.com' }); +``` + +**AFTER (PostHog):** +```javascript +posthog.identify('user-123', { + email: 'user@example.com', +}); +``` + +--- + +## Reset / Logout + +**BEFORE (Amplitude):** +```javascript +import { reset } from '@amplitude/analytics-browser'; +reset(); + +// or +amplitude.getInstance().setUserId(null); +amplitude.getInstance().regenerateDeviceId(); +``` + +**AFTER (PostHog):** +```javascript +posthog.reset(); +``` + +--- + +## Group / Company Identification + +**BEFORE (Amplitude):** +```javascript +import { setGroup } from '@amplitude/analytics-browser'; +setGroup('company', 'company-123'); + +// or +amplitude.getInstance().setGroup('company', 'company-123'); +ampli.client.setGroup('test group', 'browser-ts-ampli'); +ampli.client.groupIdentify('test group', 'browser-ts-ampli', amplitudeIdentify); +``` + +**AFTER (PostHog):** +```javascript +posthog.group('company', 'company-123', { + // optional group properties + name: 'Acme Inc', +}); +``` + +--- + +## Revenue Tracking + +**BEFORE (Amplitude):** +```javascript +import { revenue, Revenue } from '@amplitude/analytics-browser'; + +const revenueEvent = new Revenue() + .setProductId('product-123') + .setPrice(9.99) + .setQuantity(1); +revenue(revenueEvent); +``` + +**AFTER (PostHog):** +```javascript +posthog.capture('purchase', { + $set: { total_revenue: 9.99 }, + product_id: 'product-123', + price: 9.99, + quantity: 1, +}); +``` + +--- + +## User Properties + +**BEFORE (Amplitude):** +```javascript +amplitude.getInstance().setUserProperties({ plan: 'premium' }); +``` + +**AFTER (PostHog):** +```javascript +posthog.capture('$set', { + $set: { plan: 'premium' }, +}); + +// Or include in identify call: +posthog.identify(userId, { plan: 'premium' }); +``` + +--- + +## Opt-Out + +**BEFORE (Amplitude):** +```javascript +amplitude.getInstance().setOptOut(true); +``` + +**AFTER (PostHog):** +```javascript +posthog.opt_out_capturing(); + +// To opt back in: +posthog.opt_in_capturing(); +``` + +--- + +## Device ID + +**BEFORE (Amplitude):** +```javascript +const deviceId = amplitude.getInstance().getDeviceId(); +``` + +**AFTER (PostHog):** +```javascript +const distinctId = posthog.get_distinct_id(); +``` + +--- + +## Next.js Projects + +For Next.js projects, use the `instrumentation-client.ts|js` file. This replaces any Amplitude initialization in layout files, providers, or useEffect hooks. + +**BEFORE (Amplitude in Next.js):** +```jsx +// app/layout.tsx or app/providers.tsx +import { init } from '@amplitude/analytics-browser'; +import { ampli } from './ampli'; + +// Often in useEffect or provider +useEffect(() => { + init('AMPLITUDE_API_KEY'); + // or + ampli.load({ client: { apiKey: 'AMPLITUDE_API_KEY' } }); +}, []); +``` + +**AFTER (PostHog with instrumentation-client):** + +Create `instrumentation-client.ts` (or `.js`) at the **root of your Next.js app** (same level as `app/` or `pages/`): + +```typescript +// instrumentation-client.ts +import posthog from 'posthog-js' + +posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { + api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST, + defaults: '2025-05-24', +}) +``` + +Or in JavaScript: +```javascript +// instrumentation-client.js +import posthog from 'posthog-js' + +posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, { + api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST, + defaults: '2025-05-24', +}) +``` + +**Key changes for Next.js migration:** +- Delete any `PostHogProvider` wrapper components +- Delete any `providers.tsx` file that only existed for PostHog +- Remove PostHog initialization from `useEffect` hooks +- Remove `'use client'` directives that were only needed for PostHog provider +- Import `posthog` directly where needed (no provider/hook required) + +**Using PostHog in Next.js components:** +```typescript +// Any client component +'use client' +import posthog from 'posthog-js' + +function MyComponent() { + const handleClick = () => { + posthog.capture('button_clicked', { button: 'signup' }) + } + + return +} +``` + +--- + +## React Projects (Non-Next.js) + +For React apps without Next.js (Create React App, Vite, etc.), use the PostHogProvider pattern: + +**BEFORE (Amplitude with React):** +```jsx +import { init } from '@amplitude/analytics-browser'; +import { ampli } from './ampli'; + +function App() { + useEffect(() => { + init('AMPLITUDE_API_KEY'); + // or + ampli.load({ client: { apiKey: 'AMPLITUDE_API_KEY' } }); + }, []); + + return ; +} +``` + +**AFTER (PostHog with React):** +```jsx +import posthog from 'posthog-js'; +import { PostHogProvider } from 'posthog-js/react'; + +// Initialize BEFORE rendering (outside component) +posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_KEY, { + api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST, + defaults: '2025-05-24', + capture_exceptions: true, +}); + +function App() { + return ( + + + + ); +} +``` + +**Using the hook in components:** +```jsx +import { usePostHog } from 'posthog-js/react'; + +function MyComponent() { + const posthog = usePostHog(); + + const handleClick = () => { + posthog.capture('button_clicked', { button: 'signup' }); + }; + + return ; +} +``` + +**IMPORTANT:** In non-Next.js React apps, use the `usePostHog` hook in components rather than importing `posthog` directly. + +--- + +## Status + +Report these status updates as you work: + +- [STATUS] Migrating file: {filename} +- [STATUS] Replacing imports +- [STATUS] Updating initialization +- [STATUS] Converting tracking calls +- [STATUS] Completed: {filename} diff --git a/llm-prompts/migrate-amplitude/1.2-verify.md b/llm-prompts/migrate-amplitude/1.2-verify.md new file mode 100644 index 0000000..ea3470c --- /dev/null +++ b/llm-prompts/migrate-amplitude/1.2-verify.md @@ -0,0 +1,131 @@ +--- +title: Amplitude Migration - Verify +description: Verify the migration is complete and clean up Amplitude artifacts +--- + +After migrating all files, perform these verification and cleanup steps. + +## Step 1: Verify No Remaining Amplitude Code + +Search the codebase for any remaining Amplitude references: + +``` +grep -r "amplitude" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" +grep -r "@amplitude" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" +grep -r "ampli\." --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" +``` + +If any Amplitude code remains, return to the migrate step and address it. + +## Step 2: Clean Up Ampli Directory + +If the project used Ampli (Amplitude's generated SDK), delete the entire directory: + +```bash +rm -rf src/ampli +rm -rf ampli +``` + +Remove any `ampli.json` configuration files as well. + +## Step 3: Update Environment Variables + +### Remove Amplitude Variables + +Delete these from `.env`, `.env.local`, `.env.production`, etc.: +- `AMPLITUDE_API_KEY` +- `REACT_APP_AMPLITUDE_API_KEY` +- `NEXT_PUBLIC_AMPLITUDE_API_KEY` +- `VITE_AMPLITUDE_API_KEY` +- Any other `*AMPLITUDE*` variables + +### Add PostHog Variables + +Ensure these are present with appropriate prefix for the framework: + +**Next.js (.env.local):** +``` +NEXT_PUBLIC_POSTHOG_KEY=phc_your_key_here +NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com +``` + +**Vite (.env):** +``` +VITE_PUBLIC_POSTHOG_KEY=phc_your_key_here +VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com +``` + +**Create React App (.env):** +``` +REACT_APP_POSTHOG_KEY=phc_your_key_here +REACT_APP_POSTHOG_HOST=https://us.i.posthog.com +``` + +## Step 4: Verify Package.json + +Confirm that: +1. All Amplitude packages are removed from `dependencies` and `devDependencies` +2. `posthog-js` (or appropriate PostHog package) is installed + +## Step 5: Run Type Check (if TypeScript) + +If the project uses TypeScript, run the type checker to catch any migration issues: + +```bash +npx tsc --noEmit +``` + +Fix any type errors related to the migration. + +## Step 6: Run Linter + +If the project has ESLint or similar configured: + +```bash +npm run lint +``` + +Fix any linting errors, particularly unused imports from Amplitude. + +## Step 7: Test the Application + +Start the development server and verify: + +1. **No console errors** related to Amplitude or PostHog +2. **PostHog initializes** - Check browser DevTools Network tab for requests to PostHog +3. **Events are captured** - Trigger some actions and verify they appear in PostHog + +## Migration Summary + +Delete the `.posthog-migration.json` planning file: + +```bash +rm .posthog-migration.json +``` + +## Checklist + +Before completing the migration, verify: + +- [ ] All Amplitude imports removed +- [ ] All Amplitude tracking calls converted to PostHog +- [ ] All Amplitude identify calls converted to PostHog +- [ ] Ampli directory deleted (if applicable) +- [ ] Amplitude packages uninstalled +- [ ] Amplitude environment variables removed +- [ ] PostHog environment variables added +- [ ] PostHog package installed +- [ ] TypeScript compiles without errors (if applicable) +- [ ] No linting errors +- [ ] Application runs without console errors + +## Status + +Report these status updates as you work: + +- [STATUS] Verifying no remaining Amplitude code +- [STATUS] Cleaning up Ampli directory +- [STATUS] Updating environment variables +- [STATUS] Running type check +- [STATUS] Running linter +- [STATUS] Migration complete diff --git a/scripts/lib/skill-generator.js b/scripts/lib/skill-generator.js index f07b37f..3072977 100644 --- a/scripts/lib/skill-generator.js +++ b/scripts/lib/skill-generator.js @@ -299,6 +299,16 @@ function generateFrontmatter(skill, version) { return '---\n' + yaml.dump(frontmatter) + '---\n\n'; } +/** + * Filter workflows by category based on skill config + * If skill.workflows is specified, only include those categories + * If not specified, defaults to ['basic-integration'] + */ +function filterWorkflowsForSkill(allWorkflows, skill) { + const allowedCategories = skill.workflows || ['basic-integration']; + return allWorkflows.filter(wf => allowedCategories.includes(wf.category)); +} + /** * Generate a complete skill package * @@ -312,7 +322,7 @@ function generateFrontmatter(skill, version) { * @param {Object} options.commandmentsConfig - Commandments config * @param {string} options.skillTemplate - Skill description template * @param {Array} options.sharedDocs - Shared docs URLs - * @param {Array} options.workflows - Discovered workflows + * @param {Array} options.allWorkflows - All discovered workflows (will be filtered per-skill) */ async function generateSkill({ skill, @@ -324,8 +334,10 @@ async function generateSkill({ commandmentsConfig, skillTemplate, sharedDocs, - workflows, + allWorkflows, }) { + // Filter workflows for this specific skill + const workflows = filterWorkflowsForSkill(allWorkflows, skill); const skillDir = path.join(outputDir, skill.id); const referencesDir = path.join(skillDir, 'references'); @@ -507,7 +519,7 @@ async function generateAllSkills({ commandmentsConfig, skillTemplate, sharedDocs, - workflows, + allWorkflows: workflows, }); console.log(` ✓ ${skill.id}`); @@ -530,6 +542,7 @@ module.exports = { loadSkillTemplate, collectCommandments, discoverWorkflows, + filterWorkflowsForSkill, generateSkill, generateAllSkills, }; diff --git a/transformation-config/commandments.yaml b/transformation-config/commandments.yaml index a06ac9b..8549f3f 100644 --- a/transformation-config/commandments.yaml +++ b/transformation-config/commandments.yaml @@ -41,4 +41,21 @@ commandments: - Create a dedicated PostHogService class in app/Services/ - do NOT scatter PostHog::capture calls throughout controllers - Register PostHog configuration in config/posthog.php using env() for all settings (api_key, host, disabled) - Do NOT use Laravel's event system or observers for analytics - call capture explicitly where actions occur + + migration: + - Remove ALL source SDK packages after migration is complete + - Remove source SDK environment variables (e.g., AMPLITUDE_API_KEY) + - Delete generated SDK directories (e.g., 'ampli' folder for Amplitude) + - Preserve existing code structure - only replace analytics calls, don't restructure files + - Use environment variables for PostHog keys - never hardcode them + - Include defaults '2025-05-24' in PostHog initialization for latest recommended settings + + amplitude: + - Replace amplitude.getInstance() patterns with posthog direct calls + - Replace Amplitude Identify class with posthog.identify() properties object + - Replace Amplitude Revenue class with posthog.capture() with $set properties + - Replace setGroup/groupIdentify with posthog.group() + - Replace setOptOut with posthog.opt_out_capturing()/opt_in_capturing() + - Remove Ampli generated SDK imports and delete the ampli directory entirely + - Map Ampli type-safe methods to posthog.capture() with appropriate event names \ No newline at end of file diff --git a/transformation-config/skills.yaml b/transformation-config/skills.yaml index 0b6be27..2cda81f 100644 --- a/transformation-config/skills.yaml +++ b/transformation-config/skills.yaml @@ -88,6 +88,16 @@ skills: docs_urls: - https://posthog.com/docs/libraries/laravel.md + # Migration skills (guide type - docs without example code) + - id: migrate-amplitude-to-posthog + type: guide + display_name: Migrate from Amplitude + description: Migrate analytics from Amplitude SDK to PostHog. Replaces Amplitude imports, initialization, event tracking, user identification, and group analytics with PostHog equivalents. + tags: [migration, amplitude, react, javascript] + workflows: [migrate-amplitude] + docs_urls: + - https://posthog.com/docs/migrate/migrate-from-amplitude.md + # Guide-only skills (docs without example code) # - id: identify-users # type: guide