vybekiit 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +840 -296
- package/dist/global-skills/add-ai/SKILL.md +53 -0
- package/dist/global-skills/add-analytics/SKILL.md +65 -0
- package/dist/global-skills/add-app-clip/SKILL.md +280 -0
- package/dist/global-skills/add-app-clip/agents/openai.yaml +4 -0
- package/dist/global-skills/add-app-clip/references/native-module.md +96 -0
- package/dist/global-skills/add-blog/SKILL.md +49 -0
- package/dist/global-skills/add-crud/SKILL.md +28 -0
- package/dist/global-skills/add-files/SKILL.md +65 -0
- package/dist/global-skills/add-images/SKILL.md +64 -0
- package/dist/global-skills/add-language/SKILL.md +44 -0
- package/dist/global-skills/add-notifications/SKILL.md +61 -0
- package/dist/global-skills/add-realtime/SKILL.md +49 -0
- package/dist/global-skills/add-route/SKILL.md +28 -0
- package/dist/global-skills/add-search/SKILL.md +43 -0
- package/dist/global-skills/add-signin/SKILL.md +78 -0
- package/dist/global-skills/add-teams/SKILL.md +64 -0
- package/dist/global-skills/add-upload/SKILL.md +27 -0
- package/dist/global-skills/aws-cdk/SKILL.md +72 -0
- package/dist/global-skills/aws-cdk/references/bootstrap-and-project-setup.md +257 -0
- package/dist/global-skills/aws-cdk/references/compliance-and-drift.md +193 -0
- package/dist/global-skills/aws-cdk/references/construct-patterns.md +315 -0
- package/dist/global-skills/aws-cdk/references/import-and-migrate.md +184 -0
- package/dist/global-skills/aws-cdk/references/refactor-and-prevent-replacement.md +198 -0
- package/dist/global-skills/aws-cdk/references/troubleshooting-credentials.md +183 -0
- package/dist/global-skills/aws-cdk/references/troubleshooting-deployment.md +293 -0
- package/dist/global-skills/aws-cdk/references/troubleshooting-synth.md +274 -0
- package/dist/global-skills/aws-cdk/references/v1-to-v2-migration.md +119 -0
- package/dist/global-skills/aws-cloudformation/SKILL.md +88 -0
- package/dist/global-skills/aws-cloudformation/references/author-cloudformation-best-practices.script.md +179 -0
- package/dist/global-skills/aws-cloudformation/references/check-cloudformation-template-compliance.script.md +159 -0
- package/dist/global-skills/aws-cloudformation/references/cloudformation-pre-deploy-validation.script.md +217 -0
- package/dist/global-skills/aws-cloudformation/references/deploy-with-express-mode.script.md +271 -0
- package/dist/global-skills/aws-cloudformation/references/lookup-resource-properties.script.md +130 -0
- package/dist/global-skills/aws-cloudformation/references/troubleshoot-deployment.script.md +200 -0
- package/dist/global-skills/aws-cloudformation/references/validate-cloudformation-template.script.md +135 -0
- package/dist/global-skills/aws-serverless/SKILL.md +51 -0
- package/dist/global-skills/aws-serverless/assets/powertools-handler.py +49 -0
- package/dist/global-skills/aws-serverless/references/api-gateway.md +553 -0
- package/dist/global-skills/aws-serverless/references/architecture.md +262 -0
- package/dist/global-skills/aws-serverless/references/concurrency.md +200 -0
- package/dist/global-skills/aws-serverless/references/deployment.md +94 -0
- package/dist/global-skills/aws-serverless/references/event-sources.md +484 -0
- package/dist/global-skills/aws-serverless/references/lambda.md +548 -0
- package/dist/global-skills/aws-serverless/references/orchestration.md +449 -0
- package/dist/global-skills/aws-serverless/references/production.md +493 -0
- package/dist/global-skills/aws-serverless/references/troubleshooting.md +711 -0
- package/dist/global-skills/back-up-my-code/SKILL.md +48 -0
- package/dist/global-skills/better-auth-best-practices/SKILL.md +182 -0
- package/dist/global-skills/better-auth-security-best-practices/SKILL.md +432 -0
- package/dist/global-skills/building-native-ui/SKILL.md +377 -0
- package/dist/global-skills/building-native-ui/agents/openai.yaml +4 -0
- package/dist/global-skills/building-native-ui/references/animations.md +220 -0
- package/dist/global-skills/building-native-ui/references/controls.md +270 -0
- package/dist/global-skills/building-native-ui/references/form-sheet.md +253 -0
- package/dist/global-skills/building-native-ui/references/gradients.md +106 -0
- package/dist/global-skills/building-native-ui/references/icons.md +213 -0
- package/dist/global-skills/building-native-ui/references/media.md +198 -0
- package/dist/global-skills/building-native-ui/references/route-structure.md +229 -0
- package/dist/global-skills/building-native-ui/references/search.md +248 -0
- package/dist/global-skills/building-native-ui/references/storage.md +121 -0
- package/dist/global-skills/building-native-ui/references/tabs.md +433 -0
- package/dist/global-skills/building-native-ui/references/toolbar-and-headers.md +284 -0
- package/dist/global-skills/building-native-ui/references/visual-effects.md +197 -0
- package/dist/global-skills/building-native-ui/references/webgpu-three.md +605 -0
- package/dist/global-skills/building-native-ui/references/zoom-transitions.md +158 -0
- package/dist/global-skills/buy-domain/SKILL.md +64 -0
- package/dist/global-skills/check-safety/SKILL.md +94 -0
- package/dist/global-skills/claimable-postgres/SKILL.md +249 -0
- package/dist/global-skills/configure-capabilities/SKILL.md +38 -0
- package/dist/global-skills/connect-account/SKILL.md +64 -0
- package/dist/global-skills/connect-account-backend/SKILL.md +41 -0
- package/dist/global-skills/create-auth-skill/SKILL.md +321 -0
- package/dist/global-skills/design-my-data/SKILL.md +48 -0
- package/dist/global-skills/doctor/SKILL.md +84 -0
- package/dist/global-skills/eas-app-stores/SKILL.md +152 -0
- package/dist/global-skills/eas-app-stores/agents/openai.yaml +4 -0
- package/dist/global-skills/eas-app-stores/references/app-store-metadata.md +497 -0
- package/dist/global-skills/eas-app-stores/references/ios-app-store.md +371 -0
- package/dist/global-skills/eas-app-stores/references/play-store.md +246 -0
- package/dist/global-skills/eas-app-stores/references/testflight.md +58 -0
- package/dist/global-skills/eas-app-stores/references/workflows.md +120 -0
- package/dist/global-skills/eas-hosting/SKILL.md +423 -0
- package/dist/global-skills/eas-hosting/agents/openai.yaml +4 -0
- package/dist/global-skills/eas-observe/SKILL.md +32 -0
- package/dist/global-skills/eas-observe/agents/openai.yaml +4 -0
- package/dist/global-skills/eas-observe/references/metrics.md +47 -0
- package/dist/global-skills/eas-observe/references/queries.md +342 -0
- package/dist/global-skills/eas-observe/references/setup.md +317 -0
- package/dist/global-skills/eas-simulator/SKILL.md +156 -0
- package/dist/global-skills/eas-simulator/agents/openai.yaml +4 -0
- package/dist/global-skills/eas-simulator/references/controllers.md +67 -0
- package/dist/global-skills/eas-simulator/references/run-your-app.md +185 -0
- package/dist/global-skills/eas-simulator/references/troubleshooting.md +38 -0
- package/dist/global-skills/eas-update-insights/SKILL.md +230 -0
- package/dist/global-skills/eas-update-insights/agents/openai.yaml +4 -0
- package/dist/global-skills/eas-update-insights/references/channel-insights-schema.md +47 -0
- package/dist/global-skills/eas-update-insights/references/update-insights-schema.md +69 -0
- package/dist/global-skills/eas-workflows/SKILL.md +94 -0
- package/dist/global-skills/eas-workflows/agents/openai.yaml +4 -0
- package/dist/global-skills/eas-workflows/scripts/fetch.js +109 -0
- package/dist/global-skills/eas-workflows/scripts/package.json +11 -0
- package/dist/global-skills/eas-workflows/scripts/validate.js +84 -0
- package/dist/global-skills/email-best-practices/SKILL.md +73 -0
- package/dist/global-skills/expo-api-routes/SKILL.md +368 -0
- package/dist/global-skills/expo-api-routes/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-app-clip/SKILL.md +282 -0
- package/dist/global-skills/expo-app-clip/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-app-clip/references/native-module.md +96 -0
- package/dist/global-skills/expo-brownfield/SKILL.md +54 -0
- package/dist/global-skills/expo-brownfield/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-brownfield/references/brownfield-integrated.md +526 -0
- package/dist/global-skills/expo-brownfield/references/brownfield-isolated.md +402 -0
- package/dist/global-skills/expo-brownfield/references/comparison.md +63 -0
- package/dist/global-skills/expo-brownfield/references/troubleshooting.md +88 -0
- package/dist/global-skills/expo-cicd-workflows/SKILL.md +92 -0
- package/dist/global-skills/expo-cicd-workflows/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-cicd-workflows/scripts/fetch.js +109 -0
- package/dist/global-skills/expo-cicd-workflows/scripts/package.json +11 -0
- package/dist/global-skills/expo-cicd-workflows/scripts/validate.js +84 -0
- package/dist/global-skills/expo-data-fetching/SKILL.md +449 -0
- package/dist/global-skills/expo-data-fetching/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-data-fetching/references/expo-router-loaders.md +341 -0
- package/dist/global-skills/expo-data-fetching/references/offline-and-cancellation.md +68 -0
- package/dist/global-skills/expo-deployment/SKILL.md +167 -0
- package/dist/global-skills/expo-deployment/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-deployment/references/app-store-metadata.md +497 -0
- package/dist/global-skills/expo-deployment/references/ios-app-store.md +371 -0
- package/dist/global-skills/expo-deployment/references/play-store.md +246 -0
- package/dist/global-skills/expo-deployment/references/testflight.md +58 -0
- package/dist/global-skills/expo-deployment/references/workflows.md +160 -0
- package/dist/global-skills/expo-dev-client/SKILL.md +174 -0
- package/dist/global-skills/expo-dev-client/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-dom/SKILL.md +417 -0
- package/dist/global-skills/expo-dom/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-examples/SKILL.md +99 -0
- package/dist/global-skills/expo-examples/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-examples/references/catalog.md +105 -0
- package/dist/global-skills/expo-module/SKILL.md +141 -0
- package/dist/global-skills/expo-module/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-module/references/config-plugin.md +90 -0
- package/dist/global-skills/expo-module/references/create-expo-module.md +206 -0
- package/dist/global-skills/expo-module/references/lifecycle.md +127 -0
- package/dist/global-skills/expo-module/references/module-config.md +48 -0
- package/dist/global-skills/expo-module/references/native-module.md +286 -0
- package/dist/global-skills/expo-module/references/native-view.md +171 -0
- package/dist/global-skills/expo-native-ui/SKILL.md +181 -0
- package/dist/global-skills/expo-native-ui/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-native-ui/references/animations.md +220 -0
- package/dist/global-skills/expo-native-ui/references/controls.md +270 -0
- package/dist/global-skills/expo-native-ui/references/gradients.md +106 -0
- package/dist/global-skills/expo-native-ui/references/icons.md +213 -0
- package/dist/global-skills/expo-native-ui/references/media.md +198 -0
- package/dist/global-skills/expo-native-ui/references/storage.md +121 -0
- package/dist/global-skills/expo-native-ui/references/visual-effects.md +197 -0
- package/dist/global-skills/expo-native-ui/references/webgpu-three.md +605 -0
- package/dist/global-skills/expo-observe/SKILL.md +30 -0
- package/dist/global-skills/expo-observe/references/metrics.md +47 -0
- package/dist/global-skills/expo-observe/references/queries.md +342 -0
- package/dist/global-skills/expo-observe/references/setup.md +317 -0
- package/dist/global-skills/expo-router/SKILL.md +230 -0
- package/dist/global-skills/expo-router/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-router/references/form-sheet.md +253 -0
- package/dist/global-skills/expo-router/references/route-structure.md +229 -0
- package/dist/global-skills/expo-router/references/search.md +248 -0
- package/dist/global-skills/expo-router/references/tabs.md +433 -0
- package/dist/global-skills/expo-router/references/toolbar-and-headers.md +284 -0
- package/dist/global-skills/expo-router/references/zoom-transitions.md +158 -0
- package/dist/global-skills/expo-skill-eval/SKILL.md +314 -0
- package/dist/global-skills/expo-skill-eval/agents/visual-grader.md +52 -0
- package/dist/global-skills/expo-skill-eval/references/design-rubric.md +45 -0
- package/dist/global-skills/expo-skill-eval/references/runtime-matrix.md +34 -0
- package/dist/global-skills/expo-skill-eval/scripts/check-static.sh +64 -0
- package/dist/global-skills/expo-skill-eval/scripts/clean-fixture.sh +56 -0
- package/dist/global-skills/expo-skill-eval/scripts/generate_viewer.py +450 -0
- package/dist/global-skills/expo-skill-eval/scripts/latest-sdk.sh +46 -0
- package/dist/global-skills/expo-skill-eval/scripts/make-fixture.sh +95 -0
- package/dist/global-skills/expo-skill-eval/scripts/make-workspace.sh +31 -0
- package/dist/global-skills/expo-skill-eval/scripts/snapshot-android.sh +284 -0
- package/dist/global-skills/expo-skill-eval/scripts/snapshot-ios.sh +132 -0
- package/dist/global-skills/expo-skill-eval/scripts/snapshot-web.sh +61 -0
- package/dist/global-skills/expo-skill-feedback/SKILL.md +54 -0
- package/dist/global-skills/expo-skill-feedback/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-skill-feedback/scripts/skill-event.cjs +180 -0
- package/dist/global-skills/expo-skill-feedback/scripts/skill-feedback.cjs +118 -0
- package/dist/global-skills/expo-skill-feedback/scripts/telemetry.cjs +65 -0
- package/dist/global-skills/expo-skill-feedback/scripts/telemetry_common.cjs +171 -0
- package/dist/global-skills/expo-tailwind-setup/SKILL.md +480 -0
- package/dist/global-skills/expo-tailwind-setup/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-ui/SKILL.md +47 -0
- package/dist/global-skills/expo-ui/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-ui/references/drop-in-replacements.md +27 -0
- package/dist/global-skills/expo-ui/references/jetpack-compose.md +73 -0
- package/dist/global-skills/expo-ui/references/swift-ui.md +73 -0
- package/dist/global-skills/expo-ui/references/universal.md +73 -0
- package/dist/global-skills/expo-ui/scripts/list-components.js +193 -0
- package/dist/global-skills/expo-upgrade/SKILL.md +134 -0
- package/dist/global-skills/expo-upgrade/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-upgrade/references/expo-av-to-audio.md +132 -0
- package/dist/global-skills/expo-upgrade/references/expo-av-to-video.md +160 -0
- package/dist/global-skills/expo-upgrade/references/native-tabs.md +124 -0
- package/dist/global-skills/expo-upgrade/references/new-architecture.md +79 -0
- package/dist/global-skills/expo-upgrade/references/react-19.md +79 -0
- package/dist/global-skills/expo-upgrade/references/react-compiler.md +59 -0
- package/dist/global-skills/expo-upgrade/references/react-navigation-to-expo-router.md +61 -0
- package/dist/global-skills/expo-web-to-native/SKILL.md +83 -0
- package/dist/global-skills/expo-web-to-native/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-web-to-native/references/false-friends.md +119 -0
- package/dist/global-skills/expo-web-to-native/references/native-patterns.md +39 -0
- package/dist/global-skills/expo-web-to-native/references/run-as-goal.md +48 -0
- package/dist/global-skills/expo-web-to-native/references/verify-on-device.md +45 -0
- package/dist/global-skills/firebase-ai-logic-basics/SKILL.md +165 -0
- package/dist/global-skills/firebase-ai-logic-basics/references/flutter_setup.md +95 -0
- package/dist/global-skills/firebase-ai-logic-basics/references/ios_setup.md +156 -0
- package/dist/global-skills/firebase-ai-logic-basics/references/usage_patterns_android.md +157 -0
- package/dist/global-skills/firebase-ai-logic-basics/references/usage_patterns_web.md +186 -0
- package/dist/global-skills/firebase-app-hosting-basics/SKILL.md +73 -0
- package/dist/global-skills/firebase-app-hosting-basics/references/cli_commands.md +85 -0
- package/dist/global-skills/firebase-app-hosting-basics/references/configuration.md +59 -0
- package/dist/global-skills/firebase-app-hosting-basics/references/emulation.md +59 -0
- package/dist/global-skills/firebase-auth-basics/SKILL.md +118 -0
- package/dist/global-skills/firebase-auth-basics/references/client_sdk_android.md +160 -0
- package/dist/global-skills/firebase-auth-basics/references/client_sdk_web.md +301 -0
- package/dist/global-skills/firebase-auth-basics/references/flutter_setup.md +149 -0
- package/dist/global-skills/firebase-auth-basics/references/ios_setup.md +87 -0
- package/dist/global-skills/firebase-auth-basics/references/security_rules.md +49 -0
- package/dist/global-skills/firebase-basics/SKILL.md +148 -0
- package/dist/global-skills/firebase-basics/references/android_setup.md +41 -0
- package/dist/global-skills/firebase-basics/references/firebase-cli-guide.md +18 -0
- package/dist/global-skills/firebase-basics/references/firebase-service-init.md +20 -0
- package/dist/global-skills/firebase-basics/references/flutter_setup.md +143 -0
- package/dist/global-skills/firebase-basics/references/ios_setup.md +113 -0
- package/dist/global-skills/firebase-basics/references/local-env-setup.md +80 -0
- package/dist/global-skills/firebase-basics/references/refresh/android_studio.md +41 -0
- package/dist/global-skills/firebase-basics/references/refresh/antigravity.md +64 -0
- package/dist/global-skills/firebase-basics/references/refresh/claude.md +12 -0
- package/dist/global-skills/firebase-basics/references/refresh/gemini-cli.md +13 -0
- package/dist/global-skills/firebase-basics/references/refresh/other-agents.md +67 -0
- package/dist/global-skills/firebase-basics/references/setup/android_studio.md +23 -0
- package/dist/global-skills/firebase-basics/references/setup/antigravity.md +98 -0
- package/dist/global-skills/firebase-basics/references/setup/claude_code.md +45 -0
- package/dist/global-skills/firebase-basics/references/setup/cursor.md +93 -0
- package/dist/global-skills/firebase-basics/references/setup/gemini_cli.md +53 -0
- package/dist/global-skills/firebase-basics/references/setup/github_copilot.md +104 -0
- package/dist/global-skills/firebase-basics/references/setup/other_agents.md +99 -0
- package/dist/global-skills/firebase-basics/references/web_setup.md +77 -0
- package/dist/global-skills/firebase-crashlytics/SKILL.md +42 -0
- package/dist/global-skills/firebase-crashlytics/references/android_setup.md +152 -0
- package/dist/global-skills/firebase-crashlytics/references/ios_setup.md +115 -0
- package/dist/global-skills/firebase-data-connect/SKILL.md +191 -0
- package/dist/global-skills/firebase-data-connect/examples.md +638 -0
- package/dist/global-skills/firebase-data-connect/reference/cloud_functions.md +184 -0
- package/dist/global-skills/firebase-data-connect/reference/config.md +271 -0
- package/dist/global-skills/firebase-data-connect/reference/data_seeding.md +185 -0
- package/dist/global-skills/firebase-data-connect/reference/native_sql.md +170 -0
- package/dist/global-skills/firebase-data-connect/reference/operations.md +385 -0
- package/dist/global-skills/firebase-data-connect/reference/realtime.md +210 -0
- package/dist/global-skills/firebase-data-connect/reference/schema.md +290 -0
- package/dist/global-skills/firebase-data-connect/reference/sdk_admin_node.md +141 -0
- package/dist/global-skills/firebase-data-connect/reference/sdk_android.md +126 -0
- package/dist/global-skills/firebase-data-connect/reference/sdk_flutter.md +134 -0
- package/dist/global-skills/firebase-data-connect/reference/sdk_ios.md +157 -0
- package/dist/global-skills/firebase-data-connect/reference/sdk_web.md +146 -0
- package/dist/global-skills/firebase-data-connect/reference/search.md +264 -0
- package/dist/global-skills/firebase-data-connect/reference/security.md +295 -0
- package/dist/global-skills/firebase-data-connect/templates.md +318 -0
- package/dist/global-skills/firebase-firestore/SKILL.md +89 -0
- package/dist/global-skills/firebase-firestore/references/enterprise/android_sdk_usage.md +230 -0
- package/dist/global-skills/firebase-firestore/references/enterprise/data_model.md +66 -0
- package/dist/global-skills/firebase-firestore/references/enterprise/flutter_setup.md +180 -0
- package/dist/global-skills/firebase-firestore/references/enterprise/indexes.md +135 -0
- package/dist/global-skills/firebase-firestore/references/enterprise/ios_setup.md +189 -0
- package/dist/global-skills/firebase-firestore/references/enterprise/provisioning.md +118 -0
- package/dist/global-skills/firebase-firestore/references/enterprise/python_sdk_usage.md +138 -0
- package/dist/global-skills/firebase-firestore/references/enterprise/security_rules.md +577 -0
- package/dist/global-skills/firebase-firestore/references/enterprise/web_sdk_usage.md +127 -0
- package/dist/global-skills/firebase-firestore/references/standard/android_sdk_usage.md +193 -0
- package/dist/global-skills/firebase-firestore/references/standard/flutter_setup.md +176 -0
- package/dist/global-skills/firebase-firestore/references/standard/indexes.md +113 -0
- package/dist/global-skills/firebase-firestore/references/standard/ios_setup.md +174 -0
- package/dist/global-skills/firebase-firestore/references/standard/provisioning.md +110 -0
- package/dist/global-skills/firebase-firestore/references/standard/security_rules.md +577 -0
- package/dist/global-skills/firebase-firestore/references/standard/web_sdk_usage.md +192 -0
- package/dist/global-skills/firebase-hosting-basics/SKILL.md +64 -0
- package/dist/global-skills/firebase-hosting-basics/references/configuration.md +115 -0
- package/dist/global-skills/firebase-hosting-basics/references/deploying.md +48 -0
- package/dist/global-skills/firebase-remote-config-basics/SKILL.md +124 -0
- package/dist/global-skills/firebase-remote-config-basics/references/android_setup.md +91 -0
- package/dist/global-skills/firebase-remote-config-basics/references/ios_setup.md +89 -0
- package/dist/global-skills/firebase-security-rules-auditor/SKILL.md +70 -0
- package/dist/global-skills/go-live/SKILL.md +90 -0
- package/dist/global-skills/harden/SKILL.md +101 -0
- package/dist/global-skills/instrument-feature-flags/SKILL.md +88 -0
- package/dist/global-skills/instrument-feature-flags/references/adding-feature-flag-code.md +3578 -0
- package/dist/global-skills/instrument-feature-flags/references/android.md +146 -0
- package/dist/global-skills/instrument-feature-flags/references/api.md +194 -0
- package/dist/global-skills/instrument-feature-flags/references/best-practices.md +231 -0
- package/dist/global-skills/instrument-feature-flags/references/django.md +263 -0
- package/dist/global-skills/instrument-feature-flags/references/dotnet.md +763 -0
- package/dist/global-skills/instrument-feature-flags/references/elixir.md +47 -0
- package/dist/global-skills/instrument-feature-flags/references/flask.md +131 -0
- package/dist/global-skills/instrument-feature-flags/references/flutter.md +212 -0
- package/dist/global-skills/instrument-feature-flags/references/go.md +208 -0
- package/dist/global-skills/instrument-feature-flags/references/ios.md +146 -0
- package/dist/global-skills/instrument-feature-flags/references/java.md +94 -0
- package/dist/global-skills/instrument-feature-flags/references/laravel.md +170 -0
- package/dist/global-skills/instrument-feature-flags/references/next-js.md +383 -0
- package/dist/global-skills/instrument-feature-flags/references/nodejs.md +216 -0
- package/dist/global-skills/instrument-feature-flags/references/php.md +187 -0
- package/dist/global-skills/instrument-feature-flags/references/python.md +191 -0
- package/dist/global-skills/instrument-feature-flags/references/react-native.md +166 -0
- package/dist/global-skills/instrument-feature-flags/references/react.md +302 -0
- package/dist/global-skills/instrument-feature-flags/references/ruby-on-rails.md +604 -0
- package/dist/global-skills/instrument-feature-flags/references/ruby.md +200 -0
- package/dist/global-skills/instrument-feature-flags/references/rust.md +222 -0
- package/dist/global-skills/instrument-feature-flags/references/usage.md +600 -0
- package/dist/global-skills/instrument-feature-flags/references/web.md +193 -0
- package/dist/global-skills/instrument-product-analytics/SKILL.md +139 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-android.md +1639 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-angular.md +944 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-hybrid.md +1001 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-ssr.md +1004 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-static.md +720 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-view-transitions.md +810 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-django.md +1167 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-expo.md +1412 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-fastapi.md +1585 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-flask.md +1208 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-laravel.md +2267 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-next-app-router.md +712 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-next-pages-router.md +767 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-nuxt-3-6.md +939 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-nuxt-4.md +1078 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-php.md +527 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-python.md +481 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-native.md +1823 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-6.md +582 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-7-data.md +892 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-7-declarative.md +649 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-7-framework.md +1218 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-tanstack-router-code-based.md +793 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-tanstack-router-file-based.md +780 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-ruby-on-rails.md +1320 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-ruby.md +452 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-sveltekit.md +854 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-swift.md +665 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-tanstack-start.md +1199 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-vue-3.md +910 -0
- package/dist/global-skills/instrument-product-analytics/references/android.md +811 -0
- package/dist/global-skills/instrument-product-analytics/references/angular.md +376 -0
- package/dist/global-skills/instrument-product-analytics/references/astro.md +165 -0
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +299 -0
- package/dist/global-skills/instrument-product-analytics/references/django.md +263 -0
- package/dist/global-skills/instrument-product-analytics/references/dotnet.md +763 -0
- package/dist/global-skills/instrument-product-analytics/references/elixir.md +414 -0
- package/dist/global-skills/instrument-product-analytics/references/flask.md +131 -0
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +845 -0
- package/dist/global-skills/instrument-product-analytics/references/go.md +567 -0
- package/dist/global-skills/instrument-product-analytics/references/identify-users.md +272 -0
- package/dist/global-skills/instrument-product-analytics/references/ios.md +154 -0
- package/dist/global-skills/instrument-product-analytics/references/laravel.md +170 -0
- package/dist/global-skills/instrument-product-analytics/references/next-js.md +383 -0
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js-3-6.md +244 -0
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js.md +253 -0
- package/dist/global-skills/instrument-product-analytics/references/php.md +646 -0
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +1675 -0
- package/dist/global-skills/instrument-product-analytics/references/python.md +898 -0
- package/dist/global-skills/instrument-product-analytics/references/react-native.md +1338 -0
- package/dist/global-skills/instrument-product-analytics/references/react-router-v6.md +376 -0
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-data-mode.md +364 -0
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-declarative-mode.md +376 -0
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-framework-mode.md +479 -0
- package/dist/global-skills/instrument-product-analytics/references/ruby-on-rails.md +604 -0
- package/dist/global-skills/instrument-product-analytics/references/ruby.md +759 -0
- package/dist/global-skills/instrument-product-analytics/references/svelte.md +234 -0
- package/dist/global-skills/instrument-product-analytics/references/tanstack-start.md +193 -0
- package/dist/global-skills/instrument-product-analytics/references/usage.md +600 -0
- package/dist/global-skills/instrument-product-analytics/references/vue-js.md +306 -0
- package/dist/global-skills/manifest.json +125 -0
- package/dist/global-skills/mongodb-atlas-stream-processing/SKILL.md +284 -0
- package/dist/global-skills/mongodb-atlas-stream-processing/references/connection-configs.md +298 -0
- package/dist/global-skills/mongodb-atlas-stream-processing/references/development-workflow.md +304 -0
- package/dist/global-skills/mongodb-atlas-stream-processing/references/mcp-troubleshooting.md +55 -0
- package/dist/global-skills/mongodb-atlas-stream-processing/references/output-diagnostics.md +150 -0
- package/dist/global-skills/mongodb-atlas-stream-processing/references/pipeline-patterns.md +457 -0
- package/dist/global-skills/mongodb-atlas-stream-processing/references/sizing-and-parallelism.md +178 -0
- package/dist/global-skills/mongodb-connection/SKILL.md +201 -0
- package/dist/global-skills/mongodb-connection/references/monitoring-guide.md +191 -0
- package/dist/global-skills/mongodb-mcp-setup/SKILL.md +324 -0
- package/dist/global-skills/mongodb-natural-language-querying/SKILL.md +195 -0
- package/dist/global-skills/mongodb-query-optimizer/SKILL.md +150 -0
- package/dist/global-skills/mongodb-query-optimizer/references/aggregation-optimization.md +210 -0
- package/dist/global-skills/mongodb-query-optimizer/references/antipattern-examples.md +74 -0
- package/dist/global-skills/mongodb-query-optimizer/references/core-indexing-principles.md +134 -0
- package/dist/global-skills/mongodb-query-optimizer/references/update-query-examples.md +39 -0
- package/dist/global-skills/mongodb-schema-design/SKILL.md +181 -0
- package/dist/global-skills/mongodb-schema-design/references/antipattern-excessive-lookups.md +84 -0
- package/dist/global-skills/mongodb-schema-design/references/antipattern-unnecessary-collections.md +91 -0
- package/dist/global-skills/mongodb-schema-design/references/antipattern-unnecessary-indexes.md +95 -0
- package/dist/global-skills/mongodb-schema-design/references/fundamental-document-model.md +91 -0
- package/dist/global-skills/mongodb-schema-design/references/fundamental-document-size.md +226 -0
- package/dist/global-skills/mongodb-schema-design/references/fundamental-embed-vs-reference.md +418 -0
- package/dist/global-skills/mongodb-schema-design/references/fundamental-schema-validation.md +131 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-approximation.md +80 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-archive.md +143 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-attribute.md +77 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-bucket.md +102 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-computed.md +162 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-document-versioning.md +166 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-extended-reference.md +72 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-outlier.md +159 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-polymorphic.md +167 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-schema-versioning.md +273 -0
- package/dist/global-skills/mongodb-schema-design/references/pattern-time-series-collections.md +190 -0
- package/dist/global-skills/mongodb-schema-design/references/source-query-stats.md +123 -0
- package/dist/global-skills/mongodb-schema-design/references/source-slow-query-logs.md +63 -0
- package/dist/global-skills/mongodb-search-and-ai/SKILL.md +142 -0
- package/dist/global-skills/mongodb-search-and-ai/references/hybrid-search.md +697 -0
- package/dist/global-skills/mongodb-search-and-ai/references/lexical-search-indexing.md +584 -0
- package/dist/global-skills/mongodb-search-and-ai/references/lexical-search-querying.md +636 -0
- package/dist/global-skills/mongodb-search-and-ai/references/vector-search.md +746 -0
- package/dist/global-skills/native-data-fetching/SKILL.md +505 -0
- package/dist/global-skills/native-data-fetching/agents/openai.yaml +4 -0
- package/dist/global-skills/native-data-fetching/references/expo-router-loaders.md +341 -0
- package/dist/global-skills/neon/SKILL.md +343 -0
- package/dist/global-skills/neon-ai-gateway/SKILL.md +236 -0
- package/dist/global-skills/neon-functions/SKILL.md +490 -0
- package/dist/global-skills/neon-functions/references/ai-sdk.md +139 -0
- package/dist/global-skills/neon-functions/references/hono-websockets.md +145 -0
- package/dist/global-skills/neon-functions/references/mastra-studio.md +127 -0
- package/dist/global-skills/neon-functions/references/mcp.md +137 -0
- package/dist/global-skills/neon-functions/references/sentry.md +131 -0
- package/dist/global-skills/neon-functions/references/sse.md +143 -0
- package/dist/global-skills/neon-object-storage/SKILL.md +197 -0
- package/dist/global-skills/neon-postgres/SKILL.md +376 -0
- package/dist/global-skills/neon-postgres-branches/SKILL.md +281 -0
- package/dist/global-skills/neon-postgres-egress-optimizer/SKILL.md +247 -0
- package/dist/global-skills/onboarding/SKILL.md +101 -0
- package/dist/global-skills/plan-my-idea/SKILL.md +67 -0
- package/dist/global-skills/publish-app/SKILL.md +72 -0
- package/dist/global-skills/publish-extension/SKILL.md +47 -0
- package/dist/global-skills/resend/SKILL.md +294 -0
- package/dist/global-skills/resend/references/api-keys.md +98 -0
- package/dist/global-skills/resend/references/automations.md +228 -0
- package/dist/global-skills/resend/references/broadcasts.md +125 -0
- package/dist/global-skills/resend/references/contact-properties.md +111 -0
- package/dist/global-skills/resend/references/contacts.md +174 -0
- package/dist/global-skills/resend/references/domains.md +179 -0
- package/dist/global-skills/resend/references/events.md +119 -0
- package/dist/global-skills/resend/references/fetch-all-templates.mjs +37 -0
- package/dist/global-skills/resend/references/installation.md +142 -0
- package/dist/global-skills/resend/references/logs.md +161 -0
- package/dist/global-skills/resend/references/receiving.md +287 -0
- package/dist/global-skills/resend/references/segments.md +77 -0
- package/dist/global-skills/resend/references/sending/batch-email-examples.md +807 -0
- package/dist/global-skills/resend/references/sending/best-practices.md +453 -0
- package/dist/global-skills/resend/references/sending/email-management.md +135 -0
- package/dist/global-skills/resend/references/sending/overview.md +209 -0
- package/dist/global-skills/resend/references/sending/single-email-examples.md +470 -0
- package/dist/global-skills/resend/references/templates.md +202 -0
- package/dist/global-skills/resend/references/topics.md +104 -0
- package/dist/global-skills/resend/references/webhooks.md +317 -0
- package/dist/global-skills/reset-password/SKILL.md +59 -0
- package/dist/global-skills/save-data/SKILL.md +70 -0
- package/dist/global-skills/sentry-sdk-setup/SKILL.md +116 -0
- package/dist/global-skills/sentry-workflow/SKILL.md +32 -0
- package/dist/global-skills/setup-email/SKILL.md +69 -0
- package/dist/global-skills/setup-payments/SKILL.md +82 -0
- package/dist/global-skills/setup-sms/SKILL.md +51 -0
- package/dist/global-skills/sign-in-with-email-link/SKILL.md +53 -0
- package/dist/global-skills/sign-in-with-google/SKILL.md +68 -0
- package/dist/global-skills/sign-in-with-phone/SKILL.md +53 -0
- package/dist/global-skills/stripe-best-practices/SKILL.md +48 -0
- package/dist/global-skills/stripe-best-practices/references/billing.md +58 -0
- package/dist/global-skills/stripe-best-practices/references/connect.md +173 -0
- package/dist/global-skills/stripe-best-practices/references/payments.md +79 -0
- package/dist/global-skills/stripe-best-practices/references/security.md +109 -0
- package/dist/global-skills/stripe-best-practices/references/tax.md +37 -0
- package/dist/global-skills/stripe-best-practices/references/treasury.md +16 -0
- package/dist/global-skills/supabase/CHANGELOG.md +53 -0
- package/dist/global-skills/supabase/SKILL.md +145 -0
- package/dist/global-skills/supabase/assets/feedback-issue-template.md +17 -0
- package/dist/global-skills/supabase/references/skill-feedback.md +17 -0
- package/dist/global-skills/supabase-postgres-best-practices/CHANGELOG.md +43 -0
- package/dist/global-skills/supabase-postgres-best-practices/SKILL.md +64 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/_contributing.md +170 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/_sections.md +39 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/_template.md +34 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
- package/dist/global-skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -0
- package/dist/global-skills/track-errors/SKILL.md +67 -0
- package/dist/global-skills/update-kit/SKILL.md +75 -0
- package/dist/global-skills/upgrading-expo/SKILL.md +134 -0
- package/dist/global-skills/upgrading-expo/agents/openai.yaml +4 -0
- package/dist/global-skills/upgrading-expo/references/expo-av-to-audio.md +132 -0
- package/dist/global-skills/upgrading-expo/references/expo-av-to-video.md +160 -0
- package/dist/global-skills/upgrading-expo/references/native-tabs.md +124 -0
- package/dist/global-skills/upgrading-expo/references/new-architecture.md +79 -0
- package/dist/global-skills/upgrading-expo/references/react-19.md +79 -0
- package/dist/global-skills/upgrading-expo/references/react-compiler.md +59 -0
- package/dist/global-skills/upgrading-expo/references/react-navigation-to-expo-router.md +61 -0
- package/dist/global-skills/use-dom/SKILL.md +417 -0
- package/dist/global-skills/use-dom/agents/openai.yaml +4 -0
- package/dist/global-skills/use-kit-mcp/SKILL.md +100 -0
- package/dist/global-skills/use-railway/SKILL.md +357 -0
- package/dist/global-skills/use-railway/references/analyze-db-mongo.md +84 -0
- package/dist/global-skills/use-railway/references/analyze-db-mysql.md +254 -0
- package/dist/global-skills/use-railway/references/analyze-db-postgres.md +479 -0
- package/dist/global-skills/use-railway/references/analyze-db-redis.md +208 -0
- package/dist/global-skills/use-railway/references/analyze-db.md +344 -0
- package/dist/global-skills/use-railway/references/configure.md +359 -0
- package/dist/global-skills/use-railway/references/deploy.md +225 -0
- package/dist/global-skills/use-railway/references/feature-flags.md +89 -0
- package/dist/global-skills/use-railway/references/iac.md +108 -0
- package/dist/global-skills/use-railway/references/operate.md +273 -0
- package/dist/global-skills/use-railway/references/request.md +262 -0
- package/dist/global-skills/use-railway/references/sandbox.md +167 -0
- package/dist/global-skills/use-railway/references/setup.md +364 -0
- package/dist/global-skills/use-railway/scripts/analyze-mongo.py +1549 -0
- package/dist/global-skills/use-railway/scripts/analyze-mysql.py +1195 -0
- package/dist/global-skills/use-railway/scripts/analyze-postgres.py +3058 -0
- package/dist/global-skills/use-railway/scripts/analyze-redis.py +1090 -0
- package/dist/global-skills/use-railway/scripts/dal.py +671 -0
- package/dist/global-skills/use-railway/scripts/enable-pg-stats.py +170 -0
- package/dist/global-skills/use-railway/scripts/pg-extensions.py +370 -0
- package/dist/global-skills/use-railway/scripts/railway-api.sh +52 -0
- package/dist/global-skills/vercel-composition-patterns/AGENTS.md +946 -0
- package/dist/global-skills/vercel-composition-patterns/README.md +60 -0
- package/dist/global-skills/vercel-composition-patterns/SKILL.md +89 -0
- package/dist/global-skills/vercel-composition-patterns/metadata.json +11 -0
- package/dist/global-skills/vercel-composition-patterns/rules/_sections.md +29 -0
- package/dist/global-skills/vercel-composition-patterns/rules/_template.md +24 -0
- package/dist/global-skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/dist/global-skills/vercel-composition-patterns/rules/architecture-compound-components.md +112 -0
- package/dist/global-skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/dist/global-skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/dist/global-skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/dist/global-skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
- package/dist/global-skills/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/dist/global-skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
- package/dist/global-skills/vercel-react-best-practices/AGENTS.md +3810 -0
- package/dist/global-skills/vercel-react-best-practices/README.md +123 -0
- package/dist/global-skills/vercel-react-best-practices/SKILL.md +149 -0
- package/dist/global-skills/vercel-react-best-practices/metadata.json +15 -0
- package/dist/global-skills/vercel-react-best-practices/rules/_sections.md +46 -0
- package/dist/global-skills/vercel-react-best-practices/rules/_template.md +28 -0
- package/dist/global-skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md +56 -0
- package/dist/global-skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/dist/global-skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
- package/dist/global-skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
- package/dist/global-skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
- package/dist/global-skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/dist/global-skills/vercel-react-best-practices/rules/async-defer-await.md +82 -0
- package/dist/global-skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
- package/dist/global-skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
- package/dist/global-skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/dist/global-skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md +63 -0
- package/dist/global-skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
- package/dist/global-skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
- package/dist/global-skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/dist/global-skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/dist/global-skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
- package/dist/global-skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
- package/dist/global-skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/dist/global-skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/dist/global-skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/dist/global-skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/dist/global-skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-no-shared-module-state.md +50 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
- package/dist/global-skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
- package/dist/global-skills/web-to-native/SKILL.md +83 -0
- package/dist/global-skills/web-to-native/references/false-friends.md +119 -0
- package/dist/global-skills/web-to-native/references/native-patterns.md +39 -0
- package/dist/global-skills/web-to-native/references/run-as-goal.md +48 -0
- package/dist/global-skills/web-to-native/references/verify-on-device.md +45 -0
- package/dist/global-skills/wire-auth/SKILL.md +28 -0
- package/dist/global-skills/wire-database/SKILL.md +28 -0
- package/dist/global-skills/wire-email/SKILL.md +27 -0
- package/dist/global-skills/wire-payments/SKILL.md +27 -0
- package/dist/global-skills/workers-best-practices/SKILL.md +127 -0
- package/dist/global-skills/workers-best-practices/references/review.md +174 -0
- package/dist/global-skills/workers-best-practices/references/rules.md +463 -0
- package/dist/global-skills/wrangler/SKILL.md +922 -0
- package/dist/global-skills/xcode-project-setup/SKILL.md +140 -0
- package/dist/global-skills/xcode-project-setup/scripts/xcode_spm_setup/Package.resolved +41 -0
- package/dist/global-skills/xcode-project-setup/scripts/xcode_spm_setup/Package.swift +17 -0
- package/dist/global-skills/xcode-project-setup/scripts/xcode_spm_setup/Sources/main.swift +232 -0
- package/package.json +21 -20
- package/LICENSE.md +0 -47
- package/dist/index.js +0 -21593
|
@@ -0,0 +1,2267 @@
|
|
|
1
|
+
# PostHog laravel Example Project
|
|
2
|
+
|
|
3
|
+
Repository: https://github.com/PostHog/context-mill
|
|
4
|
+
Path: example-apps/laravel
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## README.md
|
|
9
|
+
|
|
10
|
+
# PostHog Laravel Example
|
|
11
|
+
|
|
12
|
+
A Laravel application demonstrating PostHog integration for analytics, feature flags, and error tracking using Livewire for reactive UI components.
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- User registration and authentication with Livewire
|
|
17
|
+
- SQLite database persistence with Eloquent ORM
|
|
18
|
+
- User identification and property tracking
|
|
19
|
+
- Custom event tracking (burrito consideration tracker)
|
|
20
|
+
- Page view tracking (dashboard, profile)
|
|
21
|
+
- Feature flags with payload support
|
|
22
|
+
- Error tracking with manual exception capture
|
|
23
|
+
- Reactive UI components with Livewire
|
|
24
|
+
|
|
25
|
+
## Tech Stack
|
|
26
|
+
|
|
27
|
+
- **Framework**: Laravel 11.x
|
|
28
|
+
- **Reactive Components**: Livewire 3.x
|
|
29
|
+
- **Database**: SQLite
|
|
30
|
+
- **Analytics**: PostHog PHP SDK
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
**Note**: This is a minimal implementation demonstrating PostHog integration. For a production application, you would need to install Laravel via Composer and set up additional dependencies.
|
|
35
|
+
|
|
36
|
+
### Manual Setup (Demonstration)
|
|
37
|
+
|
|
38
|
+
1. Install dependencies:
|
|
39
|
+
```bash
|
|
40
|
+
composer install
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
2. Set up environment:
|
|
44
|
+
```bash
|
|
45
|
+
cp .env.example .env
|
|
46
|
+
# Edit .env with your PostHog project token
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. Configure PostHog in `.env`:
|
|
50
|
+
```env
|
|
51
|
+
POSTHOG_PROJECT_TOKEN=your_posthog_project_token
|
|
52
|
+
POSTHOG_HOST=https://us.i.posthog.com
|
|
53
|
+
POSTHOG_DISABLED=false
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
4. Generate application key:
|
|
57
|
+
```bash
|
|
58
|
+
php artisan key:generate
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
5. Create database and run migrations:
|
|
62
|
+
```bash
|
|
63
|
+
touch database/database.sqlite
|
|
64
|
+
php artisan migrate --seed
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
6. Start the development server:
|
|
68
|
+
```bash
|
|
69
|
+
php artisan serve
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
7. Open http://localhost:8000 and either:
|
|
73
|
+
- Login with default credentials: `admin@example.com` / `admin`
|
|
74
|
+
- Or click "Sign up here" to create a new account
|
|
75
|
+
|
|
76
|
+
## PostHog Service
|
|
77
|
+
|
|
78
|
+
The `PostHogService` class (`app/Services/PostHogService.php`) wraps the PostHog PHP SDK and provides:
|
|
79
|
+
|
|
80
|
+
| Method | Description |
|
|
81
|
+
|--------|-------------|
|
|
82
|
+
| `identify($distinctId, $properties)` | Identify a user with properties |
|
|
83
|
+
| `capture($distinctId, $event, $properties)` | Capture custom events |
|
|
84
|
+
| `captureException($exception, $distinctId)` | Capture exceptions with stack traces |
|
|
85
|
+
| `isFeatureEnabled($key, $distinctId, $properties)` | Check feature flag status |
|
|
86
|
+
| `getFeatureFlagPayload($key, $distinctId)` | Get feature flag payload |
|
|
87
|
+
|
|
88
|
+
All methods check `config('posthog.disabled')` and return early if PostHog is disabled.
|
|
89
|
+
|
|
90
|
+
## PostHog Integration Points
|
|
91
|
+
|
|
92
|
+
### User Registration (`app/Http/Livewire/Auth/Register.php`)
|
|
93
|
+
New users are identified and tracked on signup:
|
|
94
|
+
```php
|
|
95
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
96
|
+
$posthog->capture($user->email, 'user_signed_up', [
|
|
97
|
+
'signup_method' => 'form',
|
|
98
|
+
]);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### User Login (`app/Http/Livewire/Auth/Login.php`)
|
|
102
|
+
Users are identified on login with their properties:
|
|
103
|
+
```php
|
|
104
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
105
|
+
$posthog->capture($user->email, 'user_logged_in', [
|
|
106
|
+
'login_method' => 'password',
|
|
107
|
+
]);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### User Logout (`routes/web.php`)
|
|
111
|
+
Logout events are tracked:
|
|
112
|
+
```php
|
|
113
|
+
$posthog->capture($user->email, 'user_logged_out');
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Page View Tracking
|
|
117
|
+
Dashboard and profile views are tracked (`app/Http/Livewire/Dashboard.php`, `app/Http/Livewire/Profile.php`):
|
|
118
|
+
```php
|
|
119
|
+
$posthog->capture($user->email, 'dashboard_viewed', [
|
|
120
|
+
'is_staff' => $user->is_staff,
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
$posthog->capture($user->email, 'profile_viewed');
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Custom Event Tracking (`app/Http/Livewire/BurritoTracker.php`)
|
|
127
|
+
The burrito tracker demonstrates custom event capture:
|
|
128
|
+
```php
|
|
129
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
130
|
+
$posthog->capture($user->email, 'burrito_considered', [
|
|
131
|
+
'total_considerations' => $this->burritoCount,
|
|
132
|
+
]);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Feature Flags (`app/Http/Livewire/Dashboard.php`)
|
|
136
|
+
The dashboard demonstrates feature flag checking:
|
|
137
|
+
```php
|
|
138
|
+
$this->showNewFeature = $posthog->isFeatureEnabled(
|
|
139
|
+
'new-dashboard-feature',
|
|
140
|
+
$user->email,
|
|
141
|
+
$user->getPostHogProperties()
|
|
142
|
+
) ?? false;
|
|
143
|
+
|
|
144
|
+
$this->featureConfig = $posthog->getFeatureFlagPayload(
|
|
145
|
+
'new-dashboard-feature',
|
|
146
|
+
$user->email
|
|
147
|
+
);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Error Tracking
|
|
151
|
+
Manual exception capture is demonstrated in multiple places:
|
|
152
|
+
|
|
153
|
+
**Livewire Components** (`app/Http/Livewire/Dashboard.php`, `app/Http/Livewire/Profile.php`):
|
|
154
|
+
```php
|
|
155
|
+
try {
|
|
156
|
+
throw new \Exception('This is a test error for PostHog tracking');
|
|
157
|
+
} catch (\Exception $e) {
|
|
158
|
+
$errorId = $posthog->captureException($e, $user->email);
|
|
159
|
+
$this->successMessage = "Error captured in PostHog! Error ID: {$errorId}";
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**API Endpoint** (`app/Http/Controllers/Api/ErrorTestController.php`):
|
|
164
|
+
```php
|
|
165
|
+
try {
|
|
166
|
+
throw new \Exception('Test exception from critical operation');
|
|
167
|
+
} catch (\Throwable $e) {
|
|
168
|
+
if ($shouldCapture) {
|
|
169
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
170
|
+
$eventId = $posthog->captureException($e, $user->email);
|
|
171
|
+
|
|
172
|
+
return response()->json([
|
|
173
|
+
'error' => 'Operation failed',
|
|
174
|
+
'error_id' => $eventId,
|
|
175
|
+
'message' => "Error captured in PostHog. Reference ID: {$eventId}",
|
|
176
|
+
], 500);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The `/api/test-error` endpoint demonstrates manual exception capture. Use `?capture=true` to capture in PostHog, or `?capture=false` to skip tracking.
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
## Pages
|
|
185
|
+
|
|
186
|
+
| Route | Component | PostHog Events |
|
|
187
|
+
|-------|-----------|----------------|
|
|
188
|
+
| `/` | Login | `user_logged_in` |
|
|
189
|
+
| `/register` | Register | `user_signed_up` |
|
|
190
|
+
| `/dashboard` | Dashboard | `dashboard_viewed`, feature flag checks |
|
|
191
|
+
| `/burrito` | BurritoTracker | `burrito_considered` |
|
|
192
|
+
| `/profile` | Profile | `profile_viewed` |
|
|
193
|
+
| `/logout` | (route) | `user_logged_out` |
|
|
194
|
+
|
|
195
|
+
## Project Structure
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
basics/laravel/
|
|
199
|
+
├── app/
|
|
200
|
+
│ ├── Http/
|
|
201
|
+
│ │ ├── Controllers/
|
|
202
|
+
│ │ │ └── Api/
|
|
203
|
+
│ │ │ ├── BurritoController.php # Burrito API endpoint
|
|
204
|
+
│ │ │ └── ErrorTestController.php # Error testing endpoint
|
|
205
|
+
│ │ └── Livewire/
|
|
206
|
+
│ │ ├── Auth/
|
|
207
|
+
│ │ │ ├── Login.php # Login component
|
|
208
|
+
│ │ │ └── Register.php # Registration component
|
|
209
|
+
│ │ ├── BurritoTracker.php # Burrito tracker component
|
|
210
|
+
│ │ ├── Dashboard.php # Dashboard with feature flags
|
|
211
|
+
│ │ └── Profile.php # User profile component
|
|
212
|
+
│ ├── Models/
|
|
213
|
+
│ │ └── User.php # User model with PostHog properties
|
|
214
|
+
│ └── Services/
|
|
215
|
+
│ └── PostHogService.php # PostHog wrapper service
|
|
216
|
+
├── database/
|
|
217
|
+
│ ├── migrations/ # Database migrations
|
|
218
|
+
│ └── seeders/
|
|
219
|
+
│ └── DatabaseSeeder.php # Seeds admin user
|
|
220
|
+
├── resources/
|
|
221
|
+
│ └── views/
|
|
222
|
+
│ ├── components/
|
|
223
|
+
│ │ └── layouts/
|
|
224
|
+
│ │ ├── app.blade.php # Authenticated layout
|
|
225
|
+
│ │ └── guest.blade.php # Guest layout
|
|
226
|
+
│ ├── errors/
|
|
227
|
+
│ │ ├── 404.blade.php # Not found page
|
|
228
|
+
│ │ └── 500.blade.php # Server error page
|
|
229
|
+
│ └── livewire/
|
|
230
|
+
│ ├── auth/
|
|
231
|
+
│ │ ├── login.blade.php # Login form
|
|
232
|
+
│ │ └── register.blade.php # Registration form
|
|
233
|
+
│ ├── burrito-tracker.blade.php # Burrito tracker UI
|
|
234
|
+
│ ├── dashboard.blade.php # Dashboard UI
|
|
235
|
+
│ └── profile.blade.php # Profile UI
|
|
236
|
+
├── routes/
|
|
237
|
+
│ ├── web.php # Web routes (auth, pages)
|
|
238
|
+
│ └── api.php # API routes
|
|
239
|
+
└── config/
|
|
240
|
+
└── posthog.php # PostHog configuration
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Development Commands
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# Start development server
|
|
247
|
+
php artisan serve
|
|
248
|
+
|
|
249
|
+
# Run migrations
|
|
250
|
+
php artisan migrate
|
|
251
|
+
|
|
252
|
+
# Seed database
|
|
253
|
+
php artisan migrate:fresh --seed
|
|
254
|
+
|
|
255
|
+
# Clear caches
|
|
256
|
+
php artisan optimize:clear
|
|
257
|
+
```
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## .env.example
|
|
261
|
+
|
|
262
|
+
```example
|
|
263
|
+
APP_NAME="PostHog Laravel Example"
|
|
264
|
+
APP_ENV=local
|
|
265
|
+
APP_KEY=
|
|
266
|
+
APP_DEBUG=true
|
|
267
|
+
APP_URL=http://localhost:8000
|
|
268
|
+
|
|
269
|
+
DB_CONNECTION=sqlite
|
|
270
|
+
# DB_DATABASE will use default database/database.sqlite
|
|
271
|
+
|
|
272
|
+
CACHE_DRIVER=file
|
|
273
|
+
CACHE_STORE=file
|
|
274
|
+
|
|
275
|
+
SESSION_DRIVER=file
|
|
276
|
+
SESSION_LIFETIME=120
|
|
277
|
+
|
|
278
|
+
POSTHOG_PROJECT_TOKEN=your_posthog_project_token_here
|
|
279
|
+
POSTHOG_HOST=https://us.i.posthog.com
|
|
280
|
+
POSTHOG_DISABLED=false
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## app/Http/Controllers/Api/BurritoController.php
|
|
287
|
+
|
|
288
|
+
```php
|
|
289
|
+
<?php
|
|
290
|
+
|
|
291
|
+
namespace App\Http\Controllers\Api;
|
|
292
|
+
|
|
293
|
+
use App\Http\Controllers\Controller;
|
|
294
|
+
use App\Services\PostHogService;
|
|
295
|
+
use Illuminate\Http\JsonResponse;
|
|
296
|
+
use Illuminate\Http\Request;
|
|
297
|
+
use Illuminate\Support\Facades\Auth;
|
|
298
|
+
|
|
299
|
+
class BurritoController extends Controller
|
|
300
|
+
{
|
|
301
|
+
public function consider(Request $request, PostHogService $posthog): JsonResponse
|
|
302
|
+
{
|
|
303
|
+
$user = Auth::user();
|
|
304
|
+
|
|
305
|
+
// Increment session counter
|
|
306
|
+
$burritoCount = session('burrito_count', 0) + 1;
|
|
307
|
+
session(['burrito_count' => $burritoCount]);
|
|
308
|
+
|
|
309
|
+
// PostHog: Track event
|
|
310
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
311
|
+
$posthog->capture($user->email, 'burrito_considered', [
|
|
312
|
+
'total_considerations' => $burritoCount,
|
|
313
|
+
]);
|
|
314
|
+
|
|
315
|
+
return response()->json([
|
|
316
|
+
'success' => true,
|
|
317
|
+
'count' => $burritoCount,
|
|
318
|
+
]);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## app/Http/Controllers/Api/ErrorTestController.php
|
|
327
|
+
|
|
328
|
+
```php
|
|
329
|
+
<?php
|
|
330
|
+
|
|
331
|
+
namespace App\Http\Controllers\Api;
|
|
332
|
+
|
|
333
|
+
use App\Http\Controllers\Controller;
|
|
334
|
+
use App\Services\PostHogService;
|
|
335
|
+
use Illuminate\Http\JsonResponse;
|
|
336
|
+
use Illuminate\Http\Request;
|
|
337
|
+
use Illuminate\Support\Facades\Auth;
|
|
338
|
+
|
|
339
|
+
class ErrorTestController extends Controller
|
|
340
|
+
{
|
|
341
|
+
public function test(Request $request, PostHogService $posthog): JsonResponse
|
|
342
|
+
{
|
|
343
|
+
$shouldCapture = $request->query('capture', 'true') === 'true';
|
|
344
|
+
$user = Auth::user();
|
|
345
|
+
|
|
346
|
+
try {
|
|
347
|
+
throw new \Exception('Test exception from critical operation');
|
|
348
|
+
} catch (\Throwable $e) {
|
|
349
|
+
if ($shouldCapture) {
|
|
350
|
+
// Capture in PostHog
|
|
351
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
352
|
+
$eventId = $posthog->captureException($e, $user->email);
|
|
353
|
+
|
|
354
|
+
return response()->json([
|
|
355
|
+
'error' => 'Operation failed',
|
|
356
|
+
'error_id' => $eventId,
|
|
357
|
+
'message' => "Error captured in PostHog. Reference ID: {$eventId}",
|
|
358
|
+
], 500);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return response()->json([
|
|
362
|
+
'error' => $e->getMessage(),
|
|
363
|
+
], 500);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## app/Http/Controllers/Controller.php
|
|
373
|
+
|
|
374
|
+
```php
|
|
375
|
+
<?php
|
|
376
|
+
|
|
377
|
+
namespace App\Http\Controllers;
|
|
378
|
+
|
|
379
|
+
abstract class Controller
|
|
380
|
+
{
|
|
381
|
+
//
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## app/Http/Livewire/Auth/Login.php
|
|
389
|
+
|
|
390
|
+
```php
|
|
391
|
+
<?php
|
|
392
|
+
|
|
393
|
+
namespace App\Http\Livewire\Auth;
|
|
394
|
+
|
|
395
|
+
use App\Services\PostHogService;
|
|
396
|
+
use Illuminate\Support\Facades\Auth;
|
|
397
|
+
use Livewire\Component;
|
|
398
|
+
|
|
399
|
+
class Login extends Component
|
|
400
|
+
{
|
|
401
|
+
public string $email = '';
|
|
402
|
+
public string $password = '';
|
|
403
|
+
public bool $remember = false;
|
|
404
|
+
|
|
405
|
+
protected $rules = [
|
|
406
|
+
'email' => 'required|email',
|
|
407
|
+
'password' => 'required',
|
|
408
|
+
];
|
|
409
|
+
|
|
410
|
+
public function login(PostHogService $posthog)
|
|
411
|
+
{
|
|
412
|
+
$this->validate();
|
|
413
|
+
|
|
414
|
+
if (Auth::attempt(['email' => $this->email, 'password' => $this->password], $this->remember)) {
|
|
415
|
+
$user = Auth::user();
|
|
416
|
+
|
|
417
|
+
// PostHog: Identify and track login
|
|
418
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
419
|
+
$posthog->capture($user->email, 'user_logged_in', [
|
|
420
|
+
'login_method' => 'password',
|
|
421
|
+
]);
|
|
422
|
+
|
|
423
|
+
session()->regenerate();
|
|
424
|
+
|
|
425
|
+
return redirect()->intended(route('dashboard'));
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
$this->addError('email', 'Invalid credentials');
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
public function render()
|
|
432
|
+
{
|
|
433
|
+
return view('livewire.auth.login')
|
|
434
|
+
->layout('components.layouts.guest');
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## app/Http/Livewire/Auth/Register.php
|
|
443
|
+
|
|
444
|
+
```php
|
|
445
|
+
<?php
|
|
446
|
+
|
|
447
|
+
namespace App\Http\Livewire\Auth;
|
|
448
|
+
|
|
449
|
+
use App\Models\User;
|
|
450
|
+
use App\Services\PostHogService;
|
|
451
|
+
use Illuminate\Support\Facades\Auth;
|
|
452
|
+
use Livewire\Component;
|
|
453
|
+
|
|
454
|
+
class Register extends Component
|
|
455
|
+
{
|
|
456
|
+
public string $email = '';
|
|
457
|
+
public string $password = '';
|
|
458
|
+
public string $password_confirmation = '';
|
|
459
|
+
|
|
460
|
+
protected $rules = [
|
|
461
|
+
'email' => 'required|email|unique:users,email',
|
|
462
|
+
'password' => 'required|min:6|confirmed',
|
|
463
|
+
];
|
|
464
|
+
|
|
465
|
+
public function register(PostHogService $posthog)
|
|
466
|
+
{
|
|
467
|
+
$validated = $this->validate();
|
|
468
|
+
|
|
469
|
+
$user = User::create([
|
|
470
|
+
'email' => $validated['email'],
|
|
471
|
+
'password' => bcrypt($validated['password']),
|
|
472
|
+
'is_staff' => false,
|
|
473
|
+
]);
|
|
474
|
+
|
|
475
|
+
// PostHog: Identify new user and track signup
|
|
476
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
477
|
+
$posthog->capture($user->email, 'user_signed_up', [
|
|
478
|
+
'signup_method' => 'form',
|
|
479
|
+
]);
|
|
480
|
+
|
|
481
|
+
Auth::login($user);
|
|
482
|
+
|
|
483
|
+
session()->flash('success', 'Account created successfully!');
|
|
484
|
+
|
|
485
|
+
return redirect()->route('dashboard');
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
public function render()
|
|
489
|
+
{
|
|
490
|
+
return view('livewire.auth.register')
|
|
491
|
+
->layout('components.layouts.guest');
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## app/Http/Livewire/BurritoTracker.php
|
|
500
|
+
|
|
501
|
+
```php
|
|
502
|
+
<?php
|
|
503
|
+
|
|
504
|
+
namespace App\Http\Livewire;
|
|
505
|
+
|
|
506
|
+
use App\Services\PostHogService;
|
|
507
|
+
use Illuminate\Support\Facades\Auth;
|
|
508
|
+
use Livewire\Component;
|
|
509
|
+
|
|
510
|
+
class BurritoTracker extends Component
|
|
511
|
+
{
|
|
512
|
+
public int $burritoCount = 0;
|
|
513
|
+
|
|
514
|
+
public function mount()
|
|
515
|
+
{
|
|
516
|
+
$this->burritoCount = session('burrito_count', 0);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
public function considerBurrito(PostHogService $posthog)
|
|
520
|
+
{
|
|
521
|
+
$this->burritoCount++;
|
|
522
|
+
session(['burrito_count' => $this->burritoCount]);
|
|
523
|
+
|
|
524
|
+
// PostHog: Track burrito consideration
|
|
525
|
+
$user = Auth::user();
|
|
526
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
527
|
+
$posthog->capture($user->email, 'burrito_considered', [
|
|
528
|
+
'total_considerations' => $this->burritoCount,
|
|
529
|
+
]);
|
|
530
|
+
|
|
531
|
+
$this->dispatch('burrito-considered');
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
public function render()
|
|
535
|
+
{
|
|
536
|
+
return view('livewire.burrito-tracker')
|
|
537
|
+
->layout('components.layouts.app');
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## app/Http/Livewire/Dashboard.php
|
|
546
|
+
|
|
547
|
+
```php
|
|
548
|
+
<?php
|
|
549
|
+
|
|
550
|
+
namespace App\Http\Livewire;
|
|
551
|
+
|
|
552
|
+
use App\Services\PostHogService;
|
|
553
|
+
use Illuminate\Support\Facades\Auth;
|
|
554
|
+
use Livewire\Component;
|
|
555
|
+
|
|
556
|
+
class Dashboard extends Component
|
|
557
|
+
{
|
|
558
|
+
public bool $showNewFeature = false;
|
|
559
|
+
public $featureConfig = null;
|
|
560
|
+
public ?string $errorMessage = null;
|
|
561
|
+
public ?string $successMessage = null;
|
|
562
|
+
|
|
563
|
+
public function mount(PostHogService $posthog)
|
|
564
|
+
{
|
|
565
|
+
$user = Auth::user();
|
|
566
|
+
|
|
567
|
+
// PostHog: Track dashboard view
|
|
568
|
+
$posthog->capture($user->email, 'dashboard_viewed', [
|
|
569
|
+
'is_staff' => $user->is_staff,
|
|
570
|
+
]);
|
|
571
|
+
|
|
572
|
+
// Check feature flag
|
|
573
|
+
$this->showNewFeature = $posthog->isFeatureEnabled(
|
|
574
|
+
'new-dashboard-feature',
|
|
575
|
+
$user->email,
|
|
576
|
+
$user->getPostHogProperties()
|
|
577
|
+
) ?? false;
|
|
578
|
+
|
|
579
|
+
// Get feature flag payload
|
|
580
|
+
$this->featureConfig = $posthog->getFeatureFlagPayload(
|
|
581
|
+
'new-dashboard-feature',
|
|
582
|
+
$user->email
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
public function testErrorWithCapture(PostHogService $posthog)
|
|
587
|
+
{
|
|
588
|
+
$user = Auth::user();
|
|
589
|
+
|
|
590
|
+
try {
|
|
591
|
+
// Simulate an error
|
|
592
|
+
throw new \Exception('This is a test error for PostHog tracking');
|
|
593
|
+
} catch (\Exception $e) {
|
|
594
|
+
// Capture the exception in PostHog
|
|
595
|
+
$errorId = $posthog->captureException($e, $user->email);
|
|
596
|
+
|
|
597
|
+
$this->successMessage = "Error captured in PostHog! Error ID: {$errorId}";
|
|
598
|
+
$this->errorMessage = null;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
public function testErrorWithoutCapture()
|
|
603
|
+
{
|
|
604
|
+
try {
|
|
605
|
+
// Simulate an error without capturing
|
|
606
|
+
throw new \Exception('This error was NOT sent to PostHog');
|
|
607
|
+
} catch (\Exception $e) {
|
|
608
|
+
$this->errorMessage = "Error occurred but NOT captured in PostHog: " . $e->getMessage();
|
|
609
|
+
$this->successMessage = null;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
public function render()
|
|
614
|
+
{
|
|
615
|
+
return view('livewire.dashboard')
|
|
616
|
+
->layout('components.layouts.app');
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
---
|
|
623
|
+
|
|
624
|
+
## app/Http/Livewire/Profile.php
|
|
625
|
+
|
|
626
|
+
```php
|
|
627
|
+
<?php
|
|
628
|
+
|
|
629
|
+
namespace App\Http\Livewire;
|
|
630
|
+
|
|
631
|
+
use App\Services\PostHogService;
|
|
632
|
+
use Illuminate\Support\Facades\Auth;
|
|
633
|
+
use Livewire\Component;
|
|
634
|
+
|
|
635
|
+
class Profile extends Component
|
|
636
|
+
{
|
|
637
|
+
public ?string $errorMessage = null;
|
|
638
|
+
public ?string $successMessage = null;
|
|
639
|
+
|
|
640
|
+
public function mount(PostHogService $posthog)
|
|
641
|
+
{
|
|
642
|
+
$user = Auth::user();
|
|
643
|
+
|
|
644
|
+
// PostHog: Track profile view
|
|
645
|
+
$posthog->capture($user->email, 'profile_viewed');
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
public function testErrorWithCapture(PostHogService $posthog)
|
|
649
|
+
{
|
|
650
|
+
$user = Auth::user();
|
|
651
|
+
|
|
652
|
+
try {
|
|
653
|
+
// Simulate an error
|
|
654
|
+
throw new \Exception('This is a test error for PostHog tracking');
|
|
655
|
+
} catch (\Exception $e) {
|
|
656
|
+
// Capture the exception in PostHog
|
|
657
|
+
$errorId = $posthog->captureException($e, $user->email);
|
|
658
|
+
|
|
659
|
+
$this->successMessage = "Error captured in PostHog! Error ID: {$errorId}";
|
|
660
|
+
$this->errorMessage = null;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
public function testErrorWithoutCapture()
|
|
665
|
+
{
|
|
666
|
+
try {
|
|
667
|
+
// Simulate an error without capturing
|
|
668
|
+
throw new \Exception('This error was NOT sent to PostHog');
|
|
669
|
+
} catch (\Exception $e) {
|
|
670
|
+
$this->errorMessage = "Error occurred but NOT captured in PostHog: " . $e->getMessage();
|
|
671
|
+
$this->successMessage = null;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
public function render()
|
|
676
|
+
{
|
|
677
|
+
return view('livewire.profile')
|
|
678
|
+
->layout('components.layouts.app');
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
---
|
|
685
|
+
|
|
686
|
+
## app/Models/User.php
|
|
687
|
+
|
|
688
|
+
```php
|
|
689
|
+
<?php
|
|
690
|
+
|
|
691
|
+
namespace App\Models;
|
|
692
|
+
|
|
693
|
+
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
694
|
+
use Illuminate\Foundation\Auth\User as Authenticatable;
|
|
695
|
+
use Illuminate\Notifications\Notifiable;
|
|
696
|
+
|
|
697
|
+
class User extends Authenticatable
|
|
698
|
+
{
|
|
699
|
+
use HasFactory, Notifiable;
|
|
700
|
+
|
|
701
|
+
protected $fillable = [
|
|
702
|
+
'email',
|
|
703
|
+
'password',
|
|
704
|
+
'is_staff',
|
|
705
|
+
];
|
|
706
|
+
|
|
707
|
+
protected $hidden = [
|
|
708
|
+
'password',
|
|
709
|
+
'remember_token',
|
|
710
|
+
];
|
|
711
|
+
|
|
712
|
+
protected function casts(): array
|
|
713
|
+
{
|
|
714
|
+
return [
|
|
715
|
+
'password' => 'hashed',
|
|
716
|
+
'is_staff' => 'boolean',
|
|
717
|
+
];
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Get PostHog person properties for this user.
|
|
722
|
+
*/
|
|
723
|
+
public function getPostHogProperties(): array
|
|
724
|
+
{
|
|
725
|
+
return [
|
|
726
|
+
'email' => $this->email,
|
|
727
|
+
'is_staff' => $this->is_staff,
|
|
728
|
+
'date_joined' => $this->created_at->toISOString(),
|
|
729
|
+
];
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
---
|
|
736
|
+
|
|
737
|
+
## app/Services/PostHogService.php
|
|
738
|
+
|
|
739
|
+
```php
|
|
740
|
+
<?php
|
|
741
|
+
|
|
742
|
+
namespace App\Services;
|
|
743
|
+
|
|
744
|
+
use PostHog\PostHog;
|
|
745
|
+
use Illuminate\Support\Facades\Auth;
|
|
746
|
+
|
|
747
|
+
class PostHogService
|
|
748
|
+
{
|
|
749
|
+
protected static $initialized = false;
|
|
750
|
+
|
|
751
|
+
public function __construct()
|
|
752
|
+
{
|
|
753
|
+
if (config('posthog.disabled')) {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// Initialize PostHog once
|
|
758
|
+
if (!self::$initialized) {
|
|
759
|
+
PostHog::init(
|
|
760
|
+
config('posthog.api_key'),
|
|
761
|
+
[
|
|
762
|
+
'host' => config('posthog.host'),
|
|
763
|
+
'debug' => config('posthog.debug'),
|
|
764
|
+
]
|
|
765
|
+
);
|
|
766
|
+
self::$initialized = true;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
public function identify(string $distinctId, array $properties = []): void
|
|
771
|
+
{
|
|
772
|
+
if (config('posthog.disabled')) {
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
PostHog::identify([
|
|
777
|
+
'distinctId' => $distinctId,
|
|
778
|
+
'properties' => $properties,
|
|
779
|
+
]);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
public function capture(string $distinctId, string $event, array $properties = []): void
|
|
783
|
+
{
|
|
784
|
+
if (config('posthog.disabled')) {
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
PostHog::capture([
|
|
789
|
+
'distinctId' => $distinctId,
|
|
790
|
+
'event' => $event,
|
|
791
|
+
'properties' => $properties,
|
|
792
|
+
]);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
public function captureException(\Throwable $exception, ?string $distinctId = null): ?string
|
|
796
|
+
{
|
|
797
|
+
if (config('posthog.disabled')) {
|
|
798
|
+
return null;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
$distinctId = $distinctId ?? Auth::user()?->email ?? 'anonymous';
|
|
802
|
+
|
|
803
|
+
$eventId = uniqid('error_', true);
|
|
804
|
+
|
|
805
|
+
PostHog::captureException($exception, $distinctId, [
|
|
806
|
+
'error_id' => $eventId,
|
|
807
|
+
]);
|
|
808
|
+
|
|
809
|
+
return $eventId;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
public function isFeatureEnabled(string $key, string $distinctId, array $properties = []): ?bool
|
|
813
|
+
{
|
|
814
|
+
if (config('posthog.disabled')) {
|
|
815
|
+
return false;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
return PostHog::isFeatureEnabled($key, $distinctId, $properties);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
public function getFeatureFlagPayload(string $key, string $distinctId)
|
|
822
|
+
{
|
|
823
|
+
if (config('posthog.disabled')) {
|
|
824
|
+
return null;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
return PostHog::getFeatureFlagPayload($key, $distinctId);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
---
|
|
834
|
+
|
|
835
|
+
## artisan
|
|
836
|
+
|
|
837
|
+
```
|
|
838
|
+
#!/usr/bin/env php
|
|
839
|
+
<?php
|
|
840
|
+
|
|
841
|
+
define('LARAVEL_START', microtime(true));
|
|
842
|
+
|
|
843
|
+
/*
|
|
844
|
+
|--------------------------------------------------------------------------
|
|
845
|
+
| Register The Auto Loader
|
|
846
|
+
|--------------------------------------------------------------------------
|
|
847
|
+
*/
|
|
848
|
+
|
|
849
|
+
require __DIR__.'/vendor/autoload.php';
|
|
850
|
+
|
|
851
|
+
$app = require_once __DIR__.'/bootstrap/app.php';
|
|
852
|
+
|
|
853
|
+
/*
|
|
854
|
+
|--------------------------------------------------------------------------
|
|
855
|
+
| Run The Artisan Application
|
|
856
|
+
|--------------------------------------------------------------------------
|
|
857
|
+
*/
|
|
858
|
+
|
|
859
|
+
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
|
860
|
+
|
|
861
|
+
$status = $kernel->handle(
|
|
862
|
+
$input = new Symfony\Component\Console\Input\ArgvInput,
|
|
863
|
+
new Symfony\Component\Console\Output\ConsoleOutput
|
|
864
|
+
);
|
|
865
|
+
|
|
866
|
+
$kernel->terminate($input, $status);
|
|
867
|
+
|
|
868
|
+
exit($status);
|
|
869
|
+
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
---
|
|
873
|
+
|
|
874
|
+
## bootstrap/app.php
|
|
875
|
+
|
|
876
|
+
```php
|
|
877
|
+
<?php
|
|
878
|
+
|
|
879
|
+
use Illuminate\Foundation\Application;
|
|
880
|
+
use Illuminate\Foundation\Configuration\Exceptions;
|
|
881
|
+
use Illuminate\Foundation\Configuration\Middleware;
|
|
882
|
+
|
|
883
|
+
return Application::configure(basePath: dirname(__DIR__))
|
|
884
|
+
->withRouting(
|
|
885
|
+
web: __DIR__.'/../routes/web.php',
|
|
886
|
+
api: __DIR__.'/../routes/api.php',
|
|
887
|
+
commands: __DIR__.'/../routes/console.php',
|
|
888
|
+
health: '/up',
|
|
889
|
+
)
|
|
890
|
+
->withMiddleware(function (Middleware $middleware) {
|
|
891
|
+
//
|
|
892
|
+
})
|
|
893
|
+
->withExceptions(function (Exceptions $exceptions) {
|
|
894
|
+
//
|
|
895
|
+
})->create();
|
|
896
|
+
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
---
|
|
900
|
+
|
|
901
|
+
## config/app.php
|
|
902
|
+
|
|
903
|
+
```php
|
|
904
|
+
<?php
|
|
905
|
+
|
|
906
|
+
return [
|
|
907
|
+
'name' => env('APP_NAME', 'PostHog Laravel Example'),
|
|
908
|
+
'env' => env('APP_ENV', 'production'),
|
|
909
|
+
'debug' => (bool) env('APP_DEBUG', false),
|
|
910
|
+
'url' => env('APP_URL', 'http://localhost'),
|
|
911
|
+
'timezone' => 'UTC',
|
|
912
|
+
'locale' => 'en',
|
|
913
|
+
'fallback_locale' => 'en',
|
|
914
|
+
'key' => env('APP_KEY'),
|
|
915
|
+
'cipher' => 'AES-256-CBC',
|
|
916
|
+
|
|
917
|
+
'providers' => [
|
|
918
|
+
// Laravel Framework Service Providers
|
|
919
|
+
Illuminate\Auth\AuthServiceProvider::class,
|
|
920
|
+
Illuminate\Broadcasting\BroadcastServiceProvider::class,
|
|
921
|
+
Illuminate\Bus\BusServiceProvider::class,
|
|
922
|
+
Illuminate\Cache\CacheServiceProvider::class,
|
|
923
|
+
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
|
|
924
|
+
Illuminate\Cookie\CookieServiceProvider::class,
|
|
925
|
+
Illuminate\Database\DatabaseServiceProvider::class,
|
|
926
|
+
Illuminate\Encryption\EncryptionServiceProvider::class,
|
|
927
|
+
Illuminate\Filesystem\FilesystemServiceProvider::class,
|
|
928
|
+
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
|
|
929
|
+
Illuminate\Hashing\HashServiceProvider::class,
|
|
930
|
+
Illuminate\Mail\MailServiceProvider::class,
|
|
931
|
+
Illuminate\Notifications\NotificationServiceProvider::class,
|
|
932
|
+
Illuminate\Pagination\PaginationServiceProvider::class,
|
|
933
|
+
Illuminate\Pipeline\PipelineServiceProvider::class,
|
|
934
|
+
Illuminate\Queue\QueueServiceProvider::class,
|
|
935
|
+
Illuminate\Redis\RedisServiceProvider::class,
|
|
936
|
+
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
|
|
937
|
+
Illuminate\Session\SessionServiceProvider::class,
|
|
938
|
+
Illuminate\Translation\TranslationServiceProvider::class,
|
|
939
|
+
Illuminate\Validation\ValidationServiceProvider::class,
|
|
940
|
+
Illuminate\View\ViewServiceProvider::class,
|
|
941
|
+
],
|
|
942
|
+
|
|
943
|
+
'aliases' => [
|
|
944
|
+
'App' => Illuminate\Support\Facades\App::class,
|
|
945
|
+
'Auth' => Illuminate\Support\Facades\Auth::class,
|
|
946
|
+
'Blade' => Illuminate\Support\Facades\Blade::class,
|
|
947
|
+
'Cache' => Illuminate\Support\Facades\Cache::class,
|
|
948
|
+
'Config' => Illuminate\Support\Facades\Config::class,
|
|
949
|
+
'DB' => Illuminate\Support\Facades\DB::class,
|
|
950
|
+
'Hash' => Illuminate\Support\Facades\Hash::class,
|
|
951
|
+
'Request' => Illuminate\Support\Facades\Request::class,
|
|
952
|
+
'Route' => Illuminate\Support\Facades\Route::class,
|
|
953
|
+
'Schema' => Illuminate\Support\Facades\Schema::class,
|
|
954
|
+
'Session' => Illuminate\Support\Facades\Session::class,
|
|
955
|
+
'View' => Illuminate\Support\Facades\View::class,
|
|
956
|
+
],
|
|
957
|
+
];
|
|
958
|
+
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
---
|
|
962
|
+
|
|
963
|
+
## config/auth.php
|
|
964
|
+
|
|
965
|
+
```php
|
|
966
|
+
<?php
|
|
967
|
+
|
|
968
|
+
return [
|
|
969
|
+
'defaults' => [
|
|
970
|
+
'guard' => 'web',
|
|
971
|
+
'passwords' => 'users',
|
|
972
|
+
],
|
|
973
|
+
|
|
974
|
+
'guards' => [
|
|
975
|
+
'web' => [
|
|
976
|
+
'driver' => 'session',
|
|
977
|
+
'provider' => 'users',
|
|
978
|
+
],
|
|
979
|
+
],
|
|
980
|
+
|
|
981
|
+
'providers' => [
|
|
982
|
+
'users' => [
|
|
983
|
+
'driver' => 'eloquent',
|
|
984
|
+
'model' => App\Models\User::class,
|
|
985
|
+
],
|
|
986
|
+
],
|
|
987
|
+
|
|
988
|
+
'passwords' => [
|
|
989
|
+
'users' => [
|
|
990
|
+
'provider' => 'users',
|
|
991
|
+
'table' => 'password_reset_tokens',
|
|
992
|
+
'expire' => 60,
|
|
993
|
+
'throttle' => 60,
|
|
994
|
+
],
|
|
995
|
+
],
|
|
996
|
+
|
|
997
|
+
'password_timeout' => 10800,
|
|
998
|
+
];
|
|
999
|
+
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
---
|
|
1003
|
+
|
|
1004
|
+
## config/database.php
|
|
1005
|
+
|
|
1006
|
+
```php
|
|
1007
|
+
<?php
|
|
1008
|
+
|
|
1009
|
+
return [
|
|
1010
|
+
'default' => env('DB_CONNECTION', 'sqlite'),
|
|
1011
|
+
|
|
1012
|
+
'connections' => [
|
|
1013
|
+
'sqlite' => [
|
|
1014
|
+
'driver' => 'sqlite',
|
|
1015
|
+
'url' => env('DATABASE_URL'),
|
|
1016
|
+
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
|
1017
|
+
'prefix' => '',
|
|
1018
|
+
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
|
1019
|
+
],
|
|
1020
|
+
|
|
1021
|
+
'mysql' => [
|
|
1022
|
+
'driver' => 'mysql',
|
|
1023
|
+
'url' => env('DATABASE_URL'),
|
|
1024
|
+
'host' => env('DB_HOST', '127.0.0.1'),
|
|
1025
|
+
'port' => env('DB_PORT', '3306'),
|
|
1026
|
+
'database' => env('DB_DATABASE', 'forge'),
|
|
1027
|
+
'username' => env('DB_USERNAME', 'forge'),
|
|
1028
|
+
'password' => env('DB_PASSWORD', ''),
|
|
1029
|
+
'charset' => 'utf8mb4',
|
|
1030
|
+
'collation' => 'utf8mb4_unicode_ci',
|
|
1031
|
+
'prefix' => '',
|
|
1032
|
+
'strict' => true,
|
|
1033
|
+
'engine' => null,
|
|
1034
|
+
],
|
|
1035
|
+
],
|
|
1036
|
+
|
|
1037
|
+
'migrations' => 'migrations',
|
|
1038
|
+
];
|
|
1039
|
+
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
---
|
|
1043
|
+
|
|
1044
|
+
## config/posthog.php
|
|
1045
|
+
|
|
1046
|
+
```php
|
|
1047
|
+
<?php
|
|
1048
|
+
|
|
1049
|
+
return [
|
|
1050
|
+
'api_key' => env('POSTHOG_PROJECT_TOKEN', ''),
|
|
1051
|
+
'host' => env('POSTHOG_HOST', 'https://us.i.posthog.com'),
|
|
1052
|
+
'disabled' => env('POSTHOG_DISABLED', false),
|
|
1053
|
+
'debug' => env('APP_DEBUG', false),
|
|
1054
|
+
];
|
|
1055
|
+
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
---
|
|
1059
|
+
|
|
1060
|
+
## config/session.php
|
|
1061
|
+
|
|
1062
|
+
```php
|
|
1063
|
+
<?php
|
|
1064
|
+
|
|
1065
|
+
return [
|
|
1066
|
+
'driver' => env('SESSION_DRIVER', 'file'),
|
|
1067
|
+
'lifetime' => env('SESSION_LIFETIME', 120),
|
|
1068
|
+
'expire_on_close' => false,
|
|
1069
|
+
'encrypt' => false,
|
|
1070
|
+
'files' => storage_path('framework/sessions'),
|
|
1071
|
+
'connection' => null,
|
|
1072
|
+
'table' => 'sessions',
|
|
1073
|
+
'store' => null,
|
|
1074
|
+
'lottery' => [2, 100],
|
|
1075
|
+
'cookie' => env('SESSION_COOKIE', 'laravel_session'),
|
|
1076
|
+
'path' => '/',
|
|
1077
|
+
'domain' => env('SESSION_DOMAIN'),
|
|
1078
|
+
'secure' => env('SESSION_SECURE_COOKIE'),
|
|
1079
|
+
'http_only' => true,
|
|
1080
|
+
'same_site' => 'lax',
|
|
1081
|
+
];
|
|
1082
|
+
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
---
|
|
1086
|
+
|
|
1087
|
+
## database/migrations/2024_01_01_000000_create_users_table.php
|
|
1088
|
+
|
|
1089
|
+
```php
|
|
1090
|
+
<?php
|
|
1091
|
+
|
|
1092
|
+
use Illuminate\Database\Migrations\Migration;
|
|
1093
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
1094
|
+
use Illuminate\Support\Facades\Schema;
|
|
1095
|
+
|
|
1096
|
+
return new class extends Migration
|
|
1097
|
+
{
|
|
1098
|
+
public function up(): void
|
|
1099
|
+
{
|
|
1100
|
+
Schema::create('users', function (Blueprint $table) {
|
|
1101
|
+
$table->id();
|
|
1102
|
+
$table->string('email')->unique();
|
|
1103
|
+
$table->string('password');
|
|
1104
|
+
$table->boolean('is_staff')->default(false);
|
|
1105
|
+
$table->rememberToken();
|
|
1106
|
+
$table->timestamps();
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
public function down(): void
|
|
1111
|
+
{
|
|
1112
|
+
Schema::dropIfExists('users');
|
|
1113
|
+
}
|
|
1114
|
+
};
|
|
1115
|
+
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
---
|
|
1119
|
+
|
|
1120
|
+
## database/seeders/DatabaseSeeder.php
|
|
1121
|
+
|
|
1122
|
+
```php
|
|
1123
|
+
<?php
|
|
1124
|
+
|
|
1125
|
+
namespace Database\Seeders;
|
|
1126
|
+
|
|
1127
|
+
use App\Models\User;
|
|
1128
|
+
use Illuminate\Database\Seeder;
|
|
1129
|
+
|
|
1130
|
+
class DatabaseSeeder extends Seeder
|
|
1131
|
+
{
|
|
1132
|
+
public function run(): void
|
|
1133
|
+
{
|
|
1134
|
+
User::firstOrCreate(
|
|
1135
|
+
['email' => 'admin@example.com'],
|
|
1136
|
+
[
|
|
1137
|
+
'password' => bcrypt('admin'),
|
|
1138
|
+
'is_staff' => true,
|
|
1139
|
+
]
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
---
|
|
1147
|
+
|
|
1148
|
+
## IMPLEMENTATION.md
|
|
1149
|
+
|
|
1150
|
+
# Laravel PostHog Example - Implementation Summary
|
|
1151
|
+
|
|
1152
|
+
This document summarizes the implementation of the Laravel PostHog example application, ported from the Flask version.
|
|
1153
|
+
|
|
1154
|
+
## ✅ Completed Implementation
|
|
1155
|
+
|
|
1156
|
+
### Core Application Structure
|
|
1157
|
+
|
|
1158
|
+
**Models & Database**
|
|
1159
|
+
- ✅ User model with PostHog properties helper method
|
|
1160
|
+
- ✅ User migration with `is_staff` field
|
|
1161
|
+
- ✅ Database seeder for default admin user
|
|
1162
|
+
- ✅ SQLite database configuration
|
|
1163
|
+
|
|
1164
|
+
**PostHog Integration**
|
|
1165
|
+
- ✅ PostHog configuration file (`config/posthog.php`)
|
|
1166
|
+
- ✅ PostHogService class with all core methods:
|
|
1167
|
+
- `identify()` - User identification
|
|
1168
|
+
- `capture()` - Event tracking
|
|
1169
|
+
- `captureException()` - Error tracking
|
|
1170
|
+
- `isFeatureEnabled()` - Feature flag checking
|
|
1171
|
+
- `getFeatureFlagPayload()` - Feature flag payload retrieval
|
|
1172
|
+
|
|
1173
|
+
**Authentication (Livewire Components)**
|
|
1174
|
+
- ✅ Login component with PostHog tracking
|
|
1175
|
+
- ✅ Register component with PostHog tracking
|
|
1176
|
+
- ✅ Logout route with PostHog tracking
|
|
1177
|
+
|
|
1178
|
+
**Core Features (Livewire Components)**
|
|
1179
|
+
- ✅ Dashboard - Feature flag demonstration
|
|
1180
|
+
- ✅ Burrito Tracker - Custom event tracking
|
|
1181
|
+
- ✅ Profile - Error tracking demonstration
|
|
1182
|
+
|
|
1183
|
+
**API Controllers**
|
|
1184
|
+
- ✅ BurritoController - API endpoint for burrito tracking
|
|
1185
|
+
- ✅ ErrorTestController - Manual error capture demonstration
|
|
1186
|
+
|
|
1187
|
+
**Views & Layouts**
|
|
1188
|
+
- ✅ App layout (authenticated users)
|
|
1189
|
+
- ✅ Guest layout (unauthenticated users)
|
|
1190
|
+
- ✅ All Livewire view files with inline styling
|
|
1191
|
+
- ✅ Error pages (404, 500)
|
|
1192
|
+
|
|
1193
|
+
**Routes**
|
|
1194
|
+
- ✅ Web routes (authentication, dashboard, burrito, profile, logout)
|
|
1195
|
+
- ✅ API routes (burrito tracking, error testing)
|
|
1196
|
+
|
|
1197
|
+
**Configuration**
|
|
1198
|
+
- ✅ Environment example file
|
|
1199
|
+
- ✅ Composer.json with dependencies
|
|
1200
|
+
- ✅ Laravel config files (app, auth, database, session)
|
|
1201
|
+
- ✅ .gitignore
|
|
1202
|
+
|
|
1203
|
+
**Documentation**
|
|
1204
|
+
- ✅ Comprehensive README
|
|
1205
|
+
- ✅ Implementation plan (php-plan.md)
|
|
1206
|
+
|
|
1207
|
+
## 📋 Features Implemented
|
|
1208
|
+
|
|
1209
|
+
### 1. User Authentication
|
|
1210
|
+
- Login with PostHog identification
|
|
1211
|
+
- Registration with PostHog tracking
|
|
1212
|
+
- Logout with event capture
|
|
1213
|
+
- Session management
|
|
1214
|
+
|
|
1215
|
+
### 2. PostHog Analytics
|
|
1216
|
+
- User identification on login/signup
|
|
1217
|
+
- Person properties (email, is_staff, date_joined)
|
|
1218
|
+
- Custom event tracking (burrito considerations)
|
|
1219
|
+
- Dashboard views tracking
|
|
1220
|
+
|
|
1221
|
+
### 3. Feature Flags
|
|
1222
|
+
- Feature flag checking (`new-dashboard-feature`)
|
|
1223
|
+
- Feature flag payload retrieval
|
|
1224
|
+
- Conditional UI rendering based on flags
|
|
1225
|
+
|
|
1226
|
+
### 4. Error Tracking
|
|
1227
|
+
- Manual exception capture
|
|
1228
|
+
- Error ID generation
|
|
1229
|
+
- Test endpoint with optional capture (`?capture=true/false`)
|
|
1230
|
+
|
|
1231
|
+
### 5. UI/UX
|
|
1232
|
+
- Responsive layouts
|
|
1233
|
+
- Flash messages for user feedback
|
|
1234
|
+
- Livewire reactivity for burrito counter
|
|
1235
|
+
- Loading states on buttons
|
|
1236
|
+
|
|
1237
|
+
## 🎯 PostHog Integration Points
|
|
1238
|
+
|
|
1239
|
+
| Feature | Location | PostHog Method |
|
|
1240
|
+
|---------|----------|----------------|
|
|
1241
|
+
| User Login | `Login.php:23-27` | `identify()` + `capture()` |
|
|
1242
|
+
| User Signup | `Register.php:29-32` | `identify()` + `capture()` |
|
|
1243
|
+
| User Logout | `web.php:25` | `capture()` |
|
|
1244
|
+
| Dashboard View | `Dashboard.php:18` | `capture()` |
|
|
1245
|
+
| Feature Flag Check | `Dashboard.php:21-25` | `isFeatureEnabled()` |
|
|
1246
|
+
| Feature Flag Payload | `Dashboard.php:28-31` | `getFeatureFlagPayload()` |
|
|
1247
|
+
| Burrito Tracking | `BurritoTracker.php:22-24` | `identify()` + `capture()` |
|
|
1248
|
+
| Profile View | `Profile.php:14` | `capture()` |
|
|
1249
|
+
| Error Capture | `ErrorTestController.php:22-24` | `identify()` + `captureException()` |
|
|
1250
|
+
|
|
1251
|
+
## 📁 File Structure
|
|
1252
|
+
|
|
1253
|
+
```
|
|
1254
|
+
basics/laravel/
|
|
1255
|
+
├── app/
|
|
1256
|
+
│ ├── Http/
|
|
1257
|
+
│ │ ├── Controllers/
|
|
1258
|
+
│ │ │ ├── Controller.php
|
|
1259
|
+
│ │ │ └── Api/
|
|
1260
|
+
│ │ │ ├── BurritoController.php
|
|
1261
|
+
│ │ │ └── ErrorTestController.php
|
|
1262
|
+
│ │ └── Livewire/
|
|
1263
|
+
│ │ ├── Auth/
|
|
1264
|
+
│ │ │ ├── Login.php
|
|
1265
|
+
│ │ │ └── Register.php
|
|
1266
|
+
│ │ ├── Dashboard.php
|
|
1267
|
+
│ │ ├── BurritoTracker.php
|
|
1268
|
+
│ │ └── Profile.php
|
|
1269
|
+
│ ├── Models/
|
|
1270
|
+
│ │ └── User.php
|
|
1271
|
+
│ └── Services/
|
|
1272
|
+
│ └── PostHogService.php
|
|
1273
|
+
├── config/
|
|
1274
|
+
│ ├── app.php
|
|
1275
|
+
│ ├── auth.php
|
|
1276
|
+
│ ├── database.php
|
|
1277
|
+
│ ├── posthog.php
|
|
1278
|
+
│ └── session.php
|
|
1279
|
+
├── database/
|
|
1280
|
+
│ ├── migrations/
|
|
1281
|
+
│ │ └── 2024_01_01_000000_create_users_table.php
|
|
1282
|
+
│ └── seeders/
|
|
1283
|
+
│ └── DatabaseSeeder.php
|
|
1284
|
+
├── resources/
|
|
1285
|
+
│ └── views/
|
|
1286
|
+
│ ├── components/
|
|
1287
|
+
│ │ └── layouts/
|
|
1288
|
+
│ │ ├── app.blade.php
|
|
1289
|
+
│ │ └── guest.blade.php
|
|
1290
|
+
│ ├── livewire/
|
|
1291
|
+
│ │ ├── auth/
|
|
1292
|
+
│ │ │ ├── login.blade.php
|
|
1293
|
+
│ │ │ └── register.blade.php
|
|
1294
|
+
│ │ ├── dashboard.blade.php
|
|
1295
|
+
│ │ ├── burrito-tracker.blade.php
|
|
1296
|
+
│ │ └── profile.blade.php
|
|
1297
|
+
│ └── errors/
|
|
1298
|
+
│ ├── 404.blade.php
|
|
1299
|
+
│ └── 500.blade.php
|
|
1300
|
+
├── routes/
|
|
1301
|
+
│ ├── api.php
|
|
1302
|
+
│ └── web.php
|
|
1303
|
+
├── .env.example
|
|
1304
|
+
├── .gitignore
|
|
1305
|
+
├── composer.json
|
|
1306
|
+
├── IMPLEMENTATION.md
|
|
1307
|
+
└── README.md
|
|
1308
|
+
```
|
|
1309
|
+
|
|
1310
|
+
## 🔄 Flask to Laravel Mapping
|
|
1311
|
+
|
|
1312
|
+
| Flask Component | Laravel Equivalent |
|
|
1313
|
+
|----------------|-------------------|
|
|
1314
|
+
| Flask-Login | Laravel Auth + Livewire |
|
|
1315
|
+
| Flask-SQLAlchemy | Eloquent ORM |
|
|
1316
|
+
| Jinja2 Templates | Blade Templates + Livewire |
|
|
1317
|
+
| Blueprint routes | Route definitions |
|
|
1318
|
+
| @app.route decorators | Route::get/post |
|
|
1319
|
+
| session | session() helper |
|
|
1320
|
+
| flash() | session()->flash() |
|
|
1321
|
+
| @login_required | Route::middleware('auth') |
|
|
1322
|
+
| request.form | Livewire properties |
|
|
1323
|
+
| render_template() | view() or Livewire render() |
|
|
1324
|
+
| jsonify() | response()->json() |
|
|
1325
|
+
| SQLAlchemy models | Eloquent models |
|
|
1326
|
+
|
|
1327
|
+
## 🚀 Next Steps for Production
|
|
1328
|
+
|
|
1329
|
+
To make this a production-ready application:
|
|
1330
|
+
|
|
1331
|
+
1. **Install via Composer**: Run full Laravel installation
|
|
1332
|
+
2. **Environment**: Generate APP_KEY with `php artisan key:generate`
|
|
1333
|
+
3. **Database**: Run migrations with `php artisan migrate --seed`
|
|
1334
|
+
4. **Assets**: Set up Vite for asset compilation
|
|
1335
|
+
5. **Middleware**: Add CSRF protection middleware
|
|
1336
|
+
6. **Validation**: Add form request classes
|
|
1337
|
+
7. **Testing**: Implement PHPUnit tests
|
|
1338
|
+
8. **Caching**: Configure Redis/Memcached
|
|
1339
|
+
9. **Queue**: Set up queue workers for PostHog events
|
|
1340
|
+
10. **Deployment**: Configure for production server
|
|
1341
|
+
|
|
1342
|
+
## 📝 Notes
|
|
1343
|
+
|
|
1344
|
+
- This implementation uses inline CSS (matching Flask example) instead of Tailwind compilation
|
|
1345
|
+
- Livewire provides reactivity without separate JavaScript files
|
|
1346
|
+
- PostHog service is dependency-injected into components/controllers
|
|
1347
|
+
- Manual error capture pattern matches Flask implementation
|
|
1348
|
+
- Session-based burrito counter (same as Flask)
|
|
1349
|
+
- Default admin account: admin@example.com / admin
|
|
1350
|
+
|
|
1351
|
+
## 🎓 Learning Resources
|
|
1352
|
+
|
|
1353
|
+
- [Laravel Documentation](https://laravel.com/docs)
|
|
1354
|
+
- [Livewire Documentation](https://livewire.laravel.com)
|
|
1355
|
+
- [PostHog PHP SDK](https://github.com/PostHog/posthog-php)
|
|
1356
|
+
- [Eloquent ORM](https://laravel.com/docs/eloquent)
|
|
1357
|
+
|
|
1358
|
+
---
|
|
1359
|
+
|
|
1360
|
+
**Implementation Date**: January 2026
|
|
1361
|
+
**Laravel Version**: 11.x
|
|
1362
|
+
**Livewire Version**: 3.x
|
|
1363
|
+
**PostHog PHP SDK**: 3.x
|
|
1364
|
+
|
|
1365
|
+
---
|
|
1366
|
+
|
|
1367
|
+
## public/index.php
|
|
1368
|
+
|
|
1369
|
+
```php
|
|
1370
|
+
<?php
|
|
1371
|
+
|
|
1372
|
+
use Illuminate\Http\Request;
|
|
1373
|
+
|
|
1374
|
+
define('LARAVEL_START', microtime(true));
|
|
1375
|
+
|
|
1376
|
+
// Suppress PHP 8.5 deprecation warnings for development
|
|
1377
|
+
error_reporting(E_ALL & ~E_DEPRECATED);
|
|
1378
|
+
|
|
1379
|
+
// Determine if the application is in maintenance mode...
|
|
1380
|
+
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
|
|
1381
|
+
require $maintenance;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
// Register the Composer autoloader...
|
|
1385
|
+
require __DIR__.'/../vendor/autoload.php';
|
|
1386
|
+
|
|
1387
|
+
// Bootstrap Laravel and handle the request...
|
|
1388
|
+
(require_once __DIR__.'/../bootstrap/app.php')
|
|
1389
|
+
->handleRequest(Request::capture());
|
|
1390
|
+
|
|
1391
|
+
```
|
|
1392
|
+
|
|
1393
|
+
---
|
|
1394
|
+
|
|
1395
|
+
## resources/views/components/layouts/app.blade.php
|
|
1396
|
+
|
|
1397
|
+
```php
|
|
1398
|
+
<!DOCTYPE html>
|
|
1399
|
+
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
|
1400
|
+
<head>
|
|
1401
|
+
<meta charset="utf-8">
|
|
1402
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1403
|
+
<meta name="csrf-token" content="{{ csrf_token() }}">
|
|
1404
|
+
|
|
1405
|
+
<title>{{ $title ?? 'PostHog Laravel Example' }}</title>
|
|
1406
|
+
|
|
1407
|
+
<style>
|
|
1408
|
+
* {
|
|
1409
|
+
box-sizing: border-box;
|
|
1410
|
+
margin: 0;
|
|
1411
|
+
padding: 0;
|
|
1412
|
+
}
|
|
1413
|
+
body {
|
|
1414
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
1415
|
+
line-height: 1.6;
|
|
1416
|
+
background-color: #f5f5f5;
|
|
1417
|
+
color: #333;
|
|
1418
|
+
}
|
|
1419
|
+
.container {
|
|
1420
|
+
max-width: 800px;
|
|
1421
|
+
margin: 0 auto;
|
|
1422
|
+
padding: 20px;
|
|
1423
|
+
}
|
|
1424
|
+
nav {
|
|
1425
|
+
background: #1d4ed8;
|
|
1426
|
+
padding: 15px 20px;
|
|
1427
|
+
margin-bottom: 30px;
|
|
1428
|
+
}
|
|
1429
|
+
nav a {
|
|
1430
|
+
color: white;
|
|
1431
|
+
text-decoration: none;
|
|
1432
|
+
margin-right: 20px;
|
|
1433
|
+
}
|
|
1434
|
+
nav a:hover {
|
|
1435
|
+
text-decoration: underline;
|
|
1436
|
+
}
|
|
1437
|
+
.nav-right {
|
|
1438
|
+
float: right;
|
|
1439
|
+
}
|
|
1440
|
+
.card {
|
|
1441
|
+
background: white;
|
|
1442
|
+
border-radius: 8px;
|
|
1443
|
+
padding: 20px;
|
|
1444
|
+
margin-bottom: 20px;
|
|
1445
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
1446
|
+
}
|
|
1447
|
+
h1, h2, h3 {
|
|
1448
|
+
margin-bottom: 15px;
|
|
1449
|
+
color: #1d4ed8;
|
|
1450
|
+
}
|
|
1451
|
+
button, .btn {
|
|
1452
|
+
background: #1d4ed8;
|
|
1453
|
+
color: white;
|
|
1454
|
+
border: none;
|
|
1455
|
+
padding: 10px 20px;
|
|
1456
|
+
border-radius: 5px;
|
|
1457
|
+
cursor: pointer;
|
|
1458
|
+
font-size: 14px;
|
|
1459
|
+
display: inline-block;
|
|
1460
|
+
text-decoration: none;
|
|
1461
|
+
}
|
|
1462
|
+
button:hover, .btn:hover {
|
|
1463
|
+
background: #1e40af;
|
|
1464
|
+
}
|
|
1465
|
+
button:disabled {
|
|
1466
|
+
opacity: 0.5;
|
|
1467
|
+
cursor: not-allowed;
|
|
1468
|
+
}
|
|
1469
|
+
button.danger, .btn-danger {
|
|
1470
|
+
background: #dc2626;
|
|
1471
|
+
}
|
|
1472
|
+
button.danger:hover, .btn-danger:hover {
|
|
1473
|
+
background: #b91c1c;
|
|
1474
|
+
}
|
|
1475
|
+
input {
|
|
1476
|
+
width: 100%;
|
|
1477
|
+
padding: 10px;
|
|
1478
|
+
margin-bottom: 15px;
|
|
1479
|
+
border: 1px solid #ddd;
|
|
1480
|
+
border-radius: 5px;
|
|
1481
|
+
font-size: 14px;
|
|
1482
|
+
}
|
|
1483
|
+
.message-error {
|
|
1484
|
+
background: #fee2e2;
|
|
1485
|
+
color: #dc2626;
|
|
1486
|
+
padding: 10px 15px;
|
|
1487
|
+
border-radius: 5px;
|
|
1488
|
+
margin-bottom: 15px;
|
|
1489
|
+
}
|
|
1490
|
+
.message-success {
|
|
1491
|
+
background: #d1fae5;
|
|
1492
|
+
color: #059669;
|
|
1493
|
+
padding: 10px 15px;
|
|
1494
|
+
border-radius: 5px;
|
|
1495
|
+
margin-bottom: 15px;
|
|
1496
|
+
}
|
|
1497
|
+
.feature-flag {
|
|
1498
|
+
background: #fef3c7;
|
|
1499
|
+
border: 2px dashed #f59e0b;
|
|
1500
|
+
padding: 15px;
|
|
1501
|
+
border-radius: 8px;
|
|
1502
|
+
margin: 20px 0;
|
|
1503
|
+
}
|
|
1504
|
+
code {
|
|
1505
|
+
background: #f3f4f6;
|
|
1506
|
+
padding: 2px 6px;
|
|
1507
|
+
border-radius: 3px;
|
|
1508
|
+
font-family: monospace;
|
|
1509
|
+
}
|
|
1510
|
+
pre {
|
|
1511
|
+
background: #1e293b;
|
|
1512
|
+
color: #e2e8f0;
|
|
1513
|
+
padding: 16px;
|
|
1514
|
+
border-radius: 8px;
|
|
1515
|
+
overflow-x: auto;
|
|
1516
|
+
font-size: 13px;
|
|
1517
|
+
}
|
|
1518
|
+
.count {
|
|
1519
|
+
font-size: 48px;
|
|
1520
|
+
font-weight: bold;
|
|
1521
|
+
color: #1d4ed8;
|
|
1522
|
+
text-align: center;
|
|
1523
|
+
padding: 20px;
|
|
1524
|
+
}
|
|
1525
|
+
table {
|
|
1526
|
+
width: 100%;
|
|
1527
|
+
border-collapse: collapse;
|
|
1528
|
+
margin: 16px 0;
|
|
1529
|
+
}
|
|
1530
|
+
th, td {
|
|
1531
|
+
padding: 12px;
|
|
1532
|
+
text-align: left;
|
|
1533
|
+
border-bottom: 1px solid #eee;
|
|
1534
|
+
}
|
|
1535
|
+
th {
|
|
1536
|
+
background: #f8fafc;
|
|
1537
|
+
font-weight: 600;
|
|
1538
|
+
}
|
|
1539
|
+
label {
|
|
1540
|
+
display: block;
|
|
1541
|
+
margin-bottom: 5px;
|
|
1542
|
+
font-weight: 500;
|
|
1543
|
+
}
|
|
1544
|
+
.text-sm {
|
|
1545
|
+
font-size: 14px;
|
|
1546
|
+
}
|
|
1547
|
+
.text-gray {
|
|
1548
|
+
color: #666;
|
|
1549
|
+
}
|
|
1550
|
+
.mb-4 {
|
|
1551
|
+
margin-bottom: 16px;
|
|
1552
|
+
}
|
|
1553
|
+
</style>
|
|
1554
|
+
@livewireStyles
|
|
1555
|
+
</head>
|
|
1556
|
+
<body>
|
|
1557
|
+
@auth
|
|
1558
|
+
<nav>
|
|
1559
|
+
<a href="{{ route('dashboard') }}">Dashboard</a>
|
|
1560
|
+
<a href="{{ route('burrito') }}">Burrito</a>
|
|
1561
|
+
<a href="{{ route('profile') }}">Profile</a>
|
|
1562
|
+
<span class="nav-right">
|
|
1563
|
+
<span style="margin-right: 15px;">{{ auth()->user()->email }}</span>
|
|
1564
|
+
<form method="POST" action="{{ route('logout') }}" style="display: inline;">
|
|
1565
|
+
@csrf
|
|
1566
|
+
<button type="submit" style="background: none; padding: 0; color: white; text-decoration: underline;">Logout</button>
|
|
1567
|
+
</form>
|
|
1568
|
+
</span>
|
|
1569
|
+
</nav>
|
|
1570
|
+
@endauth
|
|
1571
|
+
|
|
1572
|
+
<div class="container">
|
|
1573
|
+
@if (session('success'))
|
|
1574
|
+
<div class="message-success">
|
|
1575
|
+
{{ session('success') }}
|
|
1576
|
+
</div>
|
|
1577
|
+
@endif
|
|
1578
|
+
|
|
1579
|
+
@if (session('error'))
|
|
1580
|
+
<div class="message-error">
|
|
1581
|
+
{{ session('error') }}
|
|
1582
|
+
</div>
|
|
1583
|
+
@endif
|
|
1584
|
+
|
|
1585
|
+
{{ $slot }}
|
|
1586
|
+
</div>
|
|
1587
|
+
|
|
1588
|
+
@livewireScripts
|
|
1589
|
+
</body>
|
|
1590
|
+
</html>
|
|
1591
|
+
|
|
1592
|
+
```
|
|
1593
|
+
|
|
1594
|
+
---
|
|
1595
|
+
|
|
1596
|
+
## resources/views/components/layouts/guest.blade.php
|
|
1597
|
+
|
|
1598
|
+
```php
|
|
1599
|
+
<!DOCTYPE html>
|
|
1600
|
+
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
|
1601
|
+
<head>
|
|
1602
|
+
<meta charset="utf-8">
|
|
1603
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1604
|
+
<meta name="csrf-token" content="{{ csrf_token() }}">
|
|
1605
|
+
|
|
1606
|
+
<title>{{ $title ?? 'PostHog Laravel Example' }}</title>
|
|
1607
|
+
|
|
1608
|
+
<style>
|
|
1609
|
+
* {
|
|
1610
|
+
box-sizing: border-box;
|
|
1611
|
+
margin: 0;
|
|
1612
|
+
padding: 0;
|
|
1613
|
+
}
|
|
1614
|
+
body {
|
|
1615
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
1616
|
+
line-height: 1.6;
|
|
1617
|
+
background-color: #f5f5f5;
|
|
1618
|
+
color: #333;
|
|
1619
|
+
}
|
|
1620
|
+
.container {
|
|
1621
|
+
max-width: 800px;
|
|
1622
|
+
margin: 0 auto;
|
|
1623
|
+
padding: 20px;
|
|
1624
|
+
}
|
|
1625
|
+
.card {
|
|
1626
|
+
background: white;
|
|
1627
|
+
border-radius: 8px;
|
|
1628
|
+
padding: 20px;
|
|
1629
|
+
margin-bottom: 20px;
|
|
1630
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
1631
|
+
}
|
|
1632
|
+
h1, h2, h3 {
|
|
1633
|
+
margin-bottom: 15px;
|
|
1634
|
+
color: #1d4ed8;
|
|
1635
|
+
}
|
|
1636
|
+
button, .btn {
|
|
1637
|
+
background: #1d4ed8;
|
|
1638
|
+
color: white;
|
|
1639
|
+
border: none;
|
|
1640
|
+
padding: 10px 20px;
|
|
1641
|
+
border-radius: 5px;
|
|
1642
|
+
cursor: pointer;
|
|
1643
|
+
font-size: 14px;
|
|
1644
|
+
display: inline-block;
|
|
1645
|
+
text-decoration: none;
|
|
1646
|
+
width: 100%;
|
|
1647
|
+
}
|
|
1648
|
+
button:hover, .btn:hover {
|
|
1649
|
+
background: #1e40af;
|
|
1650
|
+
}
|
|
1651
|
+
input {
|
|
1652
|
+
width: 100%;
|
|
1653
|
+
padding: 10px;
|
|
1654
|
+
margin-bottom: 15px;
|
|
1655
|
+
border: 1px solid #ddd;
|
|
1656
|
+
border-radius: 5px;
|
|
1657
|
+
font-size: 14px;
|
|
1658
|
+
}
|
|
1659
|
+
label {
|
|
1660
|
+
display: block;
|
|
1661
|
+
margin-bottom: 5px;
|
|
1662
|
+
font-weight: 500;
|
|
1663
|
+
}
|
|
1664
|
+
.error {
|
|
1665
|
+
color: #dc2626;
|
|
1666
|
+
font-size: 13px;
|
|
1667
|
+
margin-top: -10px;
|
|
1668
|
+
margin-bottom: 10px;
|
|
1669
|
+
}
|
|
1670
|
+
.text-sm {
|
|
1671
|
+
font-size: 14px;
|
|
1672
|
+
}
|
|
1673
|
+
.text-gray {
|
|
1674
|
+
color: #666;
|
|
1675
|
+
}
|
|
1676
|
+
a {
|
|
1677
|
+
color: #1d4ed8;
|
|
1678
|
+
}
|
|
1679
|
+
code {
|
|
1680
|
+
background: #f3f4f6;
|
|
1681
|
+
padding: 2px 6px;
|
|
1682
|
+
border-radius: 3px;
|
|
1683
|
+
font-family: monospace;
|
|
1684
|
+
font-size: 13px;
|
|
1685
|
+
}
|
|
1686
|
+
pre {
|
|
1687
|
+
background: #1e293b;
|
|
1688
|
+
color: #e2e8f0;
|
|
1689
|
+
padding: 16px;
|
|
1690
|
+
border-radius: 8px;
|
|
1691
|
+
overflow-x: auto;
|
|
1692
|
+
font-size: 13px;
|
|
1693
|
+
margin-top: 10px;
|
|
1694
|
+
}
|
|
1695
|
+
ul {
|
|
1696
|
+
margin-left: 20px;
|
|
1697
|
+
}
|
|
1698
|
+
</style>
|
|
1699
|
+
@livewireStyles
|
|
1700
|
+
</head>
|
|
1701
|
+
<body>
|
|
1702
|
+
<div class="container">
|
|
1703
|
+
{{ $slot }}
|
|
1704
|
+
</div>
|
|
1705
|
+
|
|
1706
|
+
@livewireScripts
|
|
1707
|
+
</body>
|
|
1708
|
+
</html>
|
|
1709
|
+
|
|
1710
|
+
```
|
|
1711
|
+
|
|
1712
|
+
---
|
|
1713
|
+
|
|
1714
|
+
## resources/views/errors/404.blade.php
|
|
1715
|
+
|
|
1716
|
+
```php
|
|
1717
|
+
<!DOCTYPE html>
|
|
1718
|
+
<html lang="en">
|
|
1719
|
+
<head>
|
|
1720
|
+
<meta charset="UTF-8">
|
|
1721
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1722
|
+
<title>Page Not Found - PostHog Laravel Example</title>
|
|
1723
|
+
<style>
|
|
1724
|
+
* {
|
|
1725
|
+
box-sizing: border-box;
|
|
1726
|
+
margin: 0;
|
|
1727
|
+
padding: 0;
|
|
1728
|
+
}
|
|
1729
|
+
body {
|
|
1730
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
1731
|
+
line-height: 1.6;
|
|
1732
|
+
background-color: #f5f5f5;
|
|
1733
|
+
color: #333;
|
|
1734
|
+
}
|
|
1735
|
+
.container {
|
|
1736
|
+
max-width: 800px;
|
|
1737
|
+
margin: 0 auto;
|
|
1738
|
+
padding: 20px;
|
|
1739
|
+
}
|
|
1740
|
+
.card {
|
|
1741
|
+
background: white;
|
|
1742
|
+
border-radius: 8px;
|
|
1743
|
+
padding: 40px;
|
|
1744
|
+
margin-top: 50px;
|
|
1745
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
1746
|
+
text-align: center;
|
|
1747
|
+
}
|
|
1748
|
+
h1 {
|
|
1749
|
+
font-size: 72px;
|
|
1750
|
+
color: #1d4ed8;
|
|
1751
|
+
margin-bottom: 15px;
|
|
1752
|
+
}
|
|
1753
|
+
h2 {
|
|
1754
|
+
font-size: 24px;
|
|
1755
|
+
color: #333;
|
|
1756
|
+
margin-bottom: 15px;
|
|
1757
|
+
}
|
|
1758
|
+
p {
|
|
1759
|
+
color: #666;
|
|
1760
|
+
margin-bottom: 25px;
|
|
1761
|
+
}
|
|
1762
|
+
.btn {
|
|
1763
|
+
background: #1d4ed8;
|
|
1764
|
+
color: white;
|
|
1765
|
+
border: none;
|
|
1766
|
+
padding: 12px 24px;
|
|
1767
|
+
border-radius: 5px;
|
|
1768
|
+
cursor: pointer;
|
|
1769
|
+
font-size: 14px;
|
|
1770
|
+
text-decoration: none;
|
|
1771
|
+
display: inline-block;
|
|
1772
|
+
}
|
|
1773
|
+
.btn:hover {
|
|
1774
|
+
background: #1e40af;
|
|
1775
|
+
}
|
|
1776
|
+
</style>
|
|
1777
|
+
</head>
|
|
1778
|
+
<body>
|
|
1779
|
+
<div class="container">
|
|
1780
|
+
<div class="card">
|
|
1781
|
+
<h1>404</h1>
|
|
1782
|
+
<h2>Page Not Found</h2>
|
|
1783
|
+
<p>The page you're looking for doesn't exist.</p>
|
|
1784
|
+
<a href="/" class="btn">Go Home</a>
|
|
1785
|
+
</div>
|
|
1786
|
+
</div>
|
|
1787
|
+
</body>
|
|
1788
|
+
</html>
|
|
1789
|
+
|
|
1790
|
+
```
|
|
1791
|
+
|
|
1792
|
+
---
|
|
1793
|
+
|
|
1794
|
+
## resources/views/errors/500.blade.php
|
|
1795
|
+
|
|
1796
|
+
```php
|
|
1797
|
+
<!DOCTYPE html>
|
|
1798
|
+
<html lang="en">
|
|
1799
|
+
<head>
|
|
1800
|
+
<meta charset="UTF-8">
|
|
1801
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1802
|
+
<title>Server Error - PostHog Laravel Example</title>
|
|
1803
|
+
<style>
|
|
1804
|
+
* {
|
|
1805
|
+
box-sizing: border-box;
|
|
1806
|
+
margin: 0;
|
|
1807
|
+
padding: 0;
|
|
1808
|
+
}
|
|
1809
|
+
body {
|
|
1810
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
1811
|
+
line-height: 1.6;
|
|
1812
|
+
background-color: #f5f5f5;
|
|
1813
|
+
color: #333;
|
|
1814
|
+
}
|
|
1815
|
+
.container {
|
|
1816
|
+
max-width: 800px;
|
|
1817
|
+
margin: 0 auto;
|
|
1818
|
+
padding: 20px;
|
|
1819
|
+
}
|
|
1820
|
+
.card {
|
|
1821
|
+
background: white;
|
|
1822
|
+
border-radius: 8px;
|
|
1823
|
+
padding: 40px;
|
|
1824
|
+
margin-top: 50px;
|
|
1825
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
1826
|
+
text-align: center;
|
|
1827
|
+
}
|
|
1828
|
+
h1 {
|
|
1829
|
+
font-size: 72px;
|
|
1830
|
+
color: #dc2626;
|
|
1831
|
+
margin-bottom: 15px;
|
|
1832
|
+
}
|
|
1833
|
+
h2 {
|
|
1834
|
+
font-size: 24px;
|
|
1835
|
+
color: #333;
|
|
1836
|
+
margin-bottom: 15px;
|
|
1837
|
+
}
|
|
1838
|
+
p {
|
|
1839
|
+
color: #666;
|
|
1840
|
+
margin-bottom: 25px;
|
|
1841
|
+
}
|
|
1842
|
+
.btn {
|
|
1843
|
+
background: #1d4ed8;
|
|
1844
|
+
color: white;
|
|
1845
|
+
border: none;
|
|
1846
|
+
padding: 12px 24px;
|
|
1847
|
+
border-radius: 5px;
|
|
1848
|
+
cursor: pointer;
|
|
1849
|
+
font-size: 14px;
|
|
1850
|
+
text-decoration: none;
|
|
1851
|
+
display: inline-block;
|
|
1852
|
+
}
|
|
1853
|
+
.btn:hover {
|
|
1854
|
+
background: #1e40af;
|
|
1855
|
+
}
|
|
1856
|
+
</style>
|
|
1857
|
+
</head>
|
|
1858
|
+
<body>
|
|
1859
|
+
<div class="container">
|
|
1860
|
+
<div class="card">
|
|
1861
|
+
<h1>500</h1>
|
|
1862
|
+
<h2>Internal Server Error</h2>
|
|
1863
|
+
<p>Something went wrong on our end.</p>
|
|
1864
|
+
<a href="/" class="btn">Go Home</a>
|
|
1865
|
+
</div>
|
|
1866
|
+
</div>
|
|
1867
|
+
</body>
|
|
1868
|
+
</html>
|
|
1869
|
+
|
|
1870
|
+
```
|
|
1871
|
+
|
|
1872
|
+
---
|
|
1873
|
+
|
|
1874
|
+
## resources/views/livewire/auth/login.blade.php
|
|
1875
|
+
|
|
1876
|
+
```php
|
|
1877
|
+
<div>
|
|
1878
|
+
<div class="card">
|
|
1879
|
+
<h1>Welcome to PostHog Laravel Example</h1>
|
|
1880
|
+
<p class="text-gray mb-4">This example demonstrates how to integrate PostHog with a Laravel application.</p>
|
|
1881
|
+
|
|
1882
|
+
<form wire:submit="login">
|
|
1883
|
+
<label for="email">Email</label>
|
|
1884
|
+
<input
|
|
1885
|
+
type="email"
|
|
1886
|
+
id="email"
|
|
1887
|
+
wire:model="email"
|
|
1888
|
+
required
|
|
1889
|
+
>
|
|
1890
|
+
@error('email') <div class="error">{{ $message }}</div> @enderror
|
|
1891
|
+
|
|
1892
|
+
<label for="password">Password</label>
|
|
1893
|
+
<input
|
|
1894
|
+
type="password"
|
|
1895
|
+
id="password"
|
|
1896
|
+
wire:model="password"
|
|
1897
|
+
required
|
|
1898
|
+
>
|
|
1899
|
+
@error('password') <div class="error">{{ $message }}</div> @enderror
|
|
1900
|
+
|
|
1901
|
+
<div style="margin-bottom: 15px;">
|
|
1902
|
+
<label style="display: inline; font-weight: normal;">
|
|
1903
|
+
<input type="checkbox" wire:model="remember" style="width: auto; margin-right: 5px;">
|
|
1904
|
+
Remember me
|
|
1905
|
+
</label>
|
|
1906
|
+
</div>
|
|
1907
|
+
|
|
1908
|
+
<button type="submit">Login</button>
|
|
1909
|
+
</form>
|
|
1910
|
+
|
|
1911
|
+
<p style="margin-top: 16px;" class="text-sm text-gray">
|
|
1912
|
+
Don't have an account? <a href="{{ route('register') }}">Sign up here</a>
|
|
1913
|
+
</p>
|
|
1914
|
+
<p class="text-sm text-gray">
|
|
1915
|
+
<strong>Tip:</strong> Default credentials are admin@example.com/admin
|
|
1916
|
+
</p>
|
|
1917
|
+
</div>
|
|
1918
|
+
|
|
1919
|
+
<div class="card">
|
|
1920
|
+
<h2>Features Demonstrated</h2>
|
|
1921
|
+
<ul class="text-gray">
|
|
1922
|
+
<li>User registration and identification</li>
|
|
1923
|
+
<li>Event tracking</li>
|
|
1924
|
+
<li>Feature flags</li>
|
|
1925
|
+
<li>Error tracking</li>
|
|
1926
|
+
</ul>
|
|
1927
|
+
</div>
|
|
1928
|
+
</div>
|
|
1929
|
+
|
|
1930
|
+
```
|
|
1931
|
+
|
|
1932
|
+
---
|
|
1933
|
+
|
|
1934
|
+
## resources/views/livewire/auth/register.blade.php
|
|
1935
|
+
|
|
1936
|
+
```php
|
|
1937
|
+
<div>
|
|
1938
|
+
<div class="card">
|
|
1939
|
+
<h1>Create an Account</h1>
|
|
1940
|
+
<p class="text-gray mb-4">Sign up to explore the PostHog Laravel integration example.</p>
|
|
1941
|
+
|
|
1942
|
+
<form wire:submit="register">
|
|
1943
|
+
<label for="email">Email *</label>
|
|
1944
|
+
<input
|
|
1945
|
+
type="email"
|
|
1946
|
+
id="email"
|
|
1947
|
+
wire:model="email"
|
|
1948
|
+
required
|
|
1949
|
+
>
|
|
1950
|
+
@error('email') <div class="error">{{ $message }}</div> @enderror
|
|
1951
|
+
|
|
1952
|
+
<label for="password">Password *</label>
|
|
1953
|
+
<input
|
|
1954
|
+
type="password"
|
|
1955
|
+
id="password"
|
|
1956
|
+
wire:model="password"
|
|
1957
|
+
required
|
|
1958
|
+
>
|
|
1959
|
+
@error('password') <div class="error">{{ $message }}</div> @enderror
|
|
1960
|
+
|
|
1961
|
+
<label for="password_confirmation">Confirm Password *</label>
|
|
1962
|
+
<input
|
|
1963
|
+
type="password"
|
|
1964
|
+
id="password_confirmation"
|
|
1965
|
+
wire:model="password_confirmation"
|
|
1966
|
+
required
|
|
1967
|
+
>
|
|
1968
|
+
|
|
1969
|
+
<button type="submit">Sign Up</button>
|
|
1970
|
+
</form>
|
|
1971
|
+
|
|
1972
|
+
<p style="margin-top: 16px;" class="text-sm text-gray">
|
|
1973
|
+
Already have an account? <a href="{{ route('login') }}">Login here</a>
|
|
1974
|
+
</p>
|
|
1975
|
+
</div>
|
|
1976
|
+
|
|
1977
|
+
<div class="card">
|
|
1978
|
+
<h2>PostHog Integration</h2>
|
|
1979
|
+
<p class="text-gray">When you sign up, the following PostHog events are captured:</p>
|
|
1980
|
+
<ul class="text-gray" style="margin-top: 10px;">
|
|
1981
|
+
<li><code>identify()</code> - Associates your email with the user</li>
|
|
1982
|
+
<li><code>capture()</code> - Sets person properties (email, etc.)</li>
|
|
1983
|
+
<li><code>user_signed_up</code> event - Tracks the signup action</li>
|
|
1984
|
+
</ul>
|
|
1985
|
+
|
|
1986
|
+
<h3 style="margin-top: 20px;">Code Example</h3>
|
|
1987
|
+
<pre>// After creating the user
|
|
1988
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
1989
|
+
$posthog->capture($user->email, 'user_signed_up', [
|
|
1990
|
+
'signup_method' => 'form'
|
|
1991
|
+
]);</pre>
|
|
1992
|
+
</div>
|
|
1993
|
+
</div>
|
|
1994
|
+
|
|
1995
|
+
```
|
|
1996
|
+
|
|
1997
|
+
---
|
|
1998
|
+
|
|
1999
|
+
## resources/views/livewire/burrito-tracker.blade.php
|
|
2000
|
+
|
|
2001
|
+
```php
|
|
2002
|
+
<div>
|
|
2003
|
+
<div class="card">
|
|
2004
|
+
<h1>Burrito Consideration Tracker</h1>
|
|
2005
|
+
<p class="text-gray mb-4">This page demonstrates custom event tracking with PostHog.</p>
|
|
2006
|
+
|
|
2007
|
+
<div class="count">{{ $burritoCount }}</div>
|
|
2008
|
+
<p style="text-align: center; color: #666; margin-bottom: 20px;">Times you've considered a burrito</p>
|
|
2009
|
+
|
|
2010
|
+
<div style="text-align: center;">
|
|
2011
|
+
<button
|
|
2012
|
+
wire:click="considerBurrito"
|
|
2013
|
+
wire:loading.attr="disabled"
|
|
2014
|
+
>
|
|
2015
|
+
<span wire:loading.remove>Consider a Burrito</span>
|
|
2016
|
+
<span wire:loading>Considering...</span>
|
|
2017
|
+
</button>
|
|
2018
|
+
</div>
|
|
2019
|
+
</div>
|
|
2020
|
+
|
|
2021
|
+
<div class="card">
|
|
2022
|
+
<h3>Code Example</h3>
|
|
2023
|
+
<pre>// Livewire component method
|
|
2024
|
+
public function considerBurrito(PostHogService $posthog)
|
|
2025
|
+
{
|
|
2026
|
+
$this->burritoCount++;
|
|
2027
|
+
session(['burrito_count' => $this->burritoCount]);
|
|
2028
|
+
|
|
2029
|
+
$user = Auth::user();
|
|
2030
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
2031
|
+
$posthog->capture($user->email, 'burrito_considered', [
|
|
2032
|
+
'total_considerations' => $this->burritoCount,
|
|
2033
|
+
]);
|
|
2034
|
+
}</pre>
|
|
2035
|
+
</div>
|
|
2036
|
+
</div>
|
|
2037
|
+
|
|
2038
|
+
```
|
|
2039
|
+
|
|
2040
|
+
---
|
|
2041
|
+
|
|
2042
|
+
## resources/views/livewire/dashboard.blade.php
|
|
2043
|
+
|
|
2044
|
+
```php
|
|
2045
|
+
<div>
|
|
2046
|
+
<div class="card">
|
|
2047
|
+
<h1>Dashboard</h1>
|
|
2048
|
+
<p class="text-gray">Welcome back, {{ auth()->user()->email }}!</p>
|
|
2049
|
+
</div>
|
|
2050
|
+
|
|
2051
|
+
<div class="card">
|
|
2052
|
+
<h2>Error Tracking Demo</h2>
|
|
2053
|
+
<p class="text-gray">Test manual exception capture in PostHog. These buttons trigger errors in the context of your logged-in user.</p>
|
|
2054
|
+
|
|
2055
|
+
@if($successMessage)
|
|
2056
|
+
<div style="background: #d4edda; border: 1px solid #c3e6cb; color: #155724; padding: 12px; border-radius: 4px; margin: 15px 0;">
|
|
2057
|
+
{{ $successMessage }}
|
|
2058
|
+
</div>
|
|
2059
|
+
@endif
|
|
2060
|
+
|
|
2061
|
+
@if($errorMessage)
|
|
2062
|
+
<div style="background: #f8d7da; border: 1px solid #f5c6cb; color: #721c24; padding: 12px; border-radius: 4px; margin: 15px 0;">
|
|
2063
|
+
{{ $errorMessage }}
|
|
2064
|
+
</div>
|
|
2065
|
+
@endif
|
|
2066
|
+
|
|
2067
|
+
<div style="display: flex; gap: 10px; margin-top: 15px;">
|
|
2068
|
+
<button wire:click="testErrorWithCapture" class="btn" style="background: #dc3545; color: white;">
|
|
2069
|
+
Capture Error in PostHog
|
|
2070
|
+
</button>
|
|
2071
|
+
<button wire:click="testErrorWithoutCapture" class="btn" style="background: #c82333; color: white;">
|
|
2072
|
+
Skip Capture in PostHog
|
|
2073
|
+
</button>
|
|
2074
|
+
</div>
|
|
2075
|
+
|
|
2076
|
+
<h3 style="margin-top: 20px;">Code Example</h3>
|
|
2077
|
+
<pre>try {
|
|
2078
|
+
// Critical operation that might fail
|
|
2079
|
+
processPayment();
|
|
2080
|
+
} catch (\Throwable $e) {
|
|
2081
|
+
// Manually capture this specific exception
|
|
2082
|
+
$errorId = $posthog->captureException($e, $user->email);
|
|
2083
|
+
|
|
2084
|
+
return response()->json([
|
|
2085
|
+
'error' => 'Operation failed',
|
|
2086
|
+
'error_id' => $errorId
|
|
2087
|
+
], 500);
|
|
2088
|
+
}</pre>
|
|
2089
|
+
<p class="text-gray" style="margin-top: 10px;">This demonstrates manual exception capture where you have control over whether errors are sent to PostHog.</p>
|
|
2090
|
+
</div>
|
|
2091
|
+
|
|
2092
|
+
<div class="card">
|
|
2093
|
+
<h2>Feature Flags</h2>
|
|
2094
|
+
|
|
2095
|
+
@if($showNewFeature)
|
|
2096
|
+
<div class="feature-flag">
|
|
2097
|
+
<strong>New Feature Enabled!</strong>
|
|
2098
|
+
<p style="margin-top: 10px;">You're seeing this because the <code>new-dashboard-feature</code> flag is enabled for you.</p>
|
|
2099
|
+
|
|
2100
|
+
@if($featureConfig)
|
|
2101
|
+
<p style="margin-top: 15px;"><strong>Feature Configuration:</strong></p>
|
|
2102
|
+
<pre>{{ json_encode($featureConfig, JSON_PRETTY_PRINT) }}</pre>
|
|
2103
|
+
@endif
|
|
2104
|
+
</div>
|
|
2105
|
+
@else
|
|
2106
|
+
<p class="text-gray">The <code>new-dashboard-feature</code> flag is not enabled for your account.</p>
|
|
2107
|
+
@endif
|
|
2108
|
+
|
|
2109
|
+
<h3 style="margin-top: 20px;">Code Example</h3>
|
|
2110
|
+
<pre>// Check if feature flag is enabled
|
|
2111
|
+
$showNewFeature = $posthog->isFeatureEnabled(
|
|
2112
|
+
'new-dashboard-feature',
|
|
2113
|
+
$user->email,
|
|
2114
|
+
$user->getPostHogProperties()
|
|
2115
|
+
);
|
|
2116
|
+
|
|
2117
|
+
// Get feature flag payload
|
|
2118
|
+
$featureConfig = $posthog->getFeatureFlagPayload(
|
|
2119
|
+
'new-dashboard-feature',
|
|
2120
|
+
$user->email
|
|
2121
|
+
);</pre>
|
|
2122
|
+
</div>
|
|
2123
|
+
|
|
2124
|
+
</div>
|
|
2125
|
+
|
|
2126
|
+
```
|
|
2127
|
+
|
|
2128
|
+
---
|
|
2129
|
+
|
|
2130
|
+
## resources/views/livewire/profile.blade.php
|
|
2131
|
+
|
|
2132
|
+
```php
|
|
2133
|
+
<div>
|
|
2134
|
+
<div class="card">
|
|
2135
|
+
<h1>Your Profile</h1>
|
|
2136
|
+
<p class="text-gray mb-4">This page demonstrates error tracking with PostHog.</p>
|
|
2137
|
+
|
|
2138
|
+
<table>
|
|
2139
|
+
<tr>
|
|
2140
|
+
<th>Email</th>
|
|
2141
|
+
<td>{{ auth()->user()->email }}</td>
|
|
2142
|
+
</tr>
|
|
2143
|
+
<tr>
|
|
2144
|
+
<th>Date Joined</th>
|
|
2145
|
+
<td>{{ auth()->user()->created_at->format('Y-m-d H:i') }}</td>
|
|
2146
|
+
</tr>
|
|
2147
|
+
<tr>
|
|
2148
|
+
<th>Staff Status</th>
|
|
2149
|
+
<td>{{ auth()->user()->is_staff ? 'Yes' : 'No' }}</td>
|
|
2150
|
+
</tr>
|
|
2151
|
+
</table>
|
|
2152
|
+
</div>
|
|
2153
|
+
|
|
2154
|
+
<div class="card">
|
|
2155
|
+
<h2>Error Tracking Demo</h2>
|
|
2156
|
+
<p class="text-gray">Test manual exception capture in PostHog. These buttons trigger errors in the context of your logged-in user.</p>
|
|
2157
|
+
|
|
2158
|
+
@if($successMessage)
|
|
2159
|
+
<div style="background: #d4edda; border: 1px solid #c3e6cb; color: #155724; padding: 12px; border-radius: 4px; margin: 15px 0;">
|
|
2160
|
+
{{ $successMessage }}
|
|
2161
|
+
</div>
|
|
2162
|
+
@endif
|
|
2163
|
+
|
|
2164
|
+
@if($errorMessage)
|
|
2165
|
+
<div style="background: #f8d7da; border: 1px solid #f5c6cb; color: #721c24; padding: 12px; border-radius: 4px; margin: 15px 0;">
|
|
2166
|
+
{{ $errorMessage }}
|
|
2167
|
+
</div>
|
|
2168
|
+
@endif
|
|
2169
|
+
|
|
2170
|
+
<div style="display: flex; gap: 10px; margin-top: 15px;">
|
|
2171
|
+
<button wire:click="testErrorWithCapture" class="btn" style="background: #dc3545; color: white;">
|
|
2172
|
+
Capture Error in PostHog
|
|
2173
|
+
</button>
|
|
2174
|
+
<button wire:click="testErrorWithoutCapture" class="btn" style="background: #c82333; color: white;">
|
|
2175
|
+
Skip Capture in PostHog
|
|
2176
|
+
</button>
|
|
2177
|
+
</div>
|
|
2178
|
+
|
|
2179
|
+
<p class="text-gray" style="margin-top: 15px;">
|
|
2180
|
+
This demonstrates manual exception capture where you have control over whether errors are sent to PostHog.
|
|
2181
|
+
</p>
|
|
2182
|
+
</div>
|
|
2183
|
+
|
|
2184
|
+
<div class="card">
|
|
2185
|
+
<h3>Code Example</h3>
|
|
2186
|
+
<pre>try {
|
|
2187
|
+
throw new \Exception('Test exception from critical operation');
|
|
2188
|
+
} catch (\Throwable $e) {
|
|
2189
|
+
// Capture exception with user context
|
|
2190
|
+
$posthog->identify($user->email, $user->getPostHogProperties());
|
|
2191
|
+
$eventId = $posthog->captureException($e, $user->email);
|
|
2192
|
+
|
|
2193
|
+
return response()->json([
|
|
2194
|
+
'error' => 'Operation failed',
|
|
2195
|
+
'error_id' => $eventId,
|
|
2196
|
+
'message' => "Error captured in PostHog. Reference ID: {$eventId}"
|
|
2197
|
+
], 500);
|
|
2198
|
+
}</pre>
|
|
2199
|
+
</div>
|
|
2200
|
+
</div>
|
|
2201
|
+
|
|
2202
|
+
```
|
|
2203
|
+
|
|
2204
|
+
---
|
|
2205
|
+
|
|
2206
|
+
## routes/api.php
|
|
2207
|
+
|
|
2208
|
+
```php
|
|
2209
|
+
<?php
|
|
2210
|
+
|
|
2211
|
+
use App\Http\Controllers\Api\BurritoController;
|
|
2212
|
+
use App\Http\Controllers\Api\ErrorTestController;
|
|
2213
|
+
use Illuminate\Support\Facades\Route;
|
|
2214
|
+
|
|
2215
|
+
Route::middleware('auth:sanctum')->group(function () {
|
|
2216
|
+
Route::post('/burrito/consider', [BurritoController::class, 'consider']);
|
|
2217
|
+
Route::post('/test-error', [ErrorTestController::class, 'test']);
|
|
2218
|
+
});
|
|
2219
|
+
|
|
2220
|
+
```
|
|
2221
|
+
|
|
2222
|
+
---
|
|
2223
|
+
|
|
2224
|
+
## routes/web.php
|
|
2225
|
+
|
|
2226
|
+
```php
|
|
2227
|
+
<?php
|
|
2228
|
+
|
|
2229
|
+
use App\Http\Livewire\Auth\Login;
|
|
2230
|
+
use App\Http\Livewire\Auth\Register;
|
|
2231
|
+
use App\Http\Livewire\BurritoTracker;
|
|
2232
|
+
use App\Http\Livewire\Dashboard;
|
|
2233
|
+
use App\Http\Livewire\Profile;
|
|
2234
|
+
use App\Services\PostHogService;
|
|
2235
|
+
use Illuminate\Support\Facades\Auth;
|
|
2236
|
+
use Illuminate\Support\Facades\Route;
|
|
2237
|
+
|
|
2238
|
+
// Guest routes
|
|
2239
|
+
Route::middleware('guest')->group(function () {
|
|
2240
|
+
Route::get('/', Login::class)->name('login');
|
|
2241
|
+
Route::get('/register', Register::class)->name('register');
|
|
2242
|
+
});
|
|
2243
|
+
|
|
2244
|
+
// Authenticated routes
|
|
2245
|
+
Route::middleware('auth')->group(function () {
|
|
2246
|
+
Route::get('/dashboard', Dashboard::class)->name('dashboard');
|
|
2247
|
+
Route::get('/burrito', BurritoTracker::class)->name('burrito');
|
|
2248
|
+
Route::get('/profile', Profile::class)->name('profile');
|
|
2249
|
+
|
|
2250
|
+
Route::post('/logout', function (PostHogService $posthog) {
|
|
2251
|
+
$user = Auth::user();
|
|
2252
|
+
|
|
2253
|
+
// PostHog: Track logout
|
|
2254
|
+
$posthog->capture($user->email, 'user_logged_out');
|
|
2255
|
+
|
|
2256
|
+
Auth::logout();
|
|
2257
|
+
request()->session()->invalidate();
|
|
2258
|
+
request()->session()->regenerateToken();
|
|
2259
|
+
|
|
2260
|
+
return redirect('/');
|
|
2261
|
+
})->name('logout');
|
|
2262
|
+
});
|
|
2263
|
+
|
|
2264
|
+
```
|
|
2265
|
+
|
|
2266
|
+
---
|
|
2267
|
+
|