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.
Files changed (665) hide show
  1. package/dist/bin.js +840 -296
  2. package/dist/global-skills/add-ai/SKILL.md +53 -0
  3. package/dist/global-skills/add-analytics/SKILL.md +65 -0
  4. package/dist/global-skills/add-app-clip/SKILL.md +280 -0
  5. package/dist/global-skills/add-app-clip/agents/openai.yaml +4 -0
  6. package/dist/global-skills/add-app-clip/references/native-module.md +96 -0
  7. package/dist/global-skills/add-blog/SKILL.md +49 -0
  8. package/dist/global-skills/add-crud/SKILL.md +28 -0
  9. package/dist/global-skills/add-files/SKILL.md +65 -0
  10. package/dist/global-skills/add-images/SKILL.md +64 -0
  11. package/dist/global-skills/add-language/SKILL.md +44 -0
  12. package/dist/global-skills/add-notifications/SKILL.md +61 -0
  13. package/dist/global-skills/add-realtime/SKILL.md +49 -0
  14. package/dist/global-skills/add-route/SKILL.md +28 -0
  15. package/dist/global-skills/add-search/SKILL.md +43 -0
  16. package/dist/global-skills/add-signin/SKILL.md +78 -0
  17. package/dist/global-skills/add-teams/SKILL.md +64 -0
  18. package/dist/global-skills/add-upload/SKILL.md +27 -0
  19. package/dist/global-skills/aws-cdk/SKILL.md +72 -0
  20. package/dist/global-skills/aws-cdk/references/bootstrap-and-project-setup.md +257 -0
  21. package/dist/global-skills/aws-cdk/references/compliance-and-drift.md +193 -0
  22. package/dist/global-skills/aws-cdk/references/construct-patterns.md +315 -0
  23. package/dist/global-skills/aws-cdk/references/import-and-migrate.md +184 -0
  24. package/dist/global-skills/aws-cdk/references/refactor-and-prevent-replacement.md +198 -0
  25. package/dist/global-skills/aws-cdk/references/troubleshooting-credentials.md +183 -0
  26. package/dist/global-skills/aws-cdk/references/troubleshooting-deployment.md +293 -0
  27. package/dist/global-skills/aws-cdk/references/troubleshooting-synth.md +274 -0
  28. package/dist/global-skills/aws-cdk/references/v1-to-v2-migration.md +119 -0
  29. package/dist/global-skills/aws-cloudformation/SKILL.md +88 -0
  30. package/dist/global-skills/aws-cloudformation/references/author-cloudformation-best-practices.script.md +179 -0
  31. package/dist/global-skills/aws-cloudformation/references/check-cloudformation-template-compliance.script.md +159 -0
  32. package/dist/global-skills/aws-cloudformation/references/cloudformation-pre-deploy-validation.script.md +217 -0
  33. package/dist/global-skills/aws-cloudformation/references/deploy-with-express-mode.script.md +271 -0
  34. package/dist/global-skills/aws-cloudformation/references/lookup-resource-properties.script.md +130 -0
  35. package/dist/global-skills/aws-cloudformation/references/troubleshoot-deployment.script.md +200 -0
  36. package/dist/global-skills/aws-cloudformation/references/validate-cloudformation-template.script.md +135 -0
  37. package/dist/global-skills/aws-serverless/SKILL.md +51 -0
  38. package/dist/global-skills/aws-serverless/assets/powertools-handler.py +49 -0
  39. package/dist/global-skills/aws-serverless/references/api-gateway.md +553 -0
  40. package/dist/global-skills/aws-serverless/references/architecture.md +262 -0
  41. package/dist/global-skills/aws-serverless/references/concurrency.md +200 -0
  42. package/dist/global-skills/aws-serverless/references/deployment.md +94 -0
  43. package/dist/global-skills/aws-serverless/references/event-sources.md +484 -0
  44. package/dist/global-skills/aws-serverless/references/lambda.md +548 -0
  45. package/dist/global-skills/aws-serverless/references/orchestration.md +449 -0
  46. package/dist/global-skills/aws-serverless/references/production.md +493 -0
  47. package/dist/global-skills/aws-serverless/references/troubleshooting.md +711 -0
  48. package/dist/global-skills/back-up-my-code/SKILL.md +48 -0
  49. package/dist/global-skills/better-auth-best-practices/SKILL.md +182 -0
  50. package/dist/global-skills/better-auth-security-best-practices/SKILL.md +432 -0
  51. package/dist/global-skills/building-native-ui/SKILL.md +377 -0
  52. package/dist/global-skills/building-native-ui/agents/openai.yaml +4 -0
  53. package/dist/global-skills/building-native-ui/references/animations.md +220 -0
  54. package/dist/global-skills/building-native-ui/references/controls.md +270 -0
  55. package/dist/global-skills/building-native-ui/references/form-sheet.md +253 -0
  56. package/dist/global-skills/building-native-ui/references/gradients.md +106 -0
  57. package/dist/global-skills/building-native-ui/references/icons.md +213 -0
  58. package/dist/global-skills/building-native-ui/references/media.md +198 -0
  59. package/dist/global-skills/building-native-ui/references/route-structure.md +229 -0
  60. package/dist/global-skills/building-native-ui/references/search.md +248 -0
  61. package/dist/global-skills/building-native-ui/references/storage.md +121 -0
  62. package/dist/global-skills/building-native-ui/references/tabs.md +433 -0
  63. package/dist/global-skills/building-native-ui/references/toolbar-and-headers.md +284 -0
  64. package/dist/global-skills/building-native-ui/references/visual-effects.md +197 -0
  65. package/dist/global-skills/building-native-ui/references/webgpu-three.md +605 -0
  66. package/dist/global-skills/building-native-ui/references/zoom-transitions.md +158 -0
  67. package/dist/global-skills/buy-domain/SKILL.md +64 -0
  68. package/dist/global-skills/check-safety/SKILL.md +94 -0
  69. package/dist/global-skills/claimable-postgres/SKILL.md +249 -0
  70. package/dist/global-skills/configure-capabilities/SKILL.md +38 -0
  71. package/dist/global-skills/connect-account/SKILL.md +64 -0
  72. package/dist/global-skills/connect-account-backend/SKILL.md +41 -0
  73. package/dist/global-skills/create-auth-skill/SKILL.md +321 -0
  74. package/dist/global-skills/design-my-data/SKILL.md +48 -0
  75. package/dist/global-skills/doctor/SKILL.md +84 -0
  76. package/dist/global-skills/eas-app-stores/SKILL.md +152 -0
  77. package/dist/global-skills/eas-app-stores/agents/openai.yaml +4 -0
  78. package/dist/global-skills/eas-app-stores/references/app-store-metadata.md +497 -0
  79. package/dist/global-skills/eas-app-stores/references/ios-app-store.md +371 -0
  80. package/dist/global-skills/eas-app-stores/references/play-store.md +246 -0
  81. package/dist/global-skills/eas-app-stores/references/testflight.md +58 -0
  82. package/dist/global-skills/eas-app-stores/references/workflows.md +120 -0
  83. package/dist/global-skills/eas-hosting/SKILL.md +423 -0
  84. package/dist/global-skills/eas-hosting/agents/openai.yaml +4 -0
  85. package/dist/global-skills/eas-observe/SKILL.md +32 -0
  86. package/dist/global-skills/eas-observe/agents/openai.yaml +4 -0
  87. package/dist/global-skills/eas-observe/references/metrics.md +47 -0
  88. package/dist/global-skills/eas-observe/references/queries.md +342 -0
  89. package/dist/global-skills/eas-observe/references/setup.md +317 -0
  90. package/dist/global-skills/eas-simulator/SKILL.md +156 -0
  91. package/dist/global-skills/eas-simulator/agents/openai.yaml +4 -0
  92. package/dist/global-skills/eas-simulator/references/controllers.md +67 -0
  93. package/dist/global-skills/eas-simulator/references/run-your-app.md +185 -0
  94. package/dist/global-skills/eas-simulator/references/troubleshooting.md +38 -0
  95. package/dist/global-skills/eas-update-insights/SKILL.md +230 -0
  96. package/dist/global-skills/eas-update-insights/agents/openai.yaml +4 -0
  97. package/dist/global-skills/eas-update-insights/references/channel-insights-schema.md +47 -0
  98. package/dist/global-skills/eas-update-insights/references/update-insights-schema.md +69 -0
  99. package/dist/global-skills/eas-workflows/SKILL.md +94 -0
  100. package/dist/global-skills/eas-workflows/agents/openai.yaml +4 -0
  101. package/dist/global-skills/eas-workflows/scripts/fetch.js +109 -0
  102. package/dist/global-skills/eas-workflows/scripts/package.json +11 -0
  103. package/dist/global-skills/eas-workflows/scripts/validate.js +84 -0
  104. package/dist/global-skills/email-best-practices/SKILL.md +73 -0
  105. package/dist/global-skills/expo-api-routes/SKILL.md +368 -0
  106. package/dist/global-skills/expo-api-routes/agents/openai.yaml +4 -0
  107. package/dist/global-skills/expo-app-clip/SKILL.md +282 -0
  108. package/dist/global-skills/expo-app-clip/agents/openai.yaml +4 -0
  109. package/dist/global-skills/expo-app-clip/references/native-module.md +96 -0
  110. package/dist/global-skills/expo-brownfield/SKILL.md +54 -0
  111. package/dist/global-skills/expo-brownfield/agents/openai.yaml +4 -0
  112. package/dist/global-skills/expo-brownfield/references/brownfield-integrated.md +526 -0
  113. package/dist/global-skills/expo-brownfield/references/brownfield-isolated.md +402 -0
  114. package/dist/global-skills/expo-brownfield/references/comparison.md +63 -0
  115. package/dist/global-skills/expo-brownfield/references/troubleshooting.md +88 -0
  116. package/dist/global-skills/expo-cicd-workflows/SKILL.md +92 -0
  117. package/dist/global-skills/expo-cicd-workflows/agents/openai.yaml +4 -0
  118. package/dist/global-skills/expo-cicd-workflows/scripts/fetch.js +109 -0
  119. package/dist/global-skills/expo-cicd-workflows/scripts/package.json +11 -0
  120. package/dist/global-skills/expo-cicd-workflows/scripts/validate.js +84 -0
  121. package/dist/global-skills/expo-data-fetching/SKILL.md +449 -0
  122. package/dist/global-skills/expo-data-fetching/agents/openai.yaml +4 -0
  123. package/dist/global-skills/expo-data-fetching/references/expo-router-loaders.md +341 -0
  124. package/dist/global-skills/expo-data-fetching/references/offline-and-cancellation.md +68 -0
  125. package/dist/global-skills/expo-deployment/SKILL.md +167 -0
  126. package/dist/global-skills/expo-deployment/agents/openai.yaml +4 -0
  127. package/dist/global-skills/expo-deployment/references/app-store-metadata.md +497 -0
  128. package/dist/global-skills/expo-deployment/references/ios-app-store.md +371 -0
  129. package/dist/global-skills/expo-deployment/references/play-store.md +246 -0
  130. package/dist/global-skills/expo-deployment/references/testflight.md +58 -0
  131. package/dist/global-skills/expo-deployment/references/workflows.md +160 -0
  132. package/dist/global-skills/expo-dev-client/SKILL.md +174 -0
  133. package/dist/global-skills/expo-dev-client/agents/openai.yaml +4 -0
  134. package/dist/global-skills/expo-dom/SKILL.md +417 -0
  135. package/dist/global-skills/expo-dom/agents/openai.yaml +4 -0
  136. package/dist/global-skills/expo-examples/SKILL.md +99 -0
  137. package/dist/global-skills/expo-examples/agents/openai.yaml +4 -0
  138. package/dist/global-skills/expo-examples/references/catalog.md +105 -0
  139. package/dist/global-skills/expo-module/SKILL.md +141 -0
  140. package/dist/global-skills/expo-module/agents/openai.yaml +4 -0
  141. package/dist/global-skills/expo-module/references/config-plugin.md +90 -0
  142. package/dist/global-skills/expo-module/references/create-expo-module.md +206 -0
  143. package/dist/global-skills/expo-module/references/lifecycle.md +127 -0
  144. package/dist/global-skills/expo-module/references/module-config.md +48 -0
  145. package/dist/global-skills/expo-module/references/native-module.md +286 -0
  146. package/dist/global-skills/expo-module/references/native-view.md +171 -0
  147. package/dist/global-skills/expo-native-ui/SKILL.md +181 -0
  148. package/dist/global-skills/expo-native-ui/agents/openai.yaml +4 -0
  149. package/dist/global-skills/expo-native-ui/references/animations.md +220 -0
  150. package/dist/global-skills/expo-native-ui/references/controls.md +270 -0
  151. package/dist/global-skills/expo-native-ui/references/gradients.md +106 -0
  152. package/dist/global-skills/expo-native-ui/references/icons.md +213 -0
  153. package/dist/global-skills/expo-native-ui/references/media.md +198 -0
  154. package/dist/global-skills/expo-native-ui/references/storage.md +121 -0
  155. package/dist/global-skills/expo-native-ui/references/visual-effects.md +197 -0
  156. package/dist/global-skills/expo-native-ui/references/webgpu-three.md +605 -0
  157. package/dist/global-skills/expo-observe/SKILL.md +30 -0
  158. package/dist/global-skills/expo-observe/references/metrics.md +47 -0
  159. package/dist/global-skills/expo-observe/references/queries.md +342 -0
  160. package/dist/global-skills/expo-observe/references/setup.md +317 -0
  161. package/dist/global-skills/expo-router/SKILL.md +230 -0
  162. package/dist/global-skills/expo-router/agents/openai.yaml +4 -0
  163. package/dist/global-skills/expo-router/references/form-sheet.md +253 -0
  164. package/dist/global-skills/expo-router/references/route-structure.md +229 -0
  165. package/dist/global-skills/expo-router/references/search.md +248 -0
  166. package/dist/global-skills/expo-router/references/tabs.md +433 -0
  167. package/dist/global-skills/expo-router/references/toolbar-and-headers.md +284 -0
  168. package/dist/global-skills/expo-router/references/zoom-transitions.md +158 -0
  169. package/dist/global-skills/expo-skill-eval/SKILL.md +314 -0
  170. package/dist/global-skills/expo-skill-eval/agents/visual-grader.md +52 -0
  171. package/dist/global-skills/expo-skill-eval/references/design-rubric.md +45 -0
  172. package/dist/global-skills/expo-skill-eval/references/runtime-matrix.md +34 -0
  173. package/dist/global-skills/expo-skill-eval/scripts/check-static.sh +64 -0
  174. package/dist/global-skills/expo-skill-eval/scripts/clean-fixture.sh +56 -0
  175. package/dist/global-skills/expo-skill-eval/scripts/generate_viewer.py +450 -0
  176. package/dist/global-skills/expo-skill-eval/scripts/latest-sdk.sh +46 -0
  177. package/dist/global-skills/expo-skill-eval/scripts/make-fixture.sh +95 -0
  178. package/dist/global-skills/expo-skill-eval/scripts/make-workspace.sh +31 -0
  179. package/dist/global-skills/expo-skill-eval/scripts/snapshot-android.sh +284 -0
  180. package/dist/global-skills/expo-skill-eval/scripts/snapshot-ios.sh +132 -0
  181. package/dist/global-skills/expo-skill-eval/scripts/snapshot-web.sh +61 -0
  182. package/dist/global-skills/expo-skill-feedback/SKILL.md +54 -0
  183. package/dist/global-skills/expo-skill-feedback/agents/openai.yaml +4 -0
  184. package/dist/global-skills/expo-skill-feedback/scripts/skill-event.cjs +180 -0
  185. package/dist/global-skills/expo-skill-feedback/scripts/skill-feedback.cjs +118 -0
  186. package/dist/global-skills/expo-skill-feedback/scripts/telemetry.cjs +65 -0
  187. package/dist/global-skills/expo-skill-feedback/scripts/telemetry_common.cjs +171 -0
  188. package/dist/global-skills/expo-tailwind-setup/SKILL.md +480 -0
  189. package/dist/global-skills/expo-tailwind-setup/agents/openai.yaml +4 -0
  190. package/dist/global-skills/expo-ui/SKILL.md +47 -0
  191. package/dist/global-skills/expo-ui/agents/openai.yaml +4 -0
  192. package/dist/global-skills/expo-ui/references/drop-in-replacements.md +27 -0
  193. package/dist/global-skills/expo-ui/references/jetpack-compose.md +73 -0
  194. package/dist/global-skills/expo-ui/references/swift-ui.md +73 -0
  195. package/dist/global-skills/expo-ui/references/universal.md +73 -0
  196. package/dist/global-skills/expo-ui/scripts/list-components.js +193 -0
  197. package/dist/global-skills/expo-upgrade/SKILL.md +134 -0
  198. package/dist/global-skills/expo-upgrade/agents/openai.yaml +4 -0
  199. package/dist/global-skills/expo-upgrade/references/expo-av-to-audio.md +132 -0
  200. package/dist/global-skills/expo-upgrade/references/expo-av-to-video.md +160 -0
  201. package/dist/global-skills/expo-upgrade/references/native-tabs.md +124 -0
  202. package/dist/global-skills/expo-upgrade/references/new-architecture.md +79 -0
  203. package/dist/global-skills/expo-upgrade/references/react-19.md +79 -0
  204. package/dist/global-skills/expo-upgrade/references/react-compiler.md +59 -0
  205. package/dist/global-skills/expo-upgrade/references/react-navigation-to-expo-router.md +61 -0
  206. package/dist/global-skills/expo-web-to-native/SKILL.md +83 -0
  207. package/dist/global-skills/expo-web-to-native/agents/openai.yaml +4 -0
  208. package/dist/global-skills/expo-web-to-native/references/false-friends.md +119 -0
  209. package/dist/global-skills/expo-web-to-native/references/native-patterns.md +39 -0
  210. package/dist/global-skills/expo-web-to-native/references/run-as-goal.md +48 -0
  211. package/dist/global-skills/expo-web-to-native/references/verify-on-device.md +45 -0
  212. package/dist/global-skills/firebase-ai-logic-basics/SKILL.md +165 -0
  213. package/dist/global-skills/firebase-ai-logic-basics/references/flutter_setup.md +95 -0
  214. package/dist/global-skills/firebase-ai-logic-basics/references/ios_setup.md +156 -0
  215. package/dist/global-skills/firebase-ai-logic-basics/references/usage_patterns_android.md +157 -0
  216. package/dist/global-skills/firebase-ai-logic-basics/references/usage_patterns_web.md +186 -0
  217. package/dist/global-skills/firebase-app-hosting-basics/SKILL.md +73 -0
  218. package/dist/global-skills/firebase-app-hosting-basics/references/cli_commands.md +85 -0
  219. package/dist/global-skills/firebase-app-hosting-basics/references/configuration.md +59 -0
  220. package/dist/global-skills/firebase-app-hosting-basics/references/emulation.md +59 -0
  221. package/dist/global-skills/firebase-auth-basics/SKILL.md +118 -0
  222. package/dist/global-skills/firebase-auth-basics/references/client_sdk_android.md +160 -0
  223. package/dist/global-skills/firebase-auth-basics/references/client_sdk_web.md +301 -0
  224. package/dist/global-skills/firebase-auth-basics/references/flutter_setup.md +149 -0
  225. package/dist/global-skills/firebase-auth-basics/references/ios_setup.md +87 -0
  226. package/dist/global-skills/firebase-auth-basics/references/security_rules.md +49 -0
  227. package/dist/global-skills/firebase-basics/SKILL.md +148 -0
  228. package/dist/global-skills/firebase-basics/references/android_setup.md +41 -0
  229. package/dist/global-skills/firebase-basics/references/firebase-cli-guide.md +18 -0
  230. package/dist/global-skills/firebase-basics/references/firebase-service-init.md +20 -0
  231. package/dist/global-skills/firebase-basics/references/flutter_setup.md +143 -0
  232. package/dist/global-skills/firebase-basics/references/ios_setup.md +113 -0
  233. package/dist/global-skills/firebase-basics/references/local-env-setup.md +80 -0
  234. package/dist/global-skills/firebase-basics/references/refresh/android_studio.md +41 -0
  235. package/dist/global-skills/firebase-basics/references/refresh/antigravity.md +64 -0
  236. package/dist/global-skills/firebase-basics/references/refresh/claude.md +12 -0
  237. package/dist/global-skills/firebase-basics/references/refresh/gemini-cli.md +13 -0
  238. package/dist/global-skills/firebase-basics/references/refresh/other-agents.md +67 -0
  239. package/dist/global-skills/firebase-basics/references/setup/android_studio.md +23 -0
  240. package/dist/global-skills/firebase-basics/references/setup/antigravity.md +98 -0
  241. package/dist/global-skills/firebase-basics/references/setup/claude_code.md +45 -0
  242. package/dist/global-skills/firebase-basics/references/setup/cursor.md +93 -0
  243. package/dist/global-skills/firebase-basics/references/setup/gemini_cli.md +53 -0
  244. package/dist/global-skills/firebase-basics/references/setup/github_copilot.md +104 -0
  245. package/dist/global-skills/firebase-basics/references/setup/other_agents.md +99 -0
  246. package/dist/global-skills/firebase-basics/references/web_setup.md +77 -0
  247. package/dist/global-skills/firebase-crashlytics/SKILL.md +42 -0
  248. package/dist/global-skills/firebase-crashlytics/references/android_setup.md +152 -0
  249. package/dist/global-skills/firebase-crashlytics/references/ios_setup.md +115 -0
  250. package/dist/global-skills/firebase-data-connect/SKILL.md +191 -0
  251. package/dist/global-skills/firebase-data-connect/examples.md +638 -0
  252. package/dist/global-skills/firebase-data-connect/reference/cloud_functions.md +184 -0
  253. package/dist/global-skills/firebase-data-connect/reference/config.md +271 -0
  254. package/dist/global-skills/firebase-data-connect/reference/data_seeding.md +185 -0
  255. package/dist/global-skills/firebase-data-connect/reference/native_sql.md +170 -0
  256. package/dist/global-skills/firebase-data-connect/reference/operations.md +385 -0
  257. package/dist/global-skills/firebase-data-connect/reference/realtime.md +210 -0
  258. package/dist/global-skills/firebase-data-connect/reference/schema.md +290 -0
  259. package/dist/global-skills/firebase-data-connect/reference/sdk_admin_node.md +141 -0
  260. package/dist/global-skills/firebase-data-connect/reference/sdk_android.md +126 -0
  261. package/dist/global-skills/firebase-data-connect/reference/sdk_flutter.md +134 -0
  262. package/dist/global-skills/firebase-data-connect/reference/sdk_ios.md +157 -0
  263. package/dist/global-skills/firebase-data-connect/reference/sdk_web.md +146 -0
  264. package/dist/global-skills/firebase-data-connect/reference/search.md +264 -0
  265. package/dist/global-skills/firebase-data-connect/reference/security.md +295 -0
  266. package/dist/global-skills/firebase-data-connect/templates.md +318 -0
  267. package/dist/global-skills/firebase-firestore/SKILL.md +89 -0
  268. package/dist/global-skills/firebase-firestore/references/enterprise/android_sdk_usage.md +230 -0
  269. package/dist/global-skills/firebase-firestore/references/enterprise/data_model.md +66 -0
  270. package/dist/global-skills/firebase-firestore/references/enterprise/flutter_setup.md +180 -0
  271. package/dist/global-skills/firebase-firestore/references/enterprise/indexes.md +135 -0
  272. package/dist/global-skills/firebase-firestore/references/enterprise/ios_setup.md +189 -0
  273. package/dist/global-skills/firebase-firestore/references/enterprise/provisioning.md +118 -0
  274. package/dist/global-skills/firebase-firestore/references/enterprise/python_sdk_usage.md +138 -0
  275. package/dist/global-skills/firebase-firestore/references/enterprise/security_rules.md +577 -0
  276. package/dist/global-skills/firebase-firestore/references/enterprise/web_sdk_usage.md +127 -0
  277. package/dist/global-skills/firebase-firestore/references/standard/android_sdk_usage.md +193 -0
  278. package/dist/global-skills/firebase-firestore/references/standard/flutter_setup.md +176 -0
  279. package/dist/global-skills/firebase-firestore/references/standard/indexes.md +113 -0
  280. package/dist/global-skills/firebase-firestore/references/standard/ios_setup.md +174 -0
  281. package/dist/global-skills/firebase-firestore/references/standard/provisioning.md +110 -0
  282. package/dist/global-skills/firebase-firestore/references/standard/security_rules.md +577 -0
  283. package/dist/global-skills/firebase-firestore/references/standard/web_sdk_usage.md +192 -0
  284. package/dist/global-skills/firebase-hosting-basics/SKILL.md +64 -0
  285. package/dist/global-skills/firebase-hosting-basics/references/configuration.md +115 -0
  286. package/dist/global-skills/firebase-hosting-basics/references/deploying.md +48 -0
  287. package/dist/global-skills/firebase-remote-config-basics/SKILL.md +124 -0
  288. package/dist/global-skills/firebase-remote-config-basics/references/android_setup.md +91 -0
  289. package/dist/global-skills/firebase-remote-config-basics/references/ios_setup.md +89 -0
  290. package/dist/global-skills/firebase-security-rules-auditor/SKILL.md +70 -0
  291. package/dist/global-skills/go-live/SKILL.md +90 -0
  292. package/dist/global-skills/harden/SKILL.md +101 -0
  293. package/dist/global-skills/instrument-feature-flags/SKILL.md +88 -0
  294. package/dist/global-skills/instrument-feature-flags/references/adding-feature-flag-code.md +3578 -0
  295. package/dist/global-skills/instrument-feature-flags/references/android.md +146 -0
  296. package/dist/global-skills/instrument-feature-flags/references/api.md +194 -0
  297. package/dist/global-skills/instrument-feature-flags/references/best-practices.md +231 -0
  298. package/dist/global-skills/instrument-feature-flags/references/django.md +263 -0
  299. package/dist/global-skills/instrument-feature-flags/references/dotnet.md +763 -0
  300. package/dist/global-skills/instrument-feature-flags/references/elixir.md +47 -0
  301. package/dist/global-skills/instrument-feature-flags/references/flask.md +131 -0
  302. package/dist/global-skills/instrument-feature-flags/references/flutter.md +212 -0
  303. package/dist/global-skills/instrument-feature-flags/references/go.md +208 -0
  304. package/dist/global-skills/instrument-feature-flags/references/ios.md +146 -0
  305. package/dist/global-skills/instrument-feature-flags/references/java.md +94 -0
  306. package/dist/global-skills/instrument-feature-flags/references/laravel.md +170 -0
  307. package/dist/global-skills/instrument-feature-flags/references/next-js.md +383 -0
  308. package/dist/global-skills/instrument-feature-flags/references/nodejs.md +216 -0
  309. package/dist/global-skills/instrument-feature-flags/references/php.md +187 -0
  310. package/dist/global-skills/instrument-feature-flags/references/python.md +191 -0
  311. package/dist/global-skills/instrument-feature-flags/references/react-native.md +166 -0
  312. package/dist/global-skills/instrument-feature-flags/references/react.md +302 -0
  313. package/dist/global-skills/instrument-feature-flags/references/ruby-on-rails.md +604 -0
  314. package/dist/global-skills/instrument-feature-flags/references/ruby.md +200 -0
  315. package/dist/global-skills/instrument-feature-flags/references/rust.md +222 -0
  316. package/dist/global-skills/instrument-feature-flags/references/usage.md +600 -0
  317. package/dist/global-skills/instrument-feature-flags/references/web.md +193 -0
  318. package/dist/global-skills/instrument-product-analytics/SKILL.md +139 -0
  319. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-android.md +1639 -0
  320. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-angular.md +944 -0
  321. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-hybrid.md +1001 -0
  322. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-ssr.md +1004 -0
  323. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-static.md +720 -0
  324. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-view-transitions.md +810 -0
  325. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-django.md +1167 -0
  326. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-expo.md +1412 -0
  327. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-fastapi.md +1585 -0
  328. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-flask.md +1208 -0
  329. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-laravel.md +2267 -0
  330. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-next-app-router.md +712 -0
  331. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-next-pages-router.md +767 -0
  332. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-nuxt-3-6.md +939 -0
  333. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-nuxt-4.md +1078 -0
  334. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-php.md +527 -0
  335. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-python.md +481 -0
  336. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-native.md +1823 -0
  337. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-6.md +582 -0
  338. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-7-data.md +892 -0
  339. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-7-declarative.md +649 -0
  340. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-7-framework.md +1218 -0
  341. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-tanstack-router-code-based.md +793 -0
  342. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-tanstack-router-file-based.md +780 -0
  343. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-ruby-on-rails.md +1320 -0
  344. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-ruby.md +452 -0
  345. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-sveltekit.md +854 -0
  346. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-swift.md +665 -0
  347. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-tanstack-start.md +1199 -0
  348. package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-vue-3.md +910 -0
  349. package/dist/global-skills/instrument-product-analytics/references/android.md +811 -0
  350. package/dist/global-skills/instrument-product-analytics/references/angular.md +376 -0
  351. package/dist/global-skills/instrument-product-analytics/references/astro.md +165 -0
  352. package/dist/global-skills/instrument-product-analytics/references/configuration.md +299 -0
  353. package/dist/global-skills/instrument-product-analytics/references/django.md +263 -0
  354. package/dist/global-skills/instrument-product-analytics/references/dotnet.md +763 -0
  355. package/dist/global-skills/instrument-product-analytics/references/elixir.md +414 -0
  356. package/dist/global-skills/instrument-product-analytics/references/flask.md +131 -0
  357. package/dist/global-skills/instrument-product-analytics/references/flutter.md +845 -0
  358. package/dist/global-skills/instrument-product-analytics/references/go.md +567 -0
  359. package/dist/global-skills/instrument-product-analytics/references/identify-users.md +272 -0
  360. package/dist/global-skills/instrument-product-analytics/references/ios.md +154 -0
  361. package/dist/global-skills/instrument-product-analytics/references/laravel.md +170 -0
  362. package/dist/global-skills/instrument-product-analytics/references/next-js.md +383 -0
  363. package/dist/global-skills/instrument-product-analytics/references/nuxt-js-3-6.md +244 -0
  364. package/dist/global-skills/instrument-product-analytics/references/nuxt-js.md +253 -0
  365. package/dist/global-skills/instrument-product-analytics/references/php.md +646 -0
  366. package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +1675 -0
  367. package/dist/global-skills/instrument-product-analytics/references/python.md +898 -0
  368. package/dist/global-skills/instrument-product-analytics/references/react-native.md +1338 -0
  369. package/dist/global-skills/instrument-product-analytics/references/react-router-v6.md +376 -0
  370. package/dist/global-skills/instrument-product-analytics/references/react-router-v7-data-mode.md +364 -0
  371. package/dist/global-skills/instrument-product-analytics/references/react-router-v7-declarative-mode.md +376 -0
  372. package/dist/global-skills/instrument-product-analytics/references/react-router-v7-framework-mode.md +479 -0
  373. package/dist/global-skills/instrument-product-analytics/references/ruby-on-rails.md +604 -0
  374. package/dist/global-skills/instrument-product-analytics/references/ruby.md +759 -0
  375. package/dist/global-skills/instrument-product-analytics/references/svelte.md +234 -0
  376. package/dist/global-skills/instrument-product-analytics/references/tanstack-start.md +193 -0
  377. package/dist/global-skills/instrument-product-analytics/references/usage.md +600 -0
  378. package/dist/global-skills/instrument-product-analytics/references/vue-js.md +306 -0
  379. package/dist/global-skills/manifest.json +125 -0
  380. package/dist/global-skills/mongodb-atlas-stream-processing/SKILL.md +284 -0
  381. package/dist/global-skills/mongodb-atlas-stream-processing/references/connection-configs.md +298 -0
  382. package/dist/global-skills/mongodb-atlas-stream-processing/references/development-workflow.md +304 -0
  383. package/dist/global-skills/mongodb-atlas-stream-processing/references/mcp-troubleshooting.md +55 -0
  384. package/dist/global-skills/mongodb-atlas-stream-processing/references/output-diagnostics.md +150 -0
  385. package/dist/global-skills/mongodb-atlas-stream-processing/references/pipeline-patterns.md +457 -0
  386. package/dist/global-skills/mongodb-atlas-stream-processing/references/sizing-and-parallelism.md +178 -0
  387. package/dist/global-skills/mongodb-connection/SKILL.md +201 -0
  388. package/dist/global-skills/mongodb-connection/references/monitoring-guide.md +191 -0
  389. package/dist/global-skills/mongodb-mcp-setup/SKILL.md +324 -0
  390. package/dist/global-skills/mongodb-natural-language-querying/SKILL.md +195 -0
  391. package/dist/global-skills/mongodb-query-optimizer/SKILL.md +150 -0
  392. package/dist/global-skills/mongodb-query-optimizer/references/aggregation-optimization.md +210 -0
  393. package/dist/global-skills/mongodb-query-optimizer/references/antipattern-examples.md +74 -0
  394. package/dist/global-skills/mongodb-query-optimizer/references/core-indexing-principles.md +134 -0
  395. package/dist/global-skills/mongodb-query-optimizer/references/update-query-examples.md +39 -0
  396. package/dist/global-skills/mongodb-schema-design/SKILL.md +181 -0
  397. package/dist/global-skills/mongodb-schema-design/references/antipattern-excessive-lookups.md +84 -0
  398. package/dist/global-skills/mongodb-schema-design/references/antipattern-unnecessary-collections.md +91 -0
  399. package/dist/global-skills/mongodb-schema-design/references/antipattern-unnecessary-indexes.md +95 -0
  400. package/dist/global-skills/mongodb-schema-design/references/fundamental-document-model.md +91 -0
  401. package/dist/global-skills/mongodb-schema-design/references/fundamental-document-size.md +226 -0
  402. package/dist/global-skills/mongodb-schema-design/references/fundamental-embed-vs-reference.md +418 -0
  403. package/dist/global-skills/mongodb-schema-design/references/fundamental-schema-validation.md +131 -0
  404. package/dist/global-skills/mongodb-schema-design/references/pattern-approximation.md +80 -0
  405. package/dist/global-skills/mongodb-schema-design/references/pattern-archive.md +143 -0
  406. package/dist/global-skills/mongodb-schema-design/references/pattern-attribute.md +77 -0
  407. package/dist/global-skills/mongodb-schema-design/references/pattern-bucket.md +102 -0
  408. package/dist/global-skills/mongodb-schema-design/references/pattern-computed.md +162 -0
  409. package/dist/global-skills/mongodb-schema-design/references/pattern-document-versioning.md +166 -0
  410. package/dist/global-skills/mongodb-schema-design/references/pattern-extended-reference.md +72 -0
  411. package/dist/global-skills/mongodb-schema-design/references/pattern-outlier.md +159 -0
  412. package/dist/global-skills/mongodb-schema-design/references/pattern-polymorphic.md +167 -0
  413. package/dist/global-skills/mongodb-schema-design/references/pattern-schema-versioning.md +273 -0
  414. package/dist/global-skills/mongodb-schema-design/references/pattern-time-series-collections.md +190 -0
  415. package/dist/global-skills/mongodb-schema-design/references/source-query-stats.md +123 -0
  416. package/dist/global-skills/mongodb-schema-design/references/source-slow-query-logs.md +63 -0
  417. package/dist/global-skills/mongodb-search-and-ai/SKILL.md +142 -0
  418. package/dist/global-skills/mongodb-search-and-ai/references/hybrid-search.md +697 -0
  419. package/dist/global-skills/mongodb-search-and-ai/references/lexical-search-indexing.md +584 -0
  420. package/dist/global-skills/mongodb-search-and-ai/references/lexical-search-querying.md +636 -0
  421. package/dist/global-skills/mongodb-search-and-ai/references/vector-search.md +746 -0
  422. package/dist/global-skills/native-data-fetching/SKILL.md +505 -0
  423. package/dist/global-skills/native-data-fetching/agents/openai.yaml +4 -0
  424. package/dist/global-skills/native-data-fetching/references/expo-router-loaders.md +341 -0
  425. package/dist/global-skills/neon/SKILL.md +343 -0
  426. package/dist/global-skills/neon-ai-gateway/SKILL.md +236 -0
  427. package/dist/global-skills/neon-functions/SKILL.md +490 -0
  428. package/dist/global-skills/neon-functions/references/ai-sdk.md +139 -0
  429. package/dist/global-skills/neon-functions/references/hono-websockets.md +145 -0
  430. package/dist/global-skills/neon-functions/references/mastra-studio.md +127 -0
  431. package/dist/global-skills/neon-functions/references/mcp.md +137 -0
  432. package/dist/global-skills/neon-functions/references/sentry.md +131 -0
  433. package/dist/global-skills/neon-functions/references/sse.md +143 -0
  434. package/dist/global-skills/neon-object-storage/SKILL.md +197 -0
  435. package/dist/global-skills/neon-postgres/SKILL.md +376 -0
  436. package/dist/global-skills/neon-postgres-branches/SKILL.md +281 -0
  437. package/dist/global-skills/neon-postgres-egress-optimizer/SKILL.md +247 -0
  438. package/dist/global-skills/onboarding/SKILL.md +101 -0
  439. package/dist/global-skills/plan-my-idea/SKILL.md +67 -0
  440. package/dist/global-skills/publish-app/SKILL.md +72 -0
  441. package/dist/global-skills/publish-extension/SKILL.md +47 -0
  442. package/dist/global-skills/resend/SKILL.md +294 -0
  443. package/dist/global-skills/resend/references/api-keys.md +98 -0
  444. package/dist/global-skills/resend/references/automations.md +228 -0
  445. package/dist/global-skills/resend/references/broadcasts.md +125 -0
  446. package/dist/global-skills/resend/references/contact-properties.md +111 -0
  447. package/dist/global-skills/resend/references/contacts.md +174 -0
  448. package/dist/global-skills/resend/references/domains.md +179 -0
  449. package/dist/global-skills/resend/references/events.md +119 -0
  450. package/dist/global-skills/resend/references/fetch-all-templates.mjs +37 -0
  451. package/dist/global-skills/resend/references/installation.md +142 -0
  452. package/dist/global-skills/resend/references/logs.md +161 -0
  453. package/dist/global-skills/resend/references/receiving.md +287 -0
  454. package/dist/global-skills/resend/references/segments.md +77 -0
  455. package/dist/global-skills/resend/references/sending/batch-email-examples.md +807 -0
  456. package/dist/global-skills/resend/references/sending/best-practices.md +453 -0
  457. package/dist/global-skills/resend/references/sending/email-management.md +135 -0
  458. package/dist/global-skills/resend/references/sending/overview.md +209 -0
  459. package/dist/global-skills/resend/references/sending/single-email-examples.md +470 -0
  460. package/dist/global-skills/resend/references/templates.md +202 -0
  461. package/dist/global-skills/resend/references/topics.md +104 -0
  462. package/dist/global-skills/resend/references/webhooks.md +317 -0
  463. package/dist/global-skills/reset-password/SKILL.md +59 -0
  464. package/dist/global-skills/save-data/SKILL.md +70 -0
  465. package/dist/global-skills/sentry-sdk-setup/SKILL.md +116 -0
  466. package/dist/global-skills/sentry-workflow/SKILL.md +32 -0
  467. package/dist/global-skills/setup-email/SKILL.md +69 -0
  468. package/dist/global-skills/setup-payments/SKILL.md +82 -0
  469. package/dist/global-skills/setup-sms/SKILL.md +51 -0
  470. package/dist/global-skills/sign-in-with-email-link/SKILL.md +53 -0
  471. package/dist/global-skills/sign-in-with-google/SKILL.md +68 -0
  472. package/dist/global-skills/sign-in-with-phone/SKILL.md +53 -0
  473. package/dist/global-skills/stripe-best-practices/SKILL.md +48 -0
  474. package/dist/global-skills/stripe-best-practices/references/billing.md +58 -0
  475. package/dist/global-skills/stripe-best-practices/references/connect.md +173 -0
  476. package/dist/global-skills/stripe-best-practices/references/payments.md +79 -0
  477. package/dist/global-skills/stripe-best-practices/references/security.md +109 -0
  478. package/dist/global-skills/stripe-best-practices/references/tax.md +37 -0
  479. package/dist/global-skills/stripe-best-practices/references/treasury.md +16 -0
  480. package/dist/global-skills/supabase/CHANGELOG.md +53 -0
  481. package/dist/global-skills/supabase/SKILL.md +145 -0
  482. package/dist/global-skills/supabase/assets/feedback-issue-template.md +17 -0
  483. package/dist/global-skills/supabase/references/skill-feedback.md +17 -0
  484. package/dist/global-skills/supabase-postgres-best-practices/CHANGELOG.md +43 -0
  485. package/dist/global-skills/supabase-postgres-best-practices/SKILL.md +64 -0
  486. package/dist/global-skills/supabase-postgres-best-practices/references/_contributing.md +170 -0
  487. package/dist/global-skills/supabase-postgres-best-practices/references/_sections.md +39 -0
  488. package/dist/global-skills/supabase-postgres-best-practices/references/_template.md +34 -0
  489. package/dist/global-skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
  490. package/dist/global-skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
  491. package/dist/global-skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
  492. package/dist/global-skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
  493. package/dist/global-skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
  494. package/dist/global-skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
  495. package/dist/global-skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
  496. package/dist/global-skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
  497. package/dist/global-skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
  498. package/dist/global-skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
  499. package/dist/global-skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
  500. package/dist/global-skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
  501. package/dist/global-skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
  502. package/dist/global-skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
  503. package/dist/global-skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
  504. package/dist/global-skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
  505. package/dist/global-skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
  506. package/dist/global-skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
  507. package/dist/global-skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
  508. package/dist/global-skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
  509. package/dist/global-skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
  510. package/dist/global-skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
  511. package/dist/global-skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
  512. package/dist/global-skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
  513. package/dist/global-skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
  514. package/dist/global-skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
  515. package/dist/global-skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
  516. package/dist/global-skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
  517. package/dist/global-skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
  518. package/dist/global-skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
  519. package/dist/global-skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -0
  520. package/dist/global-skills/track-errors/SKILL.md +67 -0
  521. package/dist/global-skills/update-kit/SKILL.md +75 -0
  522. package/dist/global-skills/upgrading-expo/SKILL.md +134 -0
  523. package/dist/global-skills/upgrading-expo/agents/openai.yaml +4 -0
  524. package/dist/global-skills/upgrading-expo/references/expo-av-to-audio.md +132 -0
  525. package/dist/global-skills/upgrading-expo/references/expo-av-to-video.md +160 -0
  526. package/dist/global-skills/upgrading-expo/references/native-tabs.md +124 -0
  527. package/dist/global-skills/upgrading-expo/references/new-architecture.md +79 -0
  528. package/dist/global-skills/upgrading-expo/references/react-19.md +79 -0
  529. package/dist/global-skills/upgrading-expo/references/react-compiler.md +59 -0
  530. package/dist/global-skills/upgrading-expo/references/react-navigation-to-expo-router.md +61 -0
  531. package/dist/global-skills/use-dom/SKILL.md +417 -0
  532. package/dist/global-skills/use-dom/agents/openai.yaml +4 -0
  533. package/dist/global-skills/use-kit-mcp/SKILL.md +100 -0
  534. package/dist/global-skills/use-railway/SKILL.md +357 -0
  535. package/dist/global-skills/use-railway/references/analyze-db-mongo.md +84 -0
  536. package/dist/global-skills/use-railway/references/analyze-db-mysql.md +254 -0
  537. package/dist/global-skills/use-railway/references/analyze-db-postgres.md +479 -0
  538. package/dist/global-skills/use-railway/references/analyze-db-redis.md +208 -0
  539. package/dist/global-skills/use-railway/references/analyze-db.md +344 -0
  540. package/dist/global-skills/use-railway/references/configure.md +359 -0
  541. package/dist/global-skills/use-railway/references/deploy.md +225 -0
  542. package/dist/global-skills/use-railway/references/feature-flags.md +89 -0
  543. package/dist/global-skills/use-railway/references/iac.md +108 -0
  544. package/dist/global-skills/use-railway/references/operate.md +273 -0
  545. package/dist/global-skills/use-railway/references/request.md +262 -0
  546. package/dist/global-skills/use-railway/references/sandbox.md +167 -0
  547. package/dist/global-skills/use-railway/references/setup.md +364 -0
  548. package/dist/global-skills/use-railway/scripts/analyze-mongo.py +1549 -0
  549. package/dist/global-skills/use-railway/scripts/analyze-mysql.py +1195 -0
  550. package/dist/global-skills/use-railway/scripts/analyze-postgres.py +3058 -0
  551. package/dist/global-skills/use-railway/scripts/analyze-redis.py +1090 -0
  552. package/dist/global-skills/use-railway/scripts/dal.py +671 -0
  553. package/dist/global-skills/use-railway/scripts/enable-pg-stats.py +170 -0
  554. package/dist/global-skills/use-railway/scripts/pg-extensions.py +370 -0
  555. package/dist/global-skills/use-railway/scripts/railway-api.sh +52 -0
  556. package/dist/global-skills/vercel-composition-patterns/AGENTS.md +946 -0
  557. package/dist/global-skills/vercel-composition-patterns/README.md +60 -0
  558. package/dist/global-skills/vercel-composition-patterns/SKILL.md +89 -0
  559. package/dist/global-skills/vercel-composition-patterns/metadata.json +11 -0
  560. package/dist/global-skills/vercel-composition-patterns/rules/_sections.md +29 -0
  561. package/dist/global-skills/vercel-composition-patterns/rules/_template.md +24 -0
  562. package/dist/global-skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  563. package/dist/global-skills/vercel-composition-patterns/rules/architecture-compound-components.md +112 -0
  564. package/dist/global-skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  565. package/dist/global-skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -0
  566. package/dist/global-skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
  567. package/dist/global-skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
  568. package/dist/global-skills/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -0
  569. package/dist/global-skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
  570. package/dist/global-skills/vercel-react-best-practices/AGENTS.md +3810 -0
  571. package/dist/global-skills/vercel-react-best-practices/README.md +123 -0
  572. package/dist/global-skills/vercel-react-best-practices/SKILL.md +149 -0
  573. package/dist/global-skills/vercel-react-best-practices/metadata.json +15 -0
  574. package/dist/global-skills/vercel-react-best-practices/rules/_sections.md +46 -0
  575. package/dist/global-skills/vercel-react-best-practices/rules/_template.md +28 -0
  576. package/dist/global-skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md +56 -0
  577. package/dist/global-skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  578. package/dist/global-skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  579. package/dist/global-skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  580. package/dist/global-skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  581. package/dist/global-skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  582. package/dist/global-skills/vercel-react-best-practices/rules/async-defer-await.md +82 -0
  583. package/dist/global-skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  584. package/dist/global-skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  585. package/dist/global-skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  586. package/dist/global-skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md +63 -0
  587. package/dist/global-skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
  588. package/dist/global-skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  589. package/dist/global-skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  590. package/dist/global-skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  591. package/dist/global-skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  592. package/dist/global-skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  593. package/dist/global-skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  594. package/dist/global-skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  595. package/dist/global-skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  596. package/dist/global-skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  597. package/dist/global-skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  598. package/dist/global-skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  599. package/dist/global-skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  600. package/dist/global-skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  601. package/dist/global-skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  602. package/dist/global-skills/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
  603. package/dist/global-skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  604. package/dist/global-skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  605. package/dist/global-skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  606. package/dist/global-skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  607. package/dist/global-skills/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
  608. package/dist/global-skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  609. package/dist/global-skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  610. package/dist/global-skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  611. package/dist/global-skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  612. package/dist/global-skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  613. package/dist/global-skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  614. package/dist/global-skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  615. package/dist/global-skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  616. package/dist/global-skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  617. package/dist/global-skills/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
  618. package/dist/global-skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
  619. package/dist/global-skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  620. package/dist/global-skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  621. package/dist/global-skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  622. package/dist/global-skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  623. package/dist/global-skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  624. package/dist/global-skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  625. package/dist/global-skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  626. package/dist/global-skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  627. package/dist/global-skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  628. package/dist/global-skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  629. package/dist/global-skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  630. package/dist/global-skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
  631. package/dist/global-skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  632. package/dist/global-skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  633. package/dist/global-skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  634. package/dist/global-skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  635. package/dist/global-skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  636. package/dist/global-skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  637. package/dist/global-skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  638. package/dist/global-skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  639. package/dist/global-skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  640. package/dist/global-skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  641. package/dist/global-skills/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
  642. package/dist/global-skills/vercel-react-best-practices/rules/server-no-shared-module-state.md +50 -0
  643. package/dist/global-skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  644. package/dist/global-skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
  645. package/dist/global-skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  646. package/dist/global-skills/web-to-native/SKILL.md +83 -0
  647. package/dist/global-skills/web-to-native/references/false-friends.md +119 -0
  648. package/dist/global-skills/web-to-native/references/native-patterns.md +39 -0
  649. package/dist/global-skills/web-to-native/references/run-as-goal.md +48 -0
  650. package/dist/global-skills/web-to-native/references/verify-on-device.md +45 -0
  651. package/dist/global-skills/wire-auth/SKILL.md +28 -0
  652. package/dist/global-skills/wire-database/SKILL.md +28 -0
  653. package/dist/global-skills/wire-email/SKILL.md +27 -0
  654. package/dist/global-skills/wire-payments/SKILL.md +27 -0
  655. package/dist/global-skills/workers-best-practices/SKILL.md +127 -0
  656. package/dist/global-skills/workers-best-practices/references/review.md +174 -0
  657. package/dist/global-skills/workers-best-practices/references/rules.md +463 -0
  658. package/dist/global-skills/wrangler/SKILL.md +922 -0
  659. package/dist/global-skills/xcode-project-setup/SKILL.md +140 -0
  660. package/dist/global-skills/xcode-project-setup/scripts/xcode_spm_setup/Package.resolved +41 -0
  661. package/dist/global-skills/xcode-project-setup/scripts/xcode_spm_setup/Package.swift +17 -0
  662. package/dist/global-skills/xcode-project-setup/scripts/xcode_spm_setup/Sources/main.swift +232 -0
  663. package/package.json +21 -20
  664. package/LICENSE.md +0 -47
  665. package/dist/index.js +0 -21593
@@ -0,0 +1,1585 @@
1
+ # PostHog fastapi Example Project
2
+
3
+ Repository: https://github.com/PostHog/context-mill
4
+ Path: example-apps/fastapi
5
+
6
+ ---
7
+
8
+ ## README.md
9
+
10
+ # PostHog FastAPI Example
11
+
12
+ A FastAPI application demonstrating PostHog integration for analytics, feature flags, and error tracking.
13
+
14
+ ## Features
15
+
16
+ - User registration and authentication with cookie-based sessions
17
+ - SQLite database persistence with SQLAlchemy
18
+ - User identification and property tracking
19
+ - Custom event tracking
20
+ - Feature flags with payload support
21
+ - Error tracking with manual exception capture
22
+
23
+ ## Quick Start
24
+
25
+ 1. Create and activate a virtual environment:
26
+ ```bash
27
+ python -m venv venv
28
+ source venv/bin/activate # On Windows: venv\Scripts\activate
29
+ ```
30
+
31
+ 2. Install dependencies:
32
+ ```bash
33
+ pip install -r requirements.txt
34
+ ```
35
+
36
+ 3. Copy the environment file and configure:
37
+ ```bash
38
+ cp .env.example .env
39
+ # Edit .env with your PostHog project key
40
+ ```
41
+
42
+ 4. Run the application:
43
+ ```bash
44
+ python run.py
45
+ ```
46
+
47
+ 5. Open http://localhost:5002 and either:
48
+ - Login with default credentials: `admin@example.com` / `admin`
49
+ - Or click "Sign up here" to create a new account
50
+
51
+ ## PostHog Integration Points
52
+
53
+ ### User Registration
54
+ New users are identified and tracked on signup using the context-based API:
55
+ ```python
56
+ with new_context():
57
+ identify_context(user.email)
58
+ tag('email', user.email)
59
+ tag('is_staff', user.is_staff)
60
+ capture('user_signed_up', properties={'signup_method': 'form'})
61
+ ```
62
+
63
+ ### User Identification
64
+ Users are identified on login with their properties:
65
+ ```python
66
+ with new_context():
67
+ identify_context(user.email)
68
+ tag('email', user.email)
69
+ tag('is_staff', user.is_staff)
70
+ capture('user_logged_in', properties={'login_method': 'password'})
71
+ ```
72
+
73
+ ### Event Tracking
74
+ Custom events are captured throughout the app:
75
+ ```python
76
+ with new_context():
77
+ identify_context(current_user.email)
78
+ capture('burrito_considered', properties={'total_considerations': count})
79
+ ```
80
+
81
+ ### Feature Flags
82
+ The dashboard demonstrates feature flag checking:
83
+ ```python
84
+ show_new_feature = posthog.feature_enabled(
85
+ 'new-dashboard-feature',
86
+ current_user.email,
87
+ person_properties={'email': current_user.email, 'is_staff': current_user.is_staff}
88
+ )
89
+ feature_config = posthog.get_feature_flag_payload('new-dashboard-feature', current_user.email)
90
+ ```
91
+
92
+ ### Error Tracking
93
+
94
+ The example demonstrates two approaches to error tracking:
95
+
96
+ Manual capture for specific critical operations** (`app/routers/api.py`).
97
+
98
+ ```python
99
+ try:
100
+ # Critical operation that might fail
101
+ result = process_payment()
102
+ except Exception as e:
103
+ # Manually capture this specific exception
104
+ with new_context():
105
+ identify_context(current_user.email)
106
+ event_id = posthog.capture_exception(e)
107
+
108
+ return JSONResponse({
109
+ "error": "Operation failed",
110
+ "error_id": event_id,
111
+ "message": f"Error captured in PostHog. Reference ID: {event_id}"
112
+ }, status_code=500)
113
+ ```
114
+
115
+ The `/api/test-error` endpoint demonstrates manual exception capture. Use `?capture=true` to capture in PostHog, or `?capture=false` to skip tracking.
116
+
117
+ ## Project Structure
118
+
119
+ ```
120
+ basics/fastapi/
121
+ ├── app/
122
+ │ ├── __init__.py # Package marker
123
+ │ ├── config.py # Pydantic Settings configuration
124
+ │ ├── database.py # SQLAlchemy setup
125
+ │ ├── dependencies.py # FastAPI dependency injection
126
+ │ ├── main.py # Application factory and lifespan
127
+ │ ├── models.py # User model (SQLAlchemy)
128
+ │ ├── routers/
129
+ │ │ ├── __init__.py # Routers package
130
+ │ │ ├── main.py # Page routes (HTML)
131
+ │ │ └── api.py # API endpoints (JSON)
132
+ │ └── templates/ # Jinja2 templates
133
+ ├── .env.example
134
+ ├── .gitignore
135
+ ├── requirements.txt
136
+ ├── README.md
137
+ └── run.py # Entry point (uvicorn)
138
+ ```
139
+
140
+ ---
141
+
142
+ ## .env.example
143
+
144
+ ```example
145
+ POSTHOG_PROJECT_TOKEN=<ph_project_token>
146
+ POSTHOG_HOST=https://us.i.posthog.com
147
+ SECRET_KEY=your-secret-key-here
148
+ DEBUG=True
149
+ POSTHOG_DISABLED=False
150
+
151
+ ```
152
+
153
+ ---
154
+
155
+ ## app/__init__.py
156
+
157
+ ```py
158
+ """FastAPI PostHog example application."""
159
+
160
+ ```
161
+
162
+ ---
163
+
164
+ ## app/config.py
165
+
166
+ ```py
167
+ """FastAPI application configuration using Pydantic Settings."""
168
+
169
+ from functools import lru_cache
170
+
171
+ from pydantic_settings import BaseSettings, SettingsConfigDict
172
+
173
+
174
+ class Settings(BaseSettings):
175
+ """Application settings loaded from environment variables."""
176
+
177
+ model_config = SettingsConfigDict(
178
+ env_file=".env",
179
+ env_file_encoding="utf-8",
180
+ extra="ignore",
181
+ )
182
+
183
+ # Application
184
+ secret_key: str = "dev-secret-key-change-in-production"
185
+ debug: bool = True
186
+
187
+ # Database (SQLite like Flask example)
188
+ database_url: str = "sqlite:///./db.sqlite3"
189
+
190
+ # PostHog
191
+ posthog_project_token: str = "<ph_project_token>"
192
+ posthog_host: str = "https://us.i.posthog.com"
193
+ posthog_disabled: bool = False
194
+
195
+
196
+ @lru_cache
197
+ def get_settings() -> Settings:
198
+ """Get cached settings instance."""
199
+ return Settings()
200
+
201
+ ```
202
+
203
+ ---
204
+
205
+ ## app/database.py
206
+
207
+ ```py
208
+ """Database configuration with SQLAlchemy."""
209
+
210
+ from sqlalchemy import create_engine
211
+ from sqlalchemy.orm import DeclarativeBase, sessionmaker
212
+
213
+ from app.config import get_settings
214
+
215
+ settings = get_settings()
216
+
217
+ engine = create_engine(
218
+ settings.database_url,
219
+ connect_args={"check_same_thread": False}, # Required for SQLite
220
+ )
221
+
222
+ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
223
+
224
+
225
+ class Base(DeclarativeBase):
226
+ """Base class for SQLAlchemy models."""
227
+
228
+ pass
229
+
230
+
231
+ def get_db():
232
+ """Dependency that provides a database session."""
233
+ db = SessionLocal()
234
+ try:
235
+ yield db
236
+ finally:
237
+ db.close()
238
+
239
+
240
+ def init_db():
241
+ """Create all database tables."""
242
+ Base.metadata.create_all(bind=engine)
243
+
244
+ ```
245
+
246
+ ---
247
+
248
+ ## app/dependencies.py
249
+
250
+ ```py
251
+ """Authentication dependencies for FastAPI."""
252
+
253
+ from typing import Annotated, Optional
254
+
255
+ from fastapi import Cookie, Depends, HTTPException, status
256
+ from itsdangerous import BadSignature, URLSafeSerializer
257
+ from sqlalchemy.orm import Session
258
+
259
+ from app.config import get_settings
260
+ from app.database import get_db
261
+ from app.models import User
262
+
263
+ settings = get_settings()
264
+ serializer = URLSafeSerializer(settings.secret_key)
265
+
266
+
267
+ def get_session_user_id(session_token: Annotated[Optional[str], Cookie()] = None) -> Optional[int]:
268
+ """Extract user ID from session cookie."""
269
+ if not session_token:
270
+ return None
271
+ try:
272
+ data = serializer.loads(session_token)
273
+ return data.get("user_id")
274
+ except BadSignature:
275
+ return None
276
+
277
+
278
+ def get_current_user(
279
+ db: Annotated[Session, Depends(get_db)],
280
+ user_id: Annotated[Optional[int], Depends(get_session_user_id)],
281
+ ) -> Optional[User]:
282
+ """Get the current authenticated user, or None if not authenticated."""
283
+ if user_id is None:
284
+ return None
285
+ return User.get_by_id(db, user_id)
286
+
287
+
288
+ def require_auth(
289
+ current_user: Annotated[Optional[User], Depends(get_current_user)],
290
+ ) -> User:
291
+ """Require authentication - raises 401 if not authenticated."""
292
+ if current_user is None:
293
+ raise HTTPException(
294
+ status_code=status.HTTP_401_UNAUTHORIZED,
295
+ detail="Authentication required",
296
+ )
297
+ return current_user
298
+
299
+
300
+ def create_session_token(user_id: int) -> str:
301
+ """Create a signed session token for the user."""
302
+ return serializer.dumps({"user_id": user_id})
303
+
304
+
305
+ # Type aliases for cleaner dependency injection
306
+ CurrentUser = Annotated[Optional[User], Depends(get_current_user)]
307
+ RequiredUser = Annotated[User, Depends(require_auth)]
308
+ DbSession = Annotated[Session, Depends(get_db)]
309
+
310
+ ```
311
+
312
+ ---
313
+
314
+ ## app/main.py
315
+
316
+ ```py
317
+ """FastAPI application with PostHog integration."""
318
+
319
+ from contextlib import asynccontextmanager
320
+ from pathlib import Path
321
+
322
+ import posthog
323
+ from fastapi import FastAPI, Request
324
+ from fastapi.responses import HTMLResponse, JSONResponse
325
+ from fastapi.staticfiles import StaticFiles
326
+ from fastapi.templating import Jinja2Templates
327
+
328
+ from app.config import get_settings
329
+ from app.database import SessionLocal, init_db
330
+ from app.middleware import PostHogMiddleware
331
+ from app.models import User
332
+ from app.routers import api, main
333
+
334
+ settings = get_settings()
335
+
336
+ # Setup templates
337
+ templates_dir = Path(__file__).parent / "templates"
338
+ templates = Jinja2Templates(directory=str(templates_dir))
339
+
340
+
341
+ @asynccontextmanager
342
+ async def lifespan(app: FastAPI):
343
+ """Application lifespan events for startup/shutdown."""
344
+ # Startup: Initialize PostHog
345
+ if not settings.posthog_disabled:
346
+ posthog.api_key = settings.posthog_project_token
347
+ posthog.host = settings.posthog_host
348
+ posthog.debug = settings.debug
349
+
350
+ # Initialize database and seed default user
351
+ init_db()
352
+ db = SessionLocal()
353
+ try:
354
+ if not User.get_by_email(db, "admin@example.com"):
355
+ User.create_user(
356
+ db,
357
+ email="admin@example.com",
358
+ password="admin",
359
+ is_staff=True,
360
+ )
361
+ finally:
362
+ db.close()
363
+
364
+ yield
365
+
366
+ # Shutdown: Flush PostHog events
367
+ if not settings.posthog_disabled:
368
+ posthog.flush()
369
+
370
+
371
+ app = FastAPI(
372
+ title="PostHog FastAPI Example",
373
+ description="Example application demonstrating PostHog integration with FastAPI",
374
+ lifespan=lifespan,
375
+ )
376
+
377
+ app.add_middleware(PostHogMiddleware)
378
+
379
+ # Include routers
380
+ app.include_router(main.router)
381
+ app.include_router(api.router, prefix="/api")
382
+
383
+
384
+ # Error handlers
385
+ @app.exception_handler(404)
386
+ async def not_found_handler(request: Request, exc):
387
+ """Handle 404 errors."""
388
+ if request.url.path.startswith("/api/"):
389
+ return JSONResponse({"error": "Not found"}, status_code=404)
390
+ return templates.TemplateResponse(
391
+ request, "errors/404.html", status_code=404
392
+ )
393
+
394
+
395
+ @app.exception_handler(500)
396
+ async def internal_error_handler(request: Request, exc):
397
+ """Handle 500 errors."""
398
+ if request.url.path.startswith("/api/"):
399
+ return JSONResponse({"error": "Internal server error"}, status_code=500)
400
+ return templates.TemplateResponse(
401
+ request, "errors/500.html", status_code=500
402
+ )
403
+
404
+ ```
405
+
406
+ ---
407
+
408
+ ## app/middleware.py
409
+
410
+ ```py
411
+ """PostHog middleware for automatic context and user identification.
412
+
413
+ Uses pure ASGI middleware instead of BaseHTTPMiddleware for better performance/best practices.
414
+ """
415
+
416
+ from http.cookies import SimpleCookie
417
+ from typing import Callable, Optional
418
+
419
+ from posthog import identify_context, new_context, tag
420
+
421
+ from app.config import get_settings
422
+ from app.database import SessionLocal
423
+ from app.dependencies import serializer
424
+ from app.models import User
425
+
426
+
427
+ class PostHogMiddleware:
428
+ """Pure ASGI middleware that wraps each request in a PostHog context.
429
+
430
+ If the user is authenticated, identifies them in the context so routes
431
+ can just call capture() without needing to set up context each time.
432
+
433
+ Uses pure ASGI interface for better performance than BaseHTTPMiddleware.
434
+ """
435
+
436
+ def __init__(self, app):
437
+ self.app = app
438
+ self.settings = get_settings()
439
+
440
+ async def __call__(self, scope, receive, send):
441
+ if scope["type"] != "http" or self.settings.posthog_disabled:
442
+ await self.app(scope, receive, send)
443
+ return
444
+
445
+ user = self._get_user_from_scope(scope)
446
+
447
+ with new_context():
448
+ if user:
449
+ identify_context(user.email)
450
+ tag("email", user.email)
451
+ tag("is_staff", user.is_staff)
452
+
453
+ await self.app(scope, receive, send)
454
+
455
+ def _get_user_from_scope(self, scope) -> Optional[User]:
456
+ """Extract authenticated user from session cookie in ASGI scope."""
457
+ headers = dict(scope.get("headers", []))
458
+ cookie_header = headers.get(b"cookie", b"").decode("utf-8")
459
+
460
+ if not cookie_header:
461
+ return None
462
+
463
+ cookies = SimpleCookie()
464
+ cookies.load(cookie_header)
465
+
466
+ session_cookie = cookies.get("session_token")
467
+ if not session_cookie:
468
+ return None
469
+
470
+ session_token = session_cookie.value
471
+
472
+ try:
473
+ data = serializer.loads(session_token)
474
+ user_id = data.get("user_id")
475
+ except Exception:
476
+ return None
477
+
478
+ if not user_id:
479
+ return None
480
+
481
+ db = SessionLocal()
482
+ try:
483
+ return User.get_by_id(db, user_id)
484
+ finally:
485
+ db.close()
486
+
487
+ ```
488
+
489
+ ---
490
+
491
+ ## app/models.py
492
+
493
+ ```py
494
+ """User model with SQLite persistence (similar to Flask example)."""
495
+
496
+ from datetime import datetime, timezone
497
+ from typing import Optional
498
+
499
+ from sqlalchemy import Boolean, DateTime, Integer, String
500
+ from sqlalchemy.orm import Mapped, Session, mapped_column
501
+ from werkzeug.security import check_password_hash, generate_password_hash
502
+
503
+ from app.database import Base
504
+
505
+
506
+ class User(Base):
507
+ """User model with SQLite persistence."""
508
+
509
+ __tablename__ = "users"
510
+
511
+ id: Mapped[int] = mapped_column(Integer, primary_key=True)
512
+ email: Mapped[str] = mapped_column(String(254), unique=True, nullable=False)
513
+ password_hash: Mapped[str] = mapped_column(String(256), nullable=False)
514
+ name: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
515
+ is_staff: Mapped[bool] = mapped_column(Boolean, default=False)
516
+ is_active: Mapped[bool] = mapped_column(Boolean, default=True)
517
+ login_count: Mapped[int] = mapped_column(Integer, default=0)
518
+ date_joined: Mapped[datetime] = mapped_column(
519
+ DateTime, default=lambda: datetime.now(timezone.utc)
520
+ )
521
+
522
+ def set_password(self, password: str) -> None:
523
+ """Hash and set the user's password."""
524
+ self.password_hash = generate_password_hash(password, method="pbkdf2:sha256")
525
+
526
+ def check_password(self, password: str) -> bool:
527
+ """Verify the password against the hash."""
528
+ return check_password_hash(self.password_hash, password)
529
+
530
+ @classmethod
531
+ def create_user(
532
+ cls, db: Session, email: str, password: str, is_staff: bool = False
533
+ ) -> "User":
534
+ """Create and save a new user."""
535
+ user = cls(email=email, is_staff=is_staff)
536
+ # nosemgrep: python.django.security.audit.unvalidated-password.unvalidated-password
537
+ user.set_password(password)
538
+ db.add(user)
539
+ db.commit()
540
+ db.refresh(user)
541
+ return user
542
+
543
+ @classmethod
544
+ def get_by_id(cls, db: Session, user_id: int) -> Optional["User"]:
545
+ """Get user by ID."""
546
+ return db.query(cls).filter(cls.id == user_id).first()
547
+
548
+ @classmethod
549
+ def get_by_email(cls, db: Session, email: str) -> Optional["User"]:
550
+ """Get user by email."""
551
+ return db.query(cls).filter(cls.email == email).first()
552
+
553
+ @classmethod
554
+ def authenticate(cls, db: Session, email: str, password: str) -> Optional["User"]:
555
+ """Authenticate user with email and password."""
556
+ user = cls.get_by_email(db, email)
557
+ if user and user.check_password(password):
558
+ return user
559
+ return None
560
+
561
+ def record_login(self, db: Session) -> bool:
562
+ """Record a login and return whether this is the user's first login."""
563
+ is_first_login = self.login_count == 0
564
+ self.login_count += 1
565
+ db.commit()
566
+ return is_first_login
567
+
568
+ def update_profile(self, db: Session, name: Optional[str] = None) -> list:
569
+ """Update user profile and return list of changed fields."""
570
+ changed_fields = []
571
+ if name is not None and name != self.name:
572
+ self.name = name
573
+ changed_fields.append("name")
574
+ if changed_fields:
575
+ db.commit()
576
+ return changed_fields
577
+
578
+ def __repr__(self) -> str:
579
+ return f"<User {self.email}>"
580
+
581
+ ```
582
+
583
+ ---
584
+
585
+ ## app/routers/__init__.py
586
+
587
+ ```py
588
+ """FastAPI routers package."""
589
+
590
+ ```
591
+
592
+ ---
593
+
594
+ ## app/routers/api.py
595
+
596
+ ```py
597
+ """API endpoints demonstrating PostHog integration patterns."""
598
+
599
+ from typing import Annotated
600
+
601
+ import posthog
602
+ from fastapi import APIRouter, Cookie, Form, Query
603
+ from fastapi.responses import JSONResponse
604
+ from posthog import capture
605
+
606
+ from app.dependencies import RequiredUser
607
+
608
+ router = APIRouter()
609
+
610
+ MAX_BURRITO_COUNT = 10000
611
+
612
+
613
+ @router.post("/burrito/consider")
614
+ async def consider_burrito(
615
+ current_user: RequiredUser,
616
+ burrito_count: Annotated[int, Cookie()] = 0,
617
+ ):
618
+ """Track burrito consideration event."""
619
+ safe_count = max(0, min(burrito_count, MAX_BURRITO_COUNT))
620
+ new_count = safe_count + 1
621
+
622
+ capture("burrito_considered", properties={"total_considerations": new_count})
623
+
624
+ response = JSONResponse({"success": True, "count": new_count})
625
+ response.set_cookie(
626
+ key="burrito_count",
627
+ value=str(new_count),
628
+ httponly=True,
629
+ samesite="lax",
630
+ )
631
+ return response
632
+
633
+
634
+ @router.post("/test-error")
635
+ async def test_error(
636
+ current_user: RequiredUser,
637
+ capture_param: Annotated[str, Query(alias="capture")] = "true",
638
+ ):
639
+ """Test endpoint demonstrating manual exception capture in PostHog."""
640
+ should_capture = capture_param.lower() == "true"
641
+
642
+ try:
643
+ raise Exception("Test exception from critical operation")
644
+ except Exception as e:
645
+ if should_capture:
646
+ event_id = posthog.capture_exception(e)
647
+ return JSONResponse(
648
+ {
649
+ "error": "Operation failed",
650
+ "error_id": event_id,
651
+ "message": f"Error captured in PostHog. Reference ID: {event_id}",
652
+ },
653
+ status_code=500,
654
+ )
655
+ else:
656
+ return JSONResponse({"error": "Operation failed"}, status_code=500)
657
+
658
+
659
+ @router.post("/trigger-error")
660
+ async def trigger_error(
661
+ current_user: RequiredUser,
662
+ error_type: Annotated[str, Form()] = "generic",
663
+ ):
664
+ """Trigger different error types for testing error tracking."""
665
+ error_messages = {
666
+ "value": "Invalid value provided",
667
+ "key": "Missing required key",
668
+ "generic": "Generic test error",
669
+ }
670
+
671
+ safe_error_type = error_type if error_type in error_messages else "generic"
672
+ error_message = error_messages[safe_error_type]
673
+
674
+ try:
675
+ if safe_error_type == "value":
676
+ raise ValueError(error_message)
677
+ elif safe_error_type == "key":
678
+ raise KeyError("missing_key")
679
+ else:
680
+ raise Exception(error_message)
681
+ except Exception as e:
682
+ posthog.capture_exception(e)
683
+ capture(
684
+ "error_triggered",
685
+ properties={"error_type": safe_error_type, "error_message": error_message},
686
+ )
687
+
688
+ return JSONResponse(
689
+ {
690
+ "success": True,
691
+ "message": "Error captured in PostHog",
692
+ "error": error_message,
693
+ }
694
+ )
695
+
696
+
697
+ @router.post("/reports/activity")
698
+ async def generate_activity_report(
699
+ current_user: RequiredUser,
700
+ report_type: Annotated[str, Form()] = "summary",
701
+ ):
702
+ """Generate user activity report."""
703
+ valid_report_types = {"summary", "detailed", "export"}
704
+ safe_report_type = report_type if report_type in valid_report_types else "summary"
705
+
706
+ report_data = {
707
+ "user": current_user.email,
708
+ "name": current_user.name,
709
+ "date_joined": current_user.date_joined.isoformat(),
710
+ "login_count": current_user.login_count,
711
+ "is_staff": current_user.is_staff,
712
+ }
713
+
714
+ if safe_report_type == "detailed":
715
+ report_data["account_age_days"] = (
716
+ __import__("datetime").datetime.now(__import__("datetime").timezone.utc)
717
+ - current_user.date_joined
718
+ ).days
719
+
720
+ row_count = len(report_data)
721
+
722
+ capture(
723
+ "report_generated",
724
+ properties={
725
+ "report_type": safe_report_type,
726
+ "row_count": row_count,
727
+ "username": current_user.email,
728
+ },
729
+ )
730
+
731
+ return JSONResponse(
732
+ {
733
+ "success": True,
734
+ "report_type": safe_report_type,
735
+ "row_count": row_count,
736
+ "data": report_data,
737
+ }
738
+ )
739
+
740
+ ```
741
+
742
+ ---
743
+
744
+ ## app/routers/main.py
745
+
746
+ ```py
747
+ """Main routes demonstrating PostHog integration patterns."""
748
+
749
+ from pathlib import Path
750
+ from typing import Annotated
751
+
752
+ import posthog
753
+ from fastapi import APIRouter, Cookie, Depends, Form, Request
754
+ from fastapi.responses import HTMLResponse, RedirectResponse
755
+ from fastapi.templating import Jinja2Templates
756
+ from posthog import capture, identify_context, new_context
757
+
758
+ from app.dependencies import (
759
+ CurrentUser,
760
+ DbSession,
761
+ RequiredUser,
762
+ create_session_token,
763
+ )
764
+ from app.models import User
765
+
766
+ router = APIRouter()
767
+
768
+ # Setup templates
769
+ templates_dir = Path(__file__).parent.parent / "templates"
770
+ templates = Jinja2Templates(directory=str(templates_dir))
771
+
772
+
773
+ @router.get("/", response_class=HTMLResponse)
774
+ async def home(request: Request, current_user: CurrentUser, db: DbSession):
775
+ """Home/login page."""
776
+ if current_user:
777
+ return RedirectResponse(url="/dashboard", status_code=302)
778
+
779
+ return templates.TemplateResponse(
780
+ request, "home.html", {"current_user": current_user}
781
+ )
782
+
783
+
784
+ @router.post("/", response_class=HTMLResponse)
785
+ async def login(
786
+ request: Request,
787
+ db: DbSession,
788
+ email: Annotated[str, Form()],
789
+ password: Annotated[str, Form()],
790
+ ):
791
+ """Handle login form submission."""
792
+ user = User.authenticate(db, email, password)
793
+
794
+ if user:
795
+ is_new_user = user.record_login(db)
796
+ with new_context():
797
+ identify_context(user.email)
798
+ capture(
799
+ "user_logged_in",
800
+ properties={
801
+ "$set": {"email": user.email, "is_staff": user.is_staff},
802
+ "username": user.email,
803
+ "is_new_user": is_new_user,
804
+ },
805
+ )
806
+
807
+ # Create session and redirect
808
+ response = RedirectResponse(url="/dashboard", status_code=302)
809
+ response.set_cookie(
810
+ key="session_token",
811
+ value=create_session_token(user.id),
812
+ httponly=True,
813
+ samesite="lax",
814
+ )
815
+ return response
816
+
817
+ # Login failed
818
+ return templates.TemplateResponse(
819
+ request,
820
+ "home.html",
821
+ {"current_user": None, "error": "Invalid email or password"},
822
+ )
823
+
824
+
825
+ @router.get("/signup", response_class=HTMLResponse)
826
+ async def signup_page(request: Request, current_user: CurrentUser):
827
+ """User registration page."""
828
+ if current_user:
829
+ return RedirectResponse(url="/dashboard", status_code=302)
830
+
831
+ return templates.TemplateResponse(
832
+ request, "signup.html", {"current_user": current_user}
833
+ )
834
+
835
+
836
+ @router.post("/signup", response_class=HTMLResponse)
837
+ async def signup(
838
+ request: Request,
839
+ db: DbSession,
840
+ email: Annotated[str, Form()],
841
+ password: Annotated[str, Form()],
842
+ password_confirm: Annotated[str, Form()],
843
+ ):
844
+ """Handle signup form submission."""
845
+ error = None
846
+
847
+ if not email or not password:
848
+ error = "Email and password are required"
849
+ elif password != password_confirm:
850
+ error = "Passwords do not match"
851
+ elif User.get_by_email(db, email):
852
+ error = "Email already registered"
853
+
854
+ if error:
855
+ return templates.TemplateResponse(
856
+ request, "signup.html", {"current_user": None, "error": error}
857
+ )
858
+
859
+ # Create new user
860
+ user = User.create_user(db, email=email, password=password, is_staff=False)
861
+
862
+ with new_context():
863
+ identify_context(user.email)
864
+ capture(
865
+ "user_signed_up",
866
+ properties={
867
+ "$set": {"email": user.email, "is_staff": user.is_staff},
868
+ "username": user.email,
869
+ "signup_method": "form",
870
+ },
871
+ )
872
+
873
+ # Create session and redirect
874
+ response = RedirectResponse(url="/dashboard", status_code=302)
875
+ response.set_cookie(
876
+ key="session_token",
877
+ value=create_session_token(user.id),
878
+ httponly=True,
879
+ samesite="lax",
880
+ )
881
+ return response
882
+
883
+
884
+ @router.get("/logout")
885
+ async def logout(current_user: RequiredUser):
886
+ """Logout and capture event."""
887
+ capture("user_logged_out")
888
+
889
+ response = RedirectResponse(url="/", status_code=302)
890
+ response.delete_cookie(key="session_token")
891
+ return response
892
+
893
+
894
+ @router.get("/dashboard", response_class=HTMLResponse)
895
+ async def dashboard(
896
+ request: Request,
897
+ current_user: RequiredUser,
898
+ ):
899
+ """Dashboard with feature flag demonstration."""
900
+ capture("dashboard_viewed", properties={"is_staff": current_user.is_staff})
901
+
902
+ # Check feature flag
903
+ show_new_feature = posthog.feature_enabled(
904
+ "new-dashboard-feature",
905
+ current_user.email,
906
+ person_properties={
907
+ "email": current_user.email,
908
+ "is_staff": current_user.is_staff,
909
+ },
910
+ )
911
+
912
+ # Get feature flag payload
913
+ feature_config = posthog.get_feature_flag_payload(
914
+ "new-dashboard-feature", current_user.email
915
+ )
916
+
917
+ return templates.TemplateResponse(
918
+ request,
919
+ "dashboard.html",
920
+ {
921
+ "current_user": current_user,
922
+ "show_new_feature": show_new_feature,
923
+ "feature_config": feature_config,
924
+ },
925
+ )
926
+
927
+
928
+ @router.get("/burrito", response_class=HTMLResponse)
929
+ async def burrito(
930
+ request: Request,
931
+ current_user: RequiredUser,
932
+ burrito_count: Annotated[int, Cookie()] = 0,
933
+ ):
934
+ """Burrito consideration tracker page."""
935
+ return templates.TemplateResponse(
936
+ request,
937
+ "burrito.html",
938
+ {"current_user": current_user, "burrito_count": burrito_count},
939
+ )
940
+
941
+
942
+ @router.get("/profile", response_class=HTMLResponse)
943
+ async def profile(request: Request, current_user: RequiredUser):
944
+ """User profile page."""
945
+ capture("profile_viewed")
946
+
947
+ return templates.TemplateResponse(
948
+ request, "profile.html", {"current_user": current_user}
949
+ )
950
+
951
+
952
+ @router.post("/profile", response_class=HTMLResponse)
953
+ async def update_profile(
954
+ request: Request,
955
+ db: DbSession,
956
+ current_user: RequiredUser,
957
+ name: Annotated[str, Form()],
958
+ ):
959
+ """Handle profile update."""
960
+ fields_changed = current_user.update_profile(db, name=name)
961
+
962
+ if fields_changed:
963
+ capture(
964
+ "profile_updated",
965
+ properties={
966
+ "username": current_user.email,
967
+ "fields_changed": fields_changed,
968
+ },
969
+ )
970
+
971
+ return templates.TemplateResponse(
972
+ request,
973
+ "profile.html",
974
+ {
975
+ "current_user": current_user,
976
+ "success": "Profile updated" if fields_changed else None,
977
+ },
978
+ )
979
+
980
+ ```
981
+
982
+ ---
983
+
984
+ ## app/templates/base.html
985
+
986
+ ```html
987
+ <!DOCTYPE html>
988
+ <html lang="en">
989
+ <head>
990
+ <meta charset="UTF-8">
991
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
992
+ <title>{% block title %}PostHog FastAPI Example{% endblock %}</title>
993
+ <style>
994
+ * {
995
+ box-sizing: border-box;
996
+ margin: 0;
997
+ padding: 0;
998
+ }
999
+ body {
1000
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
1001
+ line-height: 1.6;
1002
+ background-color: #f5f5f5;
1003
+ color: #333;
1004
+ }
1005
+ .container {
1006
+ max-width: 800px;
1007
+ margin: 0 auto;
1008
+ padding: 20px;
1009
+ }
1010
+ nav {
1011
+ background: #1d4ed8;
1012
+ padding: 15px 20px;
1013
+ margin-bottom: 30px;
1014
+ }
1015
+ nav a {
1016
+ color: white;
1017
+ text-decoration: none;
1018
+ margin-right: 20px;
1019
+ }
1020
+ nav a:hover {
1021
+ text-decoration: underline;
1022
+ }
1023
+ .card {
1024
+ background: white;
1025
+ border-radius: 8px;
1026
+ padding: 20px;
1027
+ margin-bottom: 20px;
1028
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
1029
+ }
1030
+ h1, h2, h3 {
1031
+ margin-bottom: 15px;
1032
+ color: #1d4ed8;
1033
+ }
1034
+ button, .btn {
1035
+ background: #1d4ed8;
1036
+ color: white;
1037
+ border: none;
1038
+ padding: 10px 20px;
1039
+ border-radius: 5px;
1040
+ cursor: pointer;
1041
+ font-size: 14px;
1042
+ display: inline-block;
1043
+ text-decoration: none;
1044
+ }
1045
+ button:hover, .btn:hover {
1046
+ background: #1e40af;
1047
+ }
1048
+ button.danger {
1049
+ background: #dc2626;
1050
+ }
1051
+ button.danger:hover {
1052
+ background: #b91c1c;
1053
+ }
1054
+ input {
1055
+ width: 100%;
1056
+ padding: 10px;
1057
+ margin-bottom: 15px;
1058
+ border: 1px solid #ddd;
1059
+ border-radius: 5px;
1060
+ font-size: 14px;
1061
+ }
1062
+ .messages {
1063
+ margin-bottom: 20px;
1064
+ }
1065
+ .message {
1066
+ padding: 10px 15px;
1067
+ border-radius: 5px;
1068
+ margin-bottom: 10px;
1069
+ }
1070
+ .message.error {
1071
+ background: #fee2e2;
1072
+ color: #dc2626;
1073
+ }
1074
+ .message.success {
1075
+ background: #d1fae5;
1076
+ color: #059669;
1077
+ }
1078
+ .feature-flag {
1079
+ background: #fef3c7;
1080
+ border: 2px dashed #f59e0b;
1081
+ padding: 15px;
1082
+ border-radius: 8px;
1083
+ margin: 20px 0;
1084
+ }
1085
+ code {
1086
+ background: #f3f4f6;
1087
+ padding: 2px 6px;
1088
+ border-radius: 3px;
1089
+ font-family: monospace;
1090
+ }
1091
+ pre {
1092
+ background: #1e293b;
1093
+ color: #e2e8f0;
1094
+ padding: 16px;
1095
+ border-radius: 8px;
1096
+ overflow-x: auto;
1097
+ font-size: 13px;
1098
+ }
1099
+ .count {
1100
+ font-size: 48px;
1101
+ font-weight: bold;
1102
+ color: #1d4ed8;
1103
+ text-align: center;
1104
+ padding: 20px;
1105
+ }
1106
+ table {
1107
+ width: 100%;
1108
+ border-collapse: collapse;
1109
+ margin: 16px 0;
1110
+ }
1111
+ th, td {
1112
+ padding: 12px;
1113
+ text-align: left;
1114
+ border-bottom: 1px solid #eee;
1115
+ }
1116
+ th {
1117
+ background: #f8fafc;
1118
+ font-weight: 600;
1119
+ }
1120
+ </style>
1121
+ </head>
1122
+ <body>
1123
+ {% if current_user %}
1124
+ <nav>
1125
+ <a href="/dashboard">Dashboard</a>
1126
+ <a href="/burrito">Burrito</a>
1127
+ <a href="/profile">Profile</a>
1128
+ <a href="/logout" style="float: right;">Logout ({{ current_user.email }})</a>
1129
+ </nav>
1130
+ {% endif %}
1131
+
1132
+ <div class="container">
1133
+ {% if error %}
1134
+ <div class="messages">
1135
+ <div class="message error">{{ error }}</div>
1136
+ </div>
1137
+ {% endif %}
1138
+ {% if success %}
1139
+ <div class="messages">
1140
+ <div class="message success">{{ success }}</div>
1141
+ </div>
1142
+ {% endif %}
1143
+
1144
+ {% block content %}{% endblock %}
1145
+ </div>
1146
+
1147
+ {% block scripts %}{% endblock %}
1148
+ </body>
1149
+ </html>
1150
+
1151
+ ```
1152
+
1153
+ ---
1154
+
1155
+ ## app/templates/burrito.html
1156
+
1157
+ ```html
1158
+ {% extends "base.html" %}
1159
+
1160
+ {% block title %}Burrito - PostHog FastAPI Example{% endblock %}
1161
+
1162
+ {% block content %}
1163
+ <div class="card">
1164
+ <h1>Burrito Consideration Tracker</h1>
1165
+ <p>This page demonstrates custom event tracking with PostHog.</p>
1166
+
1167
+ <div class="count" id="burrito-count">{{ burrito_count }}</div>
1168
+ <p style="text-align: center; color: #666;">Times you've considered a burrito</p>
1169
+
1170
+ <div style="text-align: center; margin-top: 20px;">
1171
+ <button onclick="considerBurrito()">Consider a Burrito</button>
1172
+ </div>
1173
+ </div>
1174
+
1175
+ <div class="card">
1176
+ <h3>Code Example</h3>
1177
+ <pre>
1178
+ # API endpoint captures the event
1179
+ with new_context():
1180
+ identify_context(current_user.email)
1181
+ capture('burrito_considered', properties={
1182
+ 'total_considerations': burrito_count
1183
+ })</pre>
1184
+ </div>
1185
+ {% endblock %}
1186
+
1187
+ {% block scripts %}
1188
+ <script>
1189
+ async function considerBurrito() {
1190
+ try {
1191
+ const response = await fetch('/api/burrito/consider', {
1192
+ method: 'POST',
1193
+ headers: {
1194
+ 'Content-Type': 'application/json'
1195
+ }
1196
+ });
1197
+ const data = await response.json();
1198
+ if (data.success) {
1199
+ document.getElementById('burrito-count').textContent = data.count;
1200
+ }
1201
+ } catch (error) {
1202
+ console.error('Error:', error);
1203
+ }
1204
+ }
1205
+ </script>
1206
+ {% endblock %}
1207
+
1208
+ ```
1209
+
1210
+ ---
1211
+
1212
+ ## app/templates/dashboard.html
1213
+
1214
+ ```html
1215
+ {% extends "base.html" %}
1216
+
1217
+ {% block title %}Dashboard - PostHog FastAPI Example{% endblock %}
1218
+
1219
+ {% block content %}
1220
+ <div class="card">
1221
+ <h1>Dashboard</h1>
1222
+ <p>Welcome back, {{ current_user.email }}!</p>
1223
+ </div>
1224
+
1225
+ <div class="card">
1226
+ <h2>Feature Flags</h2>
1227
+
1228
+ {% if show_new_feature %}
1229
+ <div class="feature-flag">
1230
+ <strong>New Feature Enabled!</strong>
1231
+ <p>You're seeing this because the <code>new-dashboard-feature</code> flag is enabled for you.</p>
1232
+ {% if feature_config %}
1233
+ <p><strong>Feature Configuration:</strong></p>
1234
+ <pre>{{ feature_config | tojson(indent=2) }}</pre>
1235
+ {% endif %}
1236
+ </div>
1237
+ {% else %}
1238
+ <p>The <code>new-dashboard-feature</code> flag is not enabled for your account.</p>
1239
+ {% endif %}
1240
+
1241
+ <h3 style="margin-top: 20px;">Code Example</h3>
1242
+ <pre>
1243
+ # Check if feature flag is enabled
1244
+ show_new_feature = posthog.feature_enabled(
1245
+ 'new-dashboard-feature',
1246
+ user_id,
1247
+ person_properties={
1248
+ 'email': current_user.email,
1249
+ 'is_staff': current_user.is_staff
1250
+ }
1251
+ )
1252
+
1253
+ # Get feature flag payload
1254
+ feature_config = posthog.get_feature_flag_payload(
1255
+ 'new-dashboard-feature',
1256
+ user_id
1257
+ )</pre>
1258
+ </div>
1259
+ {% endblock %}
1260
+
1261
+ ```
1262
+
1263
+ ---
1264
+
1265
+ ## app/templates/errors/404.html
1266
+
1267
+ ```html
1268
+ {% extends "base.html" %}
1269
+
1270
+ {% block title %}Page Not Found - PostHog FastAPI Example{% endblock %}
1271
+
1272
+ {% block content %}
1273
+ <div class="card">
1274
+ <h1>404 - Page Not Found</h1>
1275
+ <p>The page you're looking for doesn't exist.</p>
1276
+ <a href="/" class="btn">Go Home</a>
1277
+ </div>
1278
+ {% endblock %}
1279
+
1280
+ ```
1281
+
1282
+ ---
1283
+
1284
+ ## app/templates/errors/500.html
1285
+
1286
+ ```html
1287
+ {% extends "base.html" %}
1288
+
1289
+ {% block title %}Server Error - PostHog FastAPI Example{% endblock %}
1290
+
1291
+ {% block content %}
1292
+ <div class="card">
1293
+ <h1>500 - Internal Server Error</h1>
1294
+ <p>Something went wrong on our end. Please try again later.</p>
1295
+ <a href="/" class="btn">Go Home</a>
1296
+ </div>
1297
+ {% endblock %}
1298
+
1299
+ ```
1300
+
1301
+ ---
1302
+
1303
+ ## app/templates/home.html
1304
+
1305
+ ```html
1306
+ {% extends "base.html" %}
1307
+
1308
+ {% block title %}Login - PostHog FastAPI Example{% endblock %}
1309
+
1310
+ {% block content %}
1311
+ <div class="card">
1312
+ <h1>Welcome to PostHog FastAPI Example</h1>
1313
+ <p>This example demonstrates how to integrate PostHog with a FastAPI application.</p>
1314
+
1315
+ <form method="POST">
1316
+ <label for="email">Email</label>
1317
+ <input type="email" id="email" name="email" required>
1318
+
1319
+ <label for="password">Password</label>
1320
+ <input type="password" id="password" name="password" required>
1321
+
1322
+ <button type="submit">Login</button>
1323
+ </form>
1324
+
1325
+ <p style="margin-top: 16px; font-size: 14px; color: #666;">
1326
+ Don't have an account? <a href="/signup">Sign up here</a>
1327
+ </p>
1328
+ <p style="font-size: 14px; color: #666;">
1329
+ <strong>Tip:</strong> Default credentials are admin@example.com/admin
1330
+ </p>
1331
+ </div>
1332
+
1333
+ <div class="card">
1334
+ <h2>Features Demonstrated</h2>
1335
+ <ul style="margin-left: 20px; color: #666;">
1336
+ <li>User registration and identification</li>
1337
+ <li>Event tracking</li>
1338
+ <li>Feature flags</li>
1339
+ <li>Error tracking</li>
1340
+ <li>Group analytics</li>
1341
+ </ul>
1342
+ </div>
1343
+ {% endblock %}
1344
+
1345
+ ```
1346
+
1347
+ ---
1348
+
1349
+ ## app/templates/profile.html
1350
+
1351
+ ```html
1352
+ {% extends "base.html" %}
1353
+
1354
+ {% block title %}Profile - PostHog FastAPI Example{% endblock %}
1355
+
1356
+ {% block content %}
1357
+ <div class="card">
1358
+ <h1>Your Profile</h1>
1359
+ <p>This page demonstrates profile updates and report generation with PostHog.</p>
1360
+
1361
+ {% if success %}
1362
+ <div class="message success">{{ success }}</div>
1363
+ {% endif %}
1364
+
1365
+ <form method="POST" action="/profile">
1366
+ <table>
1367
+ <tr>
1368
+ <th>Email</th>
1369
+ <td>{{ current_user.email }}</td>
1370
+ </tr>
1371
+ <tr>
1372
+ <th>Name</th>
1373
+ <td>
1374
+ <input type="text" name="name" value="{{ current_user.name or '' }}" placeholder="Enter your name">
1375
+ </td>
1376
+ </tr>
1377
+ <tr>
1378
+ <th>Date Joined</th>
1379
+ <td>{{ current_user.date_joined.strftime('%Y-%m-%d %H:%M') }}</td>
1380
+ </tr>
1381
+ <tr>
1382
+ <th>Login Count</th>
1383
+ <td>{{ current_user.login_count }}</td>
1384
+ </tr>
1385
+ <tr>
1386
+ <th>Staff Status</th>
1387
+ <td>{{ 'Yes' if current_user.is_staff else 'No' }}</td>
1388
+ </tr>
1389
+ </table>
1390
+ <button type="submit">Update Profile</button>
1391
+ </form>
1392
+ </div>
1393
+
1394
+ <div class="card">
1395
+ <h2>Activity Reports</h2>
1396
+ <p>Generate a report of your account activity:</p>
1397
+
1398
+ <div style="margin: 20px 0;">
1399
+ <button onclick="generateReport('summary')">Summary Report</button>
1400
+ <button onclick="generateReport('detailed')">Detailed Report</button>
1401
+ </div>
1402
+
1403
+ <div id="report-result" style="display: none;" class="message"></div>
1404
+ </div>
1405
+
1406
+ <div class="card">
1407
+ <h2>Error Tracking Demo</h2>
1408
+ <p>Click a button to trigger an error and see it captured in PostHog:</p>
1409
+
1410
+ <div style="margin: 20px 0;">
1411
+ <button class="danger" onclick="triggerError('value')">
1412
+ Trigger ValueError
1413
+ </button>
1414
+ <button class="danger" onclick="triggerError('key')">
1415
+ Trigger KeyError
1416
+ </button>
1417
+ <button class="danger" onclick="triggerError('generic')">
1418
+ Trigger Generic Error
1419
+ </button>
1420
+ </div>
1421
+
1422
+ <div id="error-result" style="display: none;" class="message"></div>
1423
+ </div>
1424
+
1425
+ <div class="card">
1426
+ <h3>Code Example</h3>
1427
+ <pre>
1428
+ try:
1429
+ raise ValueError('Invalid value provided')
1430
+ except Exception as e:
1431
+ # Capture exception and event with user context
1432
+ with new_context():
1433
+ identify_context(current_user.email)
1434
+ posthog.capture_exception(e)
1435
+ capture('error_triggered', properties={
1436
+ 'error_type': 'value',
1437
+ 'error_message': str(e)
1438
+ })</pre>
1439
+ </div>
1440
+ {% endblock %}
1441
+
1442
+ {% block scripts %}
1443
+ <script>
1444
+ async function triggerError(errorType) {
1445
+ const resultDiv = document.getElementById('error-result');
1446
+ try {
1447
+ const formData = new FormData();
1448
+ formData.append('error_type', errorType);
1449
+
1450
+ const response = await fetch('/api/trigger-error', {
1451
+ method: 'POST',
1452
+ body: formData
1453
+ });
1454
+ const data = await response.json();
1455
+
1456
+ resultDiv.style.display = 'block';
1457
+ resultDiv.className = 'message ' + (data.success ? 'success' : 'error');
1458
+ resultDiv.textContent = data.message + ': ' + data.error;
1459
+ } catch (error) {
1460
+ console.error('Error:', error);
1461
+ resultDiv.style.display = 'block';
1462
+ resultDiv.className = 'message error';
1463
+ resultDiv.textContent = 'Request failed: ' + error.message;
1464
+ }
1465
+ }
1466
+
1467
+ async function generateReport(reportType) {
1468
+ const resultDiv = document.getElementById('report-result');
1469
+ try {
1470
+ const formData = new FormData();
1471
+ formData.append('report_type', reportType);
1472
+
1473
+ const response = await fetch('/api/reports/activity', {
1474
+ method: 'POST',
1475
+ body: formData
1476
+ });
1477
+ const data = await response.json();
1478
+
1479
+ resultDiv.style.display = 'block';
1480
+ resultDiv.className = 'message success';
1481
+ resultDiv.innerHTML = '<strong>' + data.report_type + ' report generated</strong> (' + data.row_count + ' rows)<br><pre>' + JSON.stringify(data.data, null, 2) + '</pre>';
1482
+ } catch (error) {
1483
+ console.error('Error:', error);
1484
+ resultDiv.style.display = 'block';
1485
+ resultDiv.className = 'message error';
1486
+ resultDiv.textContent = 'Request failed: ' + error.message;
1487
+ }
1488
+ }
1489
+ </script>
1490
+ {% endblock %}
1491
+
1492
+ ```
1493
+
1494
+ ---
1495
+
1496
+ ## app/templates/signup.html
1497
+
1498
+ ```html
1499
+ {% extends "base.html" %}
1500
+
1501
+ {% block title %}Sign Up - PostHog FastAPI Example{% endblock %}
1502
+
1503
+ {% block content %}
1504
+ <div class="card">
1505
+ <h1>Create an Account</h1>
1506
+ <p>Sign up to explore the PostHog FastAPI integration example.</p>
1507
+
1508
+ <form method="POST">
1509
+ <label for="email">Email *</label>
1510
+ <input type="email" id="email" name="email" required>
1511
+
1512
+ <label for="password">Password *</label>
1513
+ <input type="password" id="password" name="password" required>
1514
+
1515
+ <label for="password_confirm">Confirm Password *</label>
1516
+ <input type="password" id="password_confirm" name="password_confirm" required>
1517
+
1518
+ <button type="submit">Sign Up</button>
1519
+ </form>
1520
+
1521
+ <p style="margin-top: 16px; font-size: 14px; color: #666;">
1522
+ Already have an account? <a href="/">Login here</a>
1523
+ </p>
1524
+ </div>
1525
+
1526
+ <div class="card">
1527
+ <h2>PostHog Integration</h2>
1528
+ <p>When you sign up, the following PostHog events are captured:</p>
1529
+ <ul style="margin-left: 20px; color: #666;">
1530
+ <li><code>identify_context()</code> - Associates your email with the context</li>
1531
+ <li><code>tag()</code> - Sets person properties (email, etc.)</li>
1532
+ <li><code>user_signed_up</code> event - Tracks the signup action</li>
1533
+ </ul>
1534
+
1535
+ <h3 style="margin-top: 20px;">Code Example</h3>
1536
+ <pre>
1537
+ # After creating the user
1538
+ with new_context():
1539
+ identify_context(user.email)
1540
+
1541
+ tag('email', user.email)
1542
+ tag('is_staff', user.is_staff)
1543
+ tag('date_joined', user.date_joined.isoformat())
1544
+
1545
+ capture('user_signed_up', properties={'signup_method': 'form'})</pre>
1546
+ </div>
1547
+ {% endblock %}
1548
+
1549
+ ```
1550
+
1551
+ ---
1552
+
1553
+ ## requirements.txt
1554
+
1555
+ ```txt
1556
+ fastapi>=0.109.0
1557
+ uvicorn>=0.27.0
1558
+ sqlalchemy>=2.0.0
1559
+ python-dotenv>=1.0.0
1560
+ posthog>=3.0.0
1561
+ pydantic>=2.0.0
1562
+ pydantic-settings>=2.0.0
1563
+ jinja2>=3.0.0
1564
+ python-multipart>=0.0.9
1565
+ werkzeug>=3.0.0
1566
+ itsdangerous>=2.0.0
1567
+
1568
+ ```
1569
+
1570
+ ---
1571
+
1572
+ ## run.py
1573
+
1574
+ ```py
1575
+ """Development server entry point."""
1576
+
1577
+ import uvicorn
1578
+
1579
+ if __name__ == "__main__":
1580
+ uvicorn.run("app.main:app", host="0.0.0.0", port=5002, reload=True)
1581
+
1582
+ ```
1583
+
1584
+ ---
1585
+