@amplitude/wizard 1.0.0-beta.2 → 1.0.0-beta.5

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 (391) hide show
  1. package/README.md +171 -74
  2. package/dist/bin.js +338 -222
  3. package/dist/src/lib/agent-interface.js +64 -9
  4. package/dist/src/lib/agent-runner.js +1 -10
  5. package/dist/src/lib/api.d.ts +22 -4
  6. package/dist/src/lib/api.js +114 -12
  7. package/dist/src/lib/commandments.js +14 -1
  8. package/dist/src/lib/constants.d.ts +5 -4
  9. package/dist/src/lib/constants.js +9 -11
  10. package/dist/src/lib/credential-resolution.d.ts +45 -0
  11. package/dist/src/lib/credential-resolution.js +311 -0
  12. package/dist/src/lib/exit-codes.d.ts +10 -0
  13. package/dist/src/lib/exit-codes.js +12 -0
  14. package/dist/src/lib/health-checks/statuspage.d.ts +1 -0
  15. package/dist/src/lib/health-checks/statuspage.js +5 -1
  16. package/dist/src/lib/mode-config.d.ts +14 -0
  17. package/dist/src/lib/mode-config.js +14 -0
  18. package/dist/src/lib/session-checkpoint.d.ts +27 -0
  19. package/dist/src/lib/session-checkpoint.js +134 -0
  20. package/dist/src/lib/wizard-session.d.ts +44 -1
  21. package/dist/src/lib/wizard-session.js +70 -14
  22. package/dist/src/lib/wizard-tools.js +19 -4
  23. package/dist/src/steps/add-mcp-server-to-clients/clients/claude.d.ts +3 -0
  24. package/dist/src/steps/add-mcp-server-to-clients/clients/claude.js +6 -0
  25. package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.js +3 -1
  26. package/dist/src/ui/agent-ui.d.ts +91 -0
  27. package/dist/src/ui/agent-ui.js +277 -0
  28. package/dist/src/ui/logging-ui.js +1 -1
  29. package/dist/src/ui/tui/App.d.ts +12 -0
  30. package/dist/src/ui/tui/App.js +29 -18
  31. package/dist/src/ui/tui/components/AmplitudeLogo.js +16 -17
  32. package/dist/src/ui/tui/components/AmplitudeTextLogo.d.ts +0 -2
  33. package/dist/src/ui/tui/components/AmplitudeTextLogo.js +53 -18
  34. package/dist/src/ui/tui/components/BrailleSpinner.d.ts +8 -0
  35. package/dist/src/ui/tui/components/BrailleSpinner.js +15 -0
  36. package/dist/src/ui/tui/components/ConsoleView.d.ts +8 -11
  37. package/dist/src/ui/tui/components/ConsoleView.js +51 -34
  38. package/dist/src/ui/tui/components/HeaderBar.d.ts +12 -0
  39. package/dist/src/ui/tui/components/HeaderBar.js +17 -0
  40. package/dist/src/ui/tui/components/JourneyStepper.d.ts +16 -0
  41. package/dist/src/ui/tui/components/JourneyStepper.js +83 -0
  42. package/dist/src/ui/tui/components/KeyHintBar.d.ts +19 -0
  43. package/dist/src/ui/tui/components/KeyHintBar.js +20 -0
  44. package/dist/src/ui/tui/console-commands.d.ts +1 -2
  45. package/dist/src/ui/tui/console-commands.js +48 -7
  46. package/dist/src/ui/tui/flows.d.ts +1 -1
  47. package/dist/src/ui/tui/flows.js +1 -1
  48. package/dist/src/ui/tui/hooks/useAsyncEffect.d.ts +15 -0
  49. package/dist/src/ui/tui/hooks/useAsyncEffect.js +35 -0
  50. package/dist/src/ui/tui/hooks/useWizardStore.d.ts +9 -0
  51. package/dist/src/ui/tui/hooks/useWizardStore.js +11 -0
  52. package/dist/src/ui/tui/ink-ui.js +1 -1
  53. package/dist/src/ui/tui/primitives/DissolveTransition.js +4 -5
  54. package/dist/src/ui/tui/primitives/EventPlanViewer.d.ts +3 -1
  55. package/dist/src/ui/tui/primitives/EventPlanViewer.js +8 -3
  56. package/dist/src/ui/tui/primitives/ProgressList.js +1 -1
  57. package/dist/src/ui/tui/primitives/SlashCommandInput.js +19 -4
  58. package/dist/src/ui/tui/primitives/SplitView.d.ts +2 -1
  59. package/dist/src/ui/tui/primitives/SplitView.js +10 -2
  60. package/dist/src/ui/tui/primitives/TabContainer.js +10 -2
  61. package/dist/src/ui/tui/primitives/index.d.ts +0 -1
  62. package/dist/src/ui/tui/primitives/index.js +0 -1
  63. package/dist/src/ui/tui/router.js +1 -1
  64. package/dist/src/ui/tui/screen-registry.d.ts +0 -7
  65. package/dist/src/ui/tui/screen-registry.js +13 -4
  66. package/dist/src/ui/tui/screens/ActivationOptionsScreen.d.ts +2 -2
  67. package/dist/src/ui/tui/screens/ActivationOptionsScreen.js +8 -8
  68. package/dist/src/ui/tui/screens/AuthScreen.js +57 -27
  69. package/dist/src/ui/tui/screens/ChecklistScreen.d.ts +2 -12
  70. package/dist/src/ui/tui/screens/ChecklistScreen.js +22 -33
  71. package/dist/src/ui/tui/screens/DataIngestionCheckScreen.d.ts +3 -12
  72. package/dist/src/ui/tui/screens/DataIngestionCheckScreen.js +109 -39
  73. package/dist/src/ui/tui/screens/DataSetupScreen.d.ts +3 -3
  74. package/dist/src/ui/tui/screens/DataSetupScreen.js +17 -10
  75. package/dist/src/ui/tui/screens/IntroScreen.d.ts +5 -3
  76. package/dist/src/ui/tui/screens/IntroScreen.js +132 -41
  77. package/dist/src/ui/tui/screens/LoginScreen.d.ts +1 -1
  78. package/dist/src/ui/tui/screens/LoginScreen.js +4 -4
  79. package/dist/src/ui/tui/screens/LogoutScreen.d.ts +4 -2
  80. package/dist/src/ui/tui/screens/LogoutScreen.js +17 -5
  81. package/dist/src/ui/tui/screens/McpScreen.d.ts +4 -4
  82. package/dist/src/ui/tui/screens/McpScreen.js +25 -17
  83. package/dist/src/ui/tui/screens/OutageScreen.d.ts +1 -1
  84. package/dist/src/ui/tui/screens/OutageScreen.js +5 -5
  85. package/dist/src/ui/tui/screens/OutroScreen.d.ts +5 -0
  86. package/dist/src/ui/tui/screens/OutroScreen.js +21 -14
  87. package/dist/src/ui/tui/screens/RegionSelectScreen.js +15 -13
  88. package/dist/src/ui/tui/screens/RunScreen.d.ts +7 -5
  89. package/dist/src/ui/tui/screens/RunScreen.js +102 -157
  90. package/dist/src/ui/tui/screens/SettingsOverrideScreen.d.ts +1 -1
  91. package/dist/src/ui/tui/screens/SettingsOverrideScreen.js +6 -5
  92. package/dist/src/ui/tui/screens/SetupScreen.d.ts +1 -1
  93. package/dist/src/ui/tui/screens/SetupScreen.js +7 -7
  94. package/dist/src/ui/tui/screens/SlackScreen.d.ts +2 -2
  95. package/dist/src/ui/tui/screens/SlackScreen.js +60 -35
  96. package/dist/src/ui/tui/session-constants.d.ts +41 -0
  97. package/dist/src/ui/tui/session-constants.js +38 -0
  98. package/dist/src/ui/tui/start-tui.d.ts +3 -1
  99. package/dist/src/ui/tui/start-tui.js +14 -10
  100. package/dist/src/ui/tui/store.d.ts +2 -1
  101. package/dist/src/ui/tui/store.js +33 -7
  102. package/dist/src/ui/tui/styles.d.ts +75 -19
  103. package/dist/src/ui/tui/styles.js +101 -19
  104. package/dist/src/ui/tui/utils/classify-error.d.ts +14 -0
  105. package/dist/src/ui/tui/utils/classify-error.js +90 -0
  106. package/dist/src/ui/tui/utils/diagnostics.d.ts +21 -0
  107. package/dist/src/ui/tui/utils/diagnostics.js +72 -0
  108. package/dist/src/ui/tui/utils/with-retry.d.ts +12 -0
  109. package/dist/src/ui/tui/utils/with-retry.js +32 -0
  110. package/dist/src/ui/tui/utils/with-timeout.d.ts +10 -0
  111. package/dist/src/ui/tui/utils/with-timeout.js +24 -0
  112. package/dist/src/utils/ampli-settings.d.ts +1 -1
  113. package/dist/src/utils/ampli-settings.js +15 -5
  114. package/dist/src/utils/api-key-store.js +5 -5
  115. package/dist/src/utils/atomic-write.d.ts +15 -0
  116. package/dist/src/utils/atomic-write.js +34 -0
  117. package/dist/src/utils/setup-utils.js +2 -2
  118. package/dist/src/utils/token-refresh.d.ts +22 -0
  119. package/dist/src/utils/token-refresh.js +79 -0
  120. package/dist/src/utils/wizard-abort.js +6 -1
  121. package/package.json +5 -5
  122. package/skills/instrumentation/add-analytics-instrumentation/SKILL.md +142 -0
  123. package/skills/instrumentation/diff-intake/SKILL.md +128 -0
  124. package/skills/instrumentation/discover-analytics-patterns/SKILL.md +185 -0
  125. package/skills/instrumentation/discover-event-surfaces/SKILL.md +322 -0
  126. package/skills/instrumentation/discover-event-surfaces/references/best-practices.md +563 -0
  127. package/skills/instrumentation/instrument-events/SKILL.md +169 -0
  128. package/skills/instrumentation/instrument-events/references/best-practices.md +563 -0
  129. package/skills/integration/integration-android/SKILL.md +49 -0
  130. package/skills/integration/integration-android/references/EXAMPLE.md +1977 -0
  131. package/skills/integration/integration-android/references/amplitude-quickstart.md +1845 -0
  132. package/skills/integration/integration-android/references/analytics.md +1778 -0
  133. package/skills/integration/integration-android/references/basic-integration-1.0-begin.md +43 -0
  134. package/skills/integration/integration-android/references/basic-integration-1.1-edit.md +35 -0
  135. package/skills/integration/integration-android/references/basic-integration-1.2-revise.md +23 -0
  136. package/skills/integration/integration-android/references/basic-integration-1.3-conclude.md +57 -0
  137. package/skills/integration/integration-angular/SKILL.md +49 -0
  138. package/skills/integration/integration-angular/references/EXAMPLE.md +899 -0
  139. package/skills/integration/integration-angular/references/amplitude-quickstart.md +1845 -0
  140. package/skills/integration/integration-angular/references/basic-integration-1.0-begin.md +43 -0
  141. package/skills/integration/integration-angular/references/basic-integration-1.1-edit.md +35 -0
  142. package/skills/integration/integration-angular/references/basic-integration-1.2-revise.md +23 -0
  143. package/skills/integration/integration-angular/references/basic-integration-1.3-conclude.md +57 -0
  144. package/skills/integration/integration-angular/references/browser-sdk-2.md +4680 -0
  145. package/skills/integration/integration-astro-hybrid/SKILL.md +56 -0
  146. package/skills/integration/integration-astro-hybrid/references/EXAMPLE.md +1095 -0
  147. package/skills/integration/integration-astro-hybrid/references/amplitude-quickstart.md +1845 -0
  148. package/skills/integration/integration-astro-hybrid/references/basic-integration-1.0-begin.md +43 -0
  149. package/skills/integration/integration-astro-hybrid/references/basic-integration-1.1-edit.md +35 -0
  150. package/skills/integration/integration-astro-hybrid/references/basic-integration-1.2-revise.md +23 -0
  151. package/skills/integration/integration-astro-hybrid/references/basic-integration-1.3-conclude.md +57 -0
  152. package/skills/integration/integration-astro-hybrid/references/browser-sdk-2.md +4680 -0
  153. package/skills/integration/integration-astro-ssr/SKILL.md +52 -0
  154. package/skills/integration/integration-astro-ssr/references/EXAMPLE.md +1106 -0
  155. package/skills/integration/integration-astro-ssr/references/amplitude-quickstart.md +1845 -0
  156. package/skills/integration/integration-astro-ssr/references/basic-integration-1.0-begin.md +43 -0
  157. package/skills/integration/integration-astro-ssr/references/basic-integration-1.1-edit.md +35 -0
  158. package/skills/integration/integration-astro-ssr/references/basic-integration-1.2-revise.md +23 -0
  159. package/skills/integration/integration-astro-ssr/references/basic-integration-1.3-conclude.md +57 -0
  160. package/skills/integration/integration-astro-ssr/references/browser-sdk-2.md +4680 -0
  161. package/skills/integration/integration-astro-static/SKILL.md +49 -0
  162. package/skills/integration/integration-astro-static/references/EXAMPLE.md +910 -0
  163. package/skills/integration/integration-astro-static/references/amplitude-quickstart.md +1845 -0
  164. package/skills/integration/integration-astro-static/references/basic-integration-1.0-begin.md +43 -0
  165. package/skills/integration/integration-astro-static/references/basic-integration-1.1-edit.md +35 -0
  166. package/skills/integration/integration-astro-static/references/basic-integration-1.2-revise.md +23 -0
  167. package/skills/integration/integration-astro-static/references/basic-integration-1.3-conclude.md +57 -0
  168. package/skills/integration/integration-astro-static/references/browser-sdk-2.md +4680 -0
  169. package/skills/integration/integration-astro-view-transitions/SKILL.md +51 -0
  170. package/skills/integration/integration-astro-view-transitions/references/EXAMPLE.md +979 -0
  171. package/skills/integration/integration-astro-view-transitions/references/amplitude-quickstart.md +1845 -0
  172. package/skills/integration/integration-astro-view-transitions/references/basic-integration-1.0-begin.md +43 -0
  173. package/skills/integration/integration-astro-view-transitions/references/basic-integration-1.1-edit.md +35 -0
  174. package/skills/integration/integration-astro-view-transitions/references/basic-integration-1.2-revise.md +23 -0
  175. package/skills/integration/integration-astro-view-transitions/references/basic-integration-1.3-conclude.md +57 -0
  176. package/skills/integration/integration-astro-view-transitions/references/browser-sdk-2.md +4680 -0
  177. package/skills/integration/integration-django/SKILL.md +57 -0
  178. package/skills/integration/integration-django/references/EXAMPLE.md +1005 -0
  179. package/skills/integration/integration-django/references/amplitude-quickstart.md +1845 -0
  180. package/skills/integration/integration-django/references/basic-integration-1.0-begin.md +43 -0
  181. package/skills/integration/integration-django/references/basic-integration-1.1-edit.md +35 -0
  182. package/skills/integration/integration-django/references/basic-integration-1.2-revise.md +23 -0
  183. package/skills/integration/integration-django/references/basic-integration-1.3-conclude.md +57 -0
  184. package/skills/integration/integration-django/references/python.md +1424 -0
  185. package/skills/integration/integration-expo/SKILL.md +53 -0
  186. package/skills/integration/integration-expo/references/EXAMPLE.md +1291 -0
  187. package/skills/integration/integration-expo/references/amplitude-quickstart.md +1845 -0
  188. package/skills/integration/integration-expo/references/basic-integration-1.0-begin.md +43 -0
  189. package/skills/integration/integration-expo/references/basic-integration-1.1-edit.md +35 -0
  190. package/skills/integration/integration-expo/references/basic-integration-1.2-revise.md +23 -0
  191. package/skills/integration/integration-expo/references/basic-integration-1.3-conclude.md +57 -0
  192. package/skills/integration/integration-expo/references/react-native-sdk.md +2819 -0
  193. package/skills/integration/integration-fastapi/SKILL.md +57 -0
  194. package/skills/integration/integration-fastapi/references/EXAMPLE.md +1389 -0
  195. package/skills/integration/integration-fastapi/references/amplitude-quickstart.md +1845 -0
  196. package/skills/integration/integration-fastapi/references/basic-integration-1.0-begin.md +43 -0
  197. package/skills/integration/integration-fastapi/references/basic-integration-1.1-edit.md +35 -0
  198. package/skills/integration/integration-fastapi/references/basic-integration-1.2-revise.md +23 -0
  199. package/skills/integration/integration-fastapi/references/basic-integration-1.3-conclude.md +57 -0
  200. package/skills/integration/integration-fastapi/references/python.md +1424 -0
  201. package/skills/integration/integration-flask/SKILL.md +56 -0
  202. package/skills/integration/integration-flask/references/EXAMPLE.md +1130 -0
  203. package/skills/integration/integration-flask/references/amplitude-quickstart.md +1845 -0
  204. package/skills/integration/integration-flask/references/basic-integration-1.0-begin.md +43 -0
  205. package/skills/integration/integration-flask/references/basic-integration-1.1-edit.md +35 -0
  206. package/skills/integration/integration-flask/references/basic-integration-1.2-revise.md +23 -0
  207. package/skills/integration/integration-flask/references/basic-integration-1.3-conclude.md +57 -0
  208. package/skills/integration/integration-flask/references/python.md +1424 -0
  209. package/skills/integration/integration-javascript_node/SKILL.md +54 -0
  210. package/skills/integration/integration-javascript_node/references/EXAMPLE.md +365 -0
  211. package/skills/integration/integration-javascript_node/references/amplitude-quickstart.md +1845 -0
  212. package/skills/integration/integration-javascript_node/references/analytics.md +1778 -0
  213. package/skills/integration/integration-javascript_node/references/basic-integration-1.0-begin.md +43 -0
  214. package/skills/integration/integration-javascript_node/references/basic-integration-1.1-edit.md +35 -0
  215. package/skills/integration/integration-javascript_node/references/basic-integration-1.2-revise.md +23 -0
  216. package/skills/integration/integration-javascript_node/references/basic-integration-1.3-conclude.md +57 -0
  217. package/skills/integration/integration-javascript_web/SKILL.md +58 -0
  218. package/skills/integration/integration-javascript_web/references/EXAMPLE.md +451 -0
  219. package/skills/integration/integration-javascript_web/references/amplitude-quickstart.md +1845 -0
  220. package/skills/integration/integration-javascript_web/references/basic-integration-1.0-begin.md +43 -0
  221. package/skills/integration/integration-javascript_web/references/basic-integration-1.1-edit.md +35 -0
  222. package/skills/integration/integration-javascript_web/references/basic-integration-1.2-revise.md +23 -0
  223. package/skills/integration/integration-javascript_web/references/basic-integration-1.3-conclude.md +57 -0
  224. package/skills/integration/integration-javascript_web/references/browser-sdk-2.md +4680 -0
  225. package/skills/integration/integration-laravel/SKILL.md +52 -0
  226. package/skills/integration/integration-laravel/references/EXAMPLE.md +2039 -0
  227. package/skills/integration/integration-laravel/references/amplitude-quickstart.md +1845 -0
  228. package/skills/integration/integration-laravel/references/analytics.md +1778 -0
  229. package/skills/integration/integration-laravel/references/basic-integration-1.0-begin.md +43 -0
  230. package/skills/integration/integration-laravel/references/basic-integration-1.1-edit.md +35 -0
  231. package/skills/integration/integration-laravel/references/basic-integration-1.2-revise.md +23 -0
  232. package/skills/integration/integration-laravel/references/basic-integration-1.3-conclude.md +57 -0
  233. package/skills/integration/integration-nextjs-app-router/SKILL.md +54 -0
  234. package/skills/integration/integration-nextjs-app-router/references/EXAMPLE.md +673 -0
  235. package/skills/integration/integration-nextjs-app-router/references/amplitude-quickstart.md +1845 -0
  236. package/skills/integration/integration-nextjs-app-router/references/basic-integration-1.0-begin.md +43 -0
  237. package/skills/integration/integration-nextjs-app-router/references/basic-integration-1.1-edit.md +35 -0
  238. package/skills/integration/integration-nextjs-app-router/references/basic-integration-1.2-revise.md +23 -0
  239. package/skills/integration/integration-nextjs-app-router/references/basic-integration-1.3-conclude.md +57 -0
  240. package/skills/integration/integration-nextjs-app-router/references/browser-sdk-2.md +4680 -0
  241. package/skills/integration/integration-nextjs-pages-router/SKILL.md +54 -0
  242. package/skills/integration/integration-nextjs-pages-router/references/EXAMPLE.md +735 -0
  243. package/skills/integration/integration-nextjs-pages-router/references/amplitude-quickstart.md +1845 -0
  244. package/skills/integration/integration-nextjs-pages-router/references/basic-integration-1.0-begin.md +43 -0
  245. package/skills/integration/integration-nextjs-pages-router/references/basic-integration-1.1-edit.md +35 -0
  246. package/skills/integration/integration-nextjs-pages-router/references/basic-integration-1.2-revise.md +23 -0
  247. package/skills/integration/integration-nextjs-pages-router/references/basic-integration-1.3-conclude.md +57 -0
  248. package/skills/integration/integration-nextjs-pages-router/references/browser-sdk-2.md +4680 -0
  249. package/skills/integration/integration-nuxt-3.6/SKILL.md +46 -0
  250. package/skills/integration/integration-nuxt-3.6/references/EXAMPLE.md +8422 -0
  251. package/skills/integration/integration-nuxt-3.6/references/amplitude-quickstart.md +1845 -0
  252. package/skills/integration/integration-nuxt-3.6/references/basic-integration-1.0-begin.md +43 -0
  253. package/skills/integration/integration-nuxt-3.6/references/basic-integration-1.1-edit.md +35 -0
  254. package/skills/integration/integration-nuxt-3.6/references/basic-integration-1.2-revise.md +23 -0
  255. package/skills/integration/integration-nuxt-3.6/references/basic-integration-1.3-conclude.md +57 -0
  256. package/skills/integration/integration-nuxt-3.6/references/browser-sdk-2.md +4680 -0
  257. package/skills/integration/integration-nuxt-4/SKILL.md +46 -0
  258. package/skills/integration/integration-nuxt-4/references/EXAMPLE.md +8670 -0
  259. package/skills/integration/integration-nuxt-4/references/amplitude-quickstart.md +1845 -0
  260. package/skills/integration/integration-nuxt-4/references/basic-integration-1.0-begin.md +43 -0
  261. package/skills/integration/integration-nuxt-4/references/basic-integration-1.1-edit.md +35 -0
  262. package/skills/integration/integration-nuxt-4/references/basic-integration-1.2-revise.md +23 -0
  263. package/skills/integration/integration-nuxt-4/references/basic-integration-1.3-conclude.md +57 -0
  264. package/skills/integration/integration-nuxt-4/references/browser-sdk-2.md +4680 -0
  265. package/skills/integration/integration-python/SKILL.md +53 -0
  266. package/skills/integration/integration-python/references/EXAMPLE.md +445 -0
  267. package/skills/integration/integration-python/references/amplitude-quickstart.md +1845 -0
  268. package/skills/integration/integration-python/references/basic-integration-1.0-begin.md +43 -0
  269. package/skills/integration/integration-python/references/basic-integration-1.1-edit.md +35 -0
  270. package/skills/integration/integration-python/references/basic-integration-1.2-revise.md +23 -0
  271. package/skills/integration/integration-python/references/basic-integration-1.3-conclude.md +57 -0
  272. package/skills/integration/integration-python/references/python.md +1424 -0
  273. package/skills/integration/integration-react-native/SKILL.md +49 -0
  274. package/skills/integration/integration-react-native/references/EXAMPLE.md +2253 -0
  275. package/skills/integration/integration-react-native/references/amplitude-quickstart.md +1845 -0
  276. package/skills/integration/integration-react-native/references/basic-integration-1.0-begin.md +43 -0
  277. package/skills/integration/integration-react-native/references/basic-integration-1.1-edit.md +35 -0
  278. package/skills/integration/integration-react-native/references/basic-integration-1.2-revise.md +23 -0
  279. package/skills/integration/integration-react-native/references/basic-integration-1.3-conclude.md +57 -0
  280. package/skills/integration/integration-react-native/references/react-native-sdk.md +2819 -0
  281. package/skills/integration/integration-react-react-router-6/SKILL.md +53 -0
  282. package/skills/integration/integration-react-react-router-6/references/EXAMPLE.md +570 -0
  283. package/skills/integration/integration-react-react-router-6/references/amplitude-quickstart.md +1845 -0
  284. package/skills/integration/integration-react-react-router-6/references/basic-integration-1.0-begin.md +43 -0
  285. package/skills/integration/integration-react-react-router-6/references/basic-integration-1.1-edit.md +35 -0
  286. package/skills/integration/integration-react-react-router-6/references/basic-integration-1.2-revise.md +23 -0
  287. package/skills/integration/integration-react-react-router-6/references/basic-integration-1.3-conclude.md +57 -0
  288. package/skills/integration/integration-react-react-router-6/references/browser-sdk-2.md +4680 -0
  289. package/skills/integration/integration-react-react-router-7-data/SKILL.md +53 -0
  290. package/skills/integration/integration-react-react-router-7-data/references/EXAMPLE.md +830 -0
  291. package/skills/integration/integration-react-react-router-7-data/references/amplitude-quickstart.md +1845 -0
  292. package/skills/integration/integration-react-react-router-7-data/references/basic-integration-1.0-begin.md +43 -0
  293. package/skills/integration/integration-react-react-router-7-data/references/basic-integration-1.1-edit.md +35 -0
  294. package/skills/integration/integration-react-react-router-7-data/references/basic-integration-1.2-revise.md +23 -0
  295. package/skills/integration/integration-react-react-router-7-data/references/basic-integration-1.3-conclude.md +57 -0
  296. package/skills/integration/integration-react-react-router-7-data/references/browser-sdk-2.md +4680 -0
  297. package/skills/integration/integration-react-react-router-7-declarative/SKILL.md +53 -0
  298. package/skills/integration/integration-react-react-router-7-declarative/references/EXAMPLE.md +609 -0
  299. package/skills/integration/integration-react-react-router-7-declarative/references/amplitude-quickstart.md +1845 -0
  300. package/skills/integration/integration-react-react-router-7-declarative/references/basic-integration-1.0-begin.md +43 -0
  301. package/skills/integration/integration-react-react-router-7-declarative/references/basic-integration-1.1-edit.md +35 -0
  302. package/skills/integration/integration-react-react-router-7-declarative/references/basic-integration-1.2-revise.md +23 -0
  303. package/skills/integration/integration-react-react-router-7-declarative/references/basic-integration-1.3-conclude.md +57 -0
  304. package/skills/integration/integration-react-react-router-7-declarative/references/browser-sdk-2.md +4680 -0
  305. package/skills/integration/integration-react-react-router-7-framework/SKILL.md +53 -0
  306. package/skills/integration/integration-react-react-router-7-framework/references/EXAMPLE.md +1081 -0
  307. package/skills/integration/integration-react-react-router-7-framework/references/amplitude-quickstart.md +1845 -0
  308. package/skills/integration/integration-react-react-router-7-framework/references/basic-integration-1.0-begin.md +43 -0
  309. package/skills/integration/integration-react-react-router-7-framework/references/basic-integration-1.1-edit.md +35 -0
  310. package/skills/integration/integration-react-react-router-7-framework/references/basic-integration-1.2-revise.md +23 -0
  311. package/skills/integration/integration-react-react-router-7-framework/references/basic-integration-1.3-conclude.md +57 -0
  312. package/skills/integration/integration-react-react-router-7-framework/references/browser-sdk-2.md +4680 -0
  313. package/skills/integration/integration-react-tanstack-router-code-based/SKILL.md +57 -0
  314. package/skills/integration/integration-react-tanstack-router-code-based/references/EXAMPLE.md +659 -0
  315. package/skills/integration/integration-react-tanstack-router-code-based/references/amplitude-quickstart.md +1845 -0
  316. package/skills/integration/integration-react-tanstack-router-code-based/references/basic-integration-1.0-begin.md +43 -0
  317. package/skills/integration/integration-react-tanstack-router-code-based/references/basic-integration-1.1-edit.md +35 -0
  318. package/skills/integration/integration-react-tanstack-router-code-based/references/basic-integration-1.2-revise.md +23 -0
  319. package/skills/integration/integration-react-tanstack-router-code-based/references/basic-integration-1.3-conclude.md +57 -0
  320. package/skills/integration/integration-react-tanstack-router-code-based/references/browser-sdk-2.md +4680 -0
  321. package/skills/integration/integration-react-tanstack-router-file-based/SKILL.md +57 -0
  322. package/skills/integration/integration-react-tanstack-router-file-based/references/EXAMPLE.md +777 -0
  323. package/skills/integration/integration-react-tanstack-router-file-based/references/amplitude-quickstart.md +1845 -0
  324. package/skills/integration/integration-react-tanstack-router-file-based/references/basic-integration-1.0-begin.md +43 -0
  325. package/skills/integration/integration-react-tanstack-router-file-based/references/basic-integration-1.1-edit.md +35 -0
  326. package/skills/integration/integration-react-tanstack-router-file-based/references/basic-integration-1.2-revise.md +23 -0
  327. package/skills/integration/integration-react-tanstack-router-file-based/references/basic-integration-1.3-conclude.md +57 -0
  328. package/skills/integration/integration-react-tanstack-router-file-based/references/browser-sdk-2.md +4680 -0
  329. package/skills/integration/integration-react-vite/SKILL.md +53 -0
  330. package/skills/integration/integration-react-vite/references/EXAMPLE.md +542 -0
  331. package/skills/integration/integration-react-vite/references/amplitude-quickstart.md +1845 -0
  332. package/skills/integration/integration-react-vite/references/basic-integration-1.0-begin.md +43 -0
  333. package/skills/integration/integration-react-vite/references/basic-integration-1.1-edit.md +35 -0
  334. package/skills/integration/integration-react-vite/references/basic-integration-1.2-revise.md +23 -0
  335. package/skills/integration/integration-react-vite/references/basic-integration-1.3-conclude.md +57 -0
  336. package/skills/integration/integration-react-vite/references/browser-sdk-2.md +4680 -0
  337. package/skills/integration/integration-ruby/SKILL.md +50 -0
  338. package/skills/integration/integration-ruby/references/EXAMPLE.md +420 -0
  339. package/skills/integration/integration-ruby/references/amplitude-quickstart.md +1845 -0
  340. package/skills/integration/integration-ruby/references/analytics.md +1778 -0
  341. package/skills/integration/integration-ruby/references/basic-integration-1.0-begin.md +43 -0
  342. package/skills/integration/integration-ruby/references/basic-integration-1.1-edit.md +35 -0
  343. package/skills/integration/integration-ruby/references/basic-integration-1.2-revise.md +23 -0
  344. package/skills/integration/integration-ruby/references/basic-integration-1.3-conclude.md +57 -0
  345. package/skills/integration/integration-ruby-on-rails/SKILL.md +55 -0
  346. package/skills/integration/integration-ruby-on-rails/references/EXAMPLE.md +1013 -0
  347. package/skills/integration/integration-ruby-on-rails/references/amplitude-quickstart.md +1845 -0
  348. package/skills/integration/integration-ruby-on-rails/references/analytics.md +1778 -0
  349. package/skills/integration/integration-ruby-on-rails/references/basic-integration-1.0-begin.md +43 -0
  350. package/skills/integration/integration-ruby-on-rails/references/basic-integration-1.1-edit.md +35 -0
  351. package/skills/integration/integration-ruby-on-rails/references/basic-integration-1.2-revise.md +23 -0
  352. package/skills/integration/integration-ruby-on-rails/references/basic-integration-1.3-conclude.md +57 -0
  353. package/skills/integration/integration-sveltekit/SKILL.md +47 -0
  354. package/skills/integration/integration-sveltekit/references/EXAMPLE.md +14121 -0
  355. package/skills/integration/integration-sveltekit/references/amplitude-quickstart.md +1845 -0
  356. package/skills/integration/integration-sveltekit/references/basic-integration-1.0-begin.md +43 -0
  357. package/skills/integration/integration-sveltekit/references/basic-integration-1.1-edit.md +35 -0
  358. package/skills/integration/integration-sveltekit/references/basic-integration-1.2-revise.md +23 -0
  359. package/skills/integration/integration-sveltekit/references/basic-integration-1.3-conclude.md +57 -0
  360. package/skills/integration/integration-sveltekit/references/browser-sdk-2.md +4680 -0
  361. package/skills/integration/integration-swift/SKILL.md +49 -0
  362. package/skills/integration/integration-swift/references/EXAMPLE.md +660 -0
  363. package/skills/integration/integration-swift/references/amplitude-quickstart.md +1845 -0
  364. package/skills/integration/integration-swift/references/analytics.md +1778 -0
  365. package/skills/integration/integration-swift/references/basic-integration-1.0-begin.md +43 -0
  366. package/skills/integration/integration-swift/references/basic-integration-1.1-edit.md +35 -0
  367. package/skills/integration/integration-swift/references/basic-integration-1.2-revise.md +23 -0
  368. package/skills/integration/integration-swift/references/basic-integration-1.3-conclude.md +57 -0
  369. package/skills/integration/integration-tanstack-start/SKILL.md +58 -0
  370. package/skills/integration/integration-tanstack-start/references/EXAMPLE.md +998 -0
  371. package/skills/integration/integration-tanstack-start/references/amplitude-quickstart.md +1845 -0
  372. package/skills/integration/integration-tanstack-start/references/basic-integration-1.0-begin.md +43 -0
  373. package/skills/integration/integration-tanstack-start/references/basic-integration-1.1-edit.md +35 -0
  374. package/skills/integration/integration-tanstack-start/references/basic-integration-1.2-revise.md +23 -0
  375. package/skills/integration/integration-tanstack-start/references/basic-integration-1.3-conclude.md +57 -0
  376. package/skills/integration/integration-tanstack-start/references/browser-sdk-2.md +4680 -0
  377. package/skills/integration/integration-vue-3/SKILL.md +46 -0
  378. package/skills/integration/integration-vue-3/references/EXAMPLE.md +846 -0
  379. package/skills/integration/integration-vue-3/references/amplitude-quickstart.md +1845 -0
  380. package/skills/integration/integration-vue-3/references/basic-integration-1.0-begin.md +43 -0
  381. package/skills/integration/integration-vue-3/references/basic-integration-1.1-edit.md +35 -0
  382. package/skills/integration/integration-vue-3/references/basic-integration-1.2-revise.md +23 -0
  383. package/skills/integration/integration-vue-3/references/basic-integration-1.3-conclude.md +57 -0
  384. package/skills/integration/integration-vue-3/references/browser-sdk-2.md +4680 -0
  385. package/skills/taxonomy/amplitude-quickstart-taxonomy-agent/SKILL.md +228 -0
  386. package/dist/src/ui/tui/components/TitleBar.d.ts +0 -8
  387. package/dist/src/ui/tui/components/TitleBar.js +0 -27
  388. package/dist/src/ui/tui/primitives/KagiSmallWebViewer.d.ts +0 -7
  389. package/dist/src/ui/tui/primitives/KagiSmallWebViewer.js +0 -101
  390. package/dist/src/utils/anthropic-status.d.ts +0 -17
  391. package/dist/src/utils/anthropic-status.js +0 -51
@@ -0,0 +1,1130 @@
1
+ # Amplitude Flask Example Project
2
+
3
+ Repository: https://github.com/amplitude/context-hub
4
+ Path: basics/flask
5
+
6
+ ---
7
+
8
+ ## README.md
9
+
10
+ # Amplitude Flask Example
11
+
12
+ A Flask application demonstrating Amplitude integration for analytics and event tracking.
13
+
14
+ ## Features
15
+
16
+ - User registration and authentication with Flask-Login
17
+ - SQLite database persistence with Flask-SQLAlchemy
18
+ - User identification and property tracking
19
+ - Custom event tracking
20
+
21
+ ## Quick Start
22
+
23
+ 1. Create and activate a virtual environment:
24
+ ```bash
25
+ python -m venv venv
26
+ source venv/bin/activate # On Windows: venv\Scripts\activate
27
+ ```
28
+
29
+ 2. Install dependencies:
30
+ ```bash
31
+ pip install -r requirements.txt
32
+ ```
33
+
34
+ 3. Copy the environment file and configure:
35
+ ```bash
36
+ cp .env.example .env
37
+ # Edit .env with your Amplitude API key
38
+ ```
39
+
40
+ 4. Run the application:
41
+ ```bash
42
+ python run.py
43
+ ```
44
+
45
+ 5. Open http://localhost:5001 and either:
46
+ - Login with default credentials: `admin@example.com` / `admin`
47
+ - Or click "Sign up here" to create a new account
48
+
49
+ ## Amplitude Integration Points
50
+
51
+ ### User Registration
52
+ New users are identified and tracked on signup:
53
+ ```python
54
+ client = get_amplitude_client()
55
+ if client:
56
+ identify_obj = Identify()
57
+ identify_obj.set('email', user.email)
58
+ identify_obj.set('is_staff', user.is_staff)
59
+ identify_obj.set('date_joined', user.date_joined.isoformat())
60
+ client.identify(identify_obj, {'user_id': user.email})
61
+
62
+ client.track(BaseEvent(
63
+ event_type='User Signed Up',
64
+ user_id=user.email,
65
+ event_properties={'signup_method': 'form'},
66
+ ))
67
+ ```
68
+
69
+ ### User Identification
70
+ Users are identified on login with their properties:
71
+ ```python
72
+ client = get_amplitude_client()
73
+ if client:
74
+ identify_obj = Identify()
75
+ identify_obj.set('email', user.email)
76
+ identify_obj.set('is_staff', user.is_staff)
77
+ client.identify(identify_obj, {'user_id': user.email})
78
+
79
+ client.track(BaseEvent(
80
+ event_type='User Logged In',
81
+ user_id=user.email,
82
+ event_properties={'login_method': 'password'},
83
+ ))
84
+ ```
85
+
86
+ ### Event Tracking
87
+ Custom events are tracked throughout the app:
88
+ ```python
89
+ client = get_amplitude_client()
90
+ if client:
91
+ client.track(BaseEvent(
92
+ event_type='Burrito Considered',
93
+ user_id=current_user.email,
94
+ event_properties={'total_considerations': count},
95
+ ))
96
+ ```
97
+
98
+ ## Project Structure
99
+
100
+ ```
101
+ basics/flask/
102
+ ├── app/
103
+ │ ├── __init__.py # Application factory
104
+ │ ├── config.py # Configuration classes
105
+ │ ├── extensions.py # Extension instances
106
+ │ ├── models.py # User model (SQLAlchemy)
107
+ │ ├── main/
108
+ │ │ ├── __init__.py # Main blueprint
109
+ │ │ └── routes.py # View functions
110
+ │ ├── templates/ # HTML templates
111
+ │ └── api/
112
+ │ ├── __init__.py # API blueprint
113
+ │ └── routes.py # API endpoints
114
+ ├── .env.example
115
+ ├── .gitignore
116
+ ├── requirements.txt
117
+ ├── README.md
118
+ └── run.py # Entry point
119
+ ```
120
+
121
+ ---
122
+
123
+ ## .env.example
124
+
125
+ ```example
126
+ AMPLITUDE_API_KEY=your_amplitude_api_key_here
127
+ FLASK_SECRET_KEY=your-secret-key-here
128
+ FLASK_DEBUG=True
129
+ AMPLITUDE_DISABLED=False
130
+
131
+ ```
132
+
133
+ ---
134
+
135
+ ## app/__init__.py
136
+
137
+ ```py
138
+ """Flask application factory."""
139
+
140
+ from flask import Flask, jsonify, render_template, request
141
+
142
+ from app.config import config
143
+ from app.extensions import db, login_manager
144
+
145
+
146
+ def create_app(config_name="default"):
147
+ """Application factory."""
148
+ app = Flask(__name__)
149
+ app.config.from_object(config[config_name])
150
+
151
+ # Initialize extensions
152
+ db.init_app(app)
153
+ login_manager.init_app(app)
154
+
155
+ # Import models after db is initialized
156
+ from app.models import User
157
+
158
+ # User loader for Flask-Login
159
+ @login_manager.user_loader
160
+ def load_user(user_id):
161
+ return User.get_by_id(user_id)
162
+
163
+ # Simple error handlers
164
+ @app.errorhandler(404)
165
+ def page_not_found(e):
166
+ if request.path.startswith('/api/'):
167
+ return jsonify({"error": "Not found"}), 404
168
+ return render_template('errors/404.html'), 404
169
+
170
+ @app.errorhandler(500)
171
+ def internal_server_error(e):
172
+ if request.path.startswith('/api/'):
173
+ return jsonify({"error": "Internal server error"}), 500
174
+ return render_template('errors/500.html'), 500
175
+
176
+ # Register blueprints
177
+ from app.api import api_bp
178
+ from app.main import main_bp
179
+
180
+ app.register_blueprint(main_bp)
181
+ app.register_blueprint(api_bp, url_prefix="/api")
182
+
183
+ # Create database tables and seed default admin user
184
+ with app.app_context():
185
+ db.create_all()
186
+ if not User.get_by_email("admin@example.com"):
187
+ User.create_user(
188
+ email="admin@example.com",
189
+ password="admin",
190
+ is_staff=True,
191
+ )
192
+
193
+ return app
194
+
195
+ ```
196
+
197
+ ---
198
+
199
+ ## app/api/__init__.py
200
+
201
+ ```py
202
+ """API blueprint registration."""
203
+
204
+ from flask import Blueprint
205
+
206
+ api_bp = Blueprint("api", __name__)
207
+
208
+ from app.api import routes # noqa: E402, F401
209
+
210
+ ```
211
+
212
+ ---
213
+
214
+ ## app/api/routes.py
215
+
216
+ ```py
217
+ """API endpoints demonstrating Amplitude integration patterns."""
218
+
219
+ from amplitude import BaseEvent
220
+ from flask import jsonify, request, session
221
+ from flask_login import current_user, login_required
222
+
223
+ from app.api import api_bp
224
+ from app.main.routes import get_amplitude_client
225
+
226
+
227
+ @api_bp.route("/burrito/consider", methods=["POST"])
228
+ @login_required
229
+ def consider_burrito():
230
+ """Track burrito consideration event."""
231
+ # Increment session counter
232
+ burrito_count = session.get("burrito_count", 0) + 1
233
+ session["burrito_count"] = burrito_count
234
+
235
+ # Amplitude: Capture custom event
236
+ client = get_amplitude_client()
237
+ if client:
238
+ client.track(BaseEvent(
239
+ event_type="Burrito Considered",
240
+ user_id=current_user.email,
241
+ event_properties={"total_considerations": burrito_count},
242
+ ))
243
+
244
+ return jsonify({"success": True, "count": burrito_count})
245
+
246
+
247
+ @api_bp.route("/test-error", methods=["POST"])
248
+ @login_required
249
+ def test_error():
250
+ """Test endpoint demonstrating manual event capture in Amplitude.
251
+
252
+ Shows how to track error events in Amplitude.
253
+ Use this pattern for critical operations where you want error tracking.
254
+
255
+ Query params:
256
+ - capture: "true" to capture the error event in Amplitude, "false" to just raise it
257
+ """
258
+ should_capture = request.args.get("capture", "true").lower() == "true"
259
+
260
+ try:
261
+ # Simulate a critical operation failure
262
+ raise Exception("Test exception from critical operation")
263
+ except Exception as e:
264
+ if should_capture:
265
+ # Manually capture this specific error event in Amplitude
266
+ client = get_amplitude_client()
267
+ if client:
268
+ client.track(BaseEvent(
269
+ event_type="Error Occurred",
270
+ user_id=current_user.email,
271
+ event_properties={
272
+ "error_message": str(e),
273
+ "error_type": type(e).__name__,
274
+ },
275
+ ))
276
+
277
+ return jsonify({
278
+ "error": "Operation failed",
279
+ "message": f"Error captured in Amplitude: {str(e)}"
280
+ }), 500
281
+ else:
282
+ # Just return error without Amplitude capture
283
+ return jsonify({"error": str(e)}), 500
284
+
285
+ ```
286
+
287
+ ---
288
+
289
+ ## app/config.py
290
+
291
+ ```py
292
+ """Flask application configuration."""
293
+
294
+ import os
295
+ from dotenv import load_dotenv
296
+
297
+ load_dotenv()
298
+
299
+
300
+ class Config:
301
+ """Base configuration."""
302
+
303
+ SECRET_KEY = os.environ.get("FLASK_SECRET_KEY", "dev-secret-key-change-in-production")
304
+
305
+ # Database configuration (SQLite like Django example)
306
+ SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL", "sqlite:///db.sqlite3")
307
+ SQLALCHEMY_TRACK_MODIFICATIONS = False
308
+
309
+ # Amplitude configuration
310
+ AMPLITUDE_API_KEY = os.environ.get("AMPLITUDE_API_KEY", "")
311
+ AMPLITUDE_DISABLED = os.environ.get("AMPLITUDE_DISABLED", "False").lower() == "true"
312
+
313
+
314
+ class DevelopmentConfig(Config):
315
+ """Development configuration."""
316
+
317
+ DEBUG = True
318
+
319
+
320
+ class ProductionConfig(Config):
321
+ """Production configuration."""
322
+
323
+ DEBUG = False
324
+
325
+
326
+ config = {
327
+ "development": DevelopmentConfig,
328
+ "production": ProductionConfig,
329
+ "default": DevelopmentConfig,
330
+ }
331
+
332
+ ```
333
+
334
+ ---
335
+
336
+ ## app/extensions.py
337
+
338
+ ```py
339
+ """Flask extensions initialized without binding to app."""
340
+
341
+ from flask_login import LoginManager
342
+ from flask_sqlalchemy import SQLAlchemy
343
+
344
+ db = SQLAlchemy()
345
+
346
+ login_manager = LoginManager()
347
+ login_manager.login_view = "main.home"
348
+ login_manager.login_message = "Please log in to access this page."
349
+
350
+ ```
351
+
352
+ ---
353
+
354
+ ## app/main/__init__.py
355
+
356
+ ```py
357
+ """Main blueprint registration."""
358
+
359
+ from flask import Blueprint
360
+
361
+ main_bp = Blueprint("main", __name__, template_folder="../templates")
362
+
363
+ from app.main import routes # noqa: E402, F401
364
+
365
+ ```
366
+
367
+ ---
368
+
369
+ ## app/main/routes.py
370
+
371
+ ```py
372
+ """Core view functions demonstrating Amplitude integration patterns."""
373
+
374
+ from amplitude import Amplitude, BaseEvent, Identify
375
+ from flask import current_app, flash, redirect, render_template, request, session, url_for
376
+ from flask_login import current_user, login_required, login_user, logout_user
377
+
378
+ from app.main import main_bp
379
+ from app.models import User
380
+
381
+
382
+ def get_amplitude_client():
383
+ """Get the Amplitude client instance."""
384
+ api_key = current_app.config.get('AMPLITUDE_API_KEY', '')
385
+ if not api_key or current_app.config.get('AMPLITUDE_DISABLED', False):
386
+ return None
387
+ return Amplitude(api_key)
388
+
389
+
390
+ @main_bp.route("/", methods=["GET", "POST"])
391
+ def home():
392
+ """Home/login page."""
393
+ if current_user.is_authenticated:
394
+ return redirect(url_for("main.dashboard"))
395
+
396
+ if request.method == "POST":
397
+ email = request.form.get("email")
398
+ password = request.form.get("password")
399
+
400
+ user = User.authenticate(email, password)
401
+ if user:
402
+ login_user(user)
403
+
404
+ # Amplitude: Identify user and capture login event
405
+ client = get_amplitude_client()
406
+ if client:
407
+ identify_obj = Identify()
408
+ identify_obj.set("email", user.email)
409
+ identify_obj.set("is_staff", user.is_staff)
410
+ identify_obj.set("date_joined", user.date_joined.isoformat())
411
+ client.identify(identify_obj, {"user_id": user.email})
412
+
413
+ client.track(BaseEvent(
414
+ event_type="User Logged In",
415
+ user_id=user.email,
416
+ event_properties={"login_method": "password"},
417
+ ))
418
+
419
+ return redirect(url_for("main.dashboard"))
420
+ else:
421
+ flash("Invalid email or password", "error")
422
+
423
+ return render_template("home.html")
424
+
425
+
426
+ @main_bp.route("/signup", methods=["GET", "POST"])
427
+ def signup():
428
+ """User registration page."""
429
+ if current_user.is_authenticated:
430
+ return redirect(url_for("main.dashboard"))
431
+
432
+ if request.method == "POST":
433
+ email = request.form.get("email")
434
+ password = request.form.get("password")
435
+ password_confirm = request.form.get("password_confirm")
436
+
437
+ # Validation
438
+ if not email or not password:
439
+ flash("Email and password are required", "error")
440
+ elif password != password_confirm:
441
+ flash("Passwords do not match", "error")
442
+ elif User.get_by_email(email):
443
+ flash("Email already registered", "error")
444
+ else:
445
+ # Create new user
446
+ user = User.create_user(
447
+ email=email,
448
+ password=password,
449
+ is_staff=False,
450
+ )
451
+
452
+ # Amplitude: Identify new user and capture signup event
453
+ client = get_amplitude_client()
454
+ if client:
455
+ identify_obj = Identify()
456
+ identify_obj.set("email", user.email)
457
+ identify_obj.set("is_staff", user.is_staff)
458
+ identify_obj.set("date_joined", user.date_joined.isoformat())
459
+ client.identify(identify_obj, {"user_id": user.email})
460
+
461
+ client.track(BaseEvent(
462
+ event_type="User Signed Up",
463
+ user_id=user.email,
464
+ event_properties={"signup_method": "form"},
465
+ ))
466
+
467
+ # Log the user in
468
+ login_user(user)
469
+ flash("Account created successfully!", "success")
470
+ return redirect(url_for("main.dashboard"))
471
+
472
+ return render_template("signup.html")
473
+
474
+
475
+ @main_bp.route("/logout")
476
+ @login_required
477
+ def logout():
478
+ """Logout and capture event."""
479
+ # Amplitude: Capture logout event before session ends
480
+ client = get_amplitude_client()
481
+ if client:
482
+ client.track(BaseEvent(
483
+ event_type="User Logged Out",
484
+ user_id=current_user.email,
485
+ ))
486
+
487
+ logout_user()
488
+ return redirect(url_for("main.home"))
489
+
490
+
491
+ @main_bp.route("/dashboard")
492
+ @login_required
493
+ def dashboard():
494
+ """Dashboard page."""
495
+ # Amplitude: Capture dashboard view
496
+ client = get_amplitude_client()
497
+ if client:
498
+ client.track(BaseEvent(
499
+ event_type="Dashboard Viewed",
500
+ user_id=current_user.email,
501
+ event_properties={"is_staff": current_user.is_staff},
502
+ ))
503
+
504
+ # TODO: Use Amplitude Experiment for feature flags
505
+
506
+ return render_template("dashboard.html")
507
+
508
+
509
+ @main_bp.route("/burrito")
510
+ @login_required
511
+ def burrito():
512
+ """Burrito consideration tracker page."""
513
+ burrito_count = session.get("burrito_count", 0)
514
+ return render_template("burrito.html", burrito_count=burrito_count)
515
+
516
+
517
+ @main_bp.route("/profile")
518
+ @login_required
519
+ def profile():
520
+ """User profile page."""
521
+ # Amplitude: Capture profile view
522
+ client = get_amplitude_client()
523
+ if client:
524
+ client.track(BaseEvent(
525
+ event_type="Profile Viewed",
526
+ user_id=current_user.email,
527
+ ))
528
+
529
+ return render_template("profile.html")
530
+
531
+ ```
532
+
533
+ ---
534
+
535
+ ## app/models.py
536
+
537
+ ```py
538
+ """User model with SQLite persistence (similar to Django's auth.User)."""
539
+
540
+ from datetime import datetime, timezone
541
+
542
+ from flask_login import UserMixin
543
+ from werkzeug.security import check_password_hash, generate_password_hash
544
+
545
+ from app.extensions import db
546
+
547
+
548
+ class User(UserMixin, db.Model):
549
+ """User model with SQLite persistence."""
550
+
551
+ __tablename__ = "users"
552
+
553
+ id = db.Column(db.Integer, primary_key=True)
554
+ email = db.Column(db.String(254), unique=True, nullable=False)
555
+ password_hash = db.Column(db.String(256), nullable=False)
556
+ is_staff = db.Column(db.Boolean, default=False)
557
+ is_active = db.Column(db.Boolean, default=True)
558
+ date_joined = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
559
+
560
+ def set_password(self, password):
561
+ """Hash and set the user's password."""
562
+ self.password_hash = generate_password_hash(password)
563
+
564
+ def check_password(self, password):
565
+ """Verify the password against the hash."""
566
+ return check_password_hash(self.password_hash, password)
567
+
568
+ @classmethod
569
+ def create_user(cls, email, password, is_staff=False):
570
+ """Create and save a new user."""
571
+ user = cls(email=email, is_staff=is_staff)
572
+ # nosemgrep: python.django.security.audit.unvalidated-password.unvalidated-password
573
+ user.set_password(password)
574
+ db.session.add(user)
575
+ db.session.commit()
576
+ return user
577
+
578
+ @classmethod
579
+ def get_by_id(cls, user_id):
580
+ """Get user by ID."""
581
+ return cls.query.get(int(user_id))
582
+
583
+ @classmethod
584
+ def get_by_email(cls, email):
585
+ """Get user by email."""
586
+ return cls.query.filter_by(email=email).first()
587
+
588
+ @classmethod
589
+ def authenticate(cls, email, password):
590
+ """Authenticate user with email and password."""
591
+ user = cls.get_by_email(email)
592
+ if user and user.check_password(password):
593
+ return user
594
+ return None
595
+
596
+ def __repr__(self):
597
+ return f"<User {self.email}>"
598
+
599
+ ```
600
+
601
+ ---
602
+
603
+ ## app/templates/base.html
604
+
605
+ ```html
606
+ <!DOCTYPE html>
607
+ <html lang="en">
608
+ <head>
609
+ <meta charset="UTF-8">
610
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
611
+ <title>{% block title %}Amplitude Flask Example{% endblock %}</title>
612
+ <style>
613
+ * {
614
+ box-sizing: border-box;
615
+ margin: 0;
616
+ padding: 0;
617
+ }
618
+ body {
619
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
620
+ line-height: 1.6;
621
+ background-color: #f5f5f5;
622
+ color: #333;
623
+ }
624
+ .container {
625
+ max-width: 800px;
626
+ margin: 0 auto;
627
+ padding: 20px;
628
+ }
629
+ nav {
630
+ background: #1d4ed8;
631
+ padding: 15px 20px;
632
+ margin-bottom: 30px;
633
+ }
634
+ nav a {
635
+ color: white;
636
+ text-decoration: none;
637
+ margin-right: 20px;
638
+ }
639
+ nav a:hover {
640
+ text-decoration: underline;
641
+ }
642
+ .card {
643
+ background: white;
644
+ border-radius: 8px;
645
+ padding: 20px;
646
+ margin-bottom: 20px;
647
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
648
+ }
649
+ h1, h2, h3 {
650
+ margin-bottom: 15px;
651
+ color: #1d4ed8;
652
+ }
653
+ button, .btn {
654
+ background: #1d4ed8;
655
+ color: white;
656
+ border: none;
657
+ padding: 10px 20px;
658
+ border-radius: 5px;
659
+ cursor: pointer;
660
+ font-size: 14px;
661
+ display: inline-block;
662
+ text-decoration: none;
663
+ }
664
+ button:hover, .btn:hover {
665
+ background: #1e40af;
666
+ }
667
+ button.danger {
668
+ background: #dc2626;
669
+ }
670
+ button.danger:hover {
671
+ background: #b91c1c;
672
+ }
673
+ input {
674
+ width: 100%;
675
+ padding: 10px;
676
+ margin-bottom: 15px;
677
+ border: 1px solid #ddd;
678
+ border-radius: 5px;
679
+ font-size: 14px;
680
+ }
681
+ .messages {
682
+ margin-bottom: 20px;
683
+ }
684
+ .message {
685
+ padding: 10px 15px;
686
+ border-radius: 5px;
687
+ margin-bottom: 10px;
688
+ }
689
+ .message.error {
690
+ background: #fee2e2;
691
+ color: #dc2626;
692
+ }
693
+ .message.success {
694
+ background: #d1fae5;
695
+ color: #059669;
696
+ }
697
+ .feature-flag {
698
+ background: #fef3c7;
699
+ border: 2px dashed #f59e0b;
700
+ padding: 15px;
701
+ border-radius: 8px;
702
+ margin: 20px 0;
703
+ }
704
+ code {
705
+ background: #f3f4f6;
706
+ padding: 2px 6px;
707
+ border-radius: 3px;
708
+ font-family: monospace;
709
+ }
710
+ pre {
711
+ background: #1e293b;
712
+ color: #e2e8f0;
713
+ padding: 16px;
714
+ border-radius: 8px;
715
+ overflow-x: auto;
716
+ font-size: 13px;
717
+ }
718
+ .count {
719
+ font-size: 48px;
720
+ font-weight: bold;
721
+ color: #1d4ed8;
722
+ text-align: center;
723
+ padding: 20px;
724
+ }
725
+ table {
726
+ width: 100%;
727
+ border-collapse: collapse;
728
+ margin: 16px 0;
729
+ }
730
+ th, td {
731
+ padding: 12px;
732
+ text-align: left;
733
+ border-bottom: 1px solid #eee;
734
+ }
735
+ th {
736
+ background: #f8fafc;
737
+ font-weight: 600;
738
+ }
739
+ </style>
740
+ </head>
741
+ <body>
742
+ {% if current_user.is_authenticated %}
743
+ <nav>
744
+ <a href="{{ url_for('main.dashboard') }}">Dashboard</a>
745
+ <a href="{{ url_for('main.burrito') }}">Burrito</a>
746
+ <a href="{{ url_for('main.profile') }}">Profile</a>
747
+ <a href="{{ url_for('main.logout') }}" style="float: right;">Logout ({{ current_user.email }})</a>
748
+ </nav>
749
+ {% endif %}
750
+
751
+ <div class="container">
752
+ {% with messages = get_flashed_messages(with_categories=true) %}
753
+ {% if messages %}
754
+ <div class="messages">
755
+ {% for category, message in messages %}
756
+ <div class="message {{ category }}">{{ message }}</div>
757
+ {% endfor %}
758
+ </div>
759
+ {% endif %}
760
+ {% endwith %}
761
+
762
+ {% block content %}{% endblock %}
763
+ </div>
764
+
765
+ {% block scripts %}{% endblock %}
766
+ </body>
767
+ </html>
768
+
769
+ ```
770
+
771
+ ---
772
+
773
+ ## app/templates/burrito.html
774
+
775
+ ```html
776
+ {% extends "base.html" %}
777
+
778
+ {% block title %}Burrito - Amplitude Flask Example{% endblock %}
779
+
780
+ {% block content %}
781
+ <div class="card">
782
+ <h1>Burrito Consideration Tracker</h1>
783
+ <p>This page demonstrates custom event tracking with Amplitude.</p>
784
+
785
+ <div class="count" id="burrito-count">{{ burrito_count }}</div>
786
+ <p style="text-align: center; color: #666;">Times you've considered a burrito</p>
787
+
788
+ <div style="text-align: center; margin-top: 20px;">
789
+ <button onclick="considerBurrito()">Consider a Burrito</button>
790
+ </div>
791
+ </div>
792
+
793
+ <div class="card">
794
+ <h3>Code Example</h3>
795
+ <pre>
796
+ # API endpoint captures the event
797
+ client = get_amplitude_client()
798
+ if client:
799
+ client.track(BaseEvent(
800
+ event_type='Burrito Considered',
801
+ user_id=current_user.email,
802
+ event_properties={'total_considerations': burrito_count},
803
+ ))</pre>
804
+ </div>
805
+ {% endblock %}
806
+
807
+ {% block scripts %}
808
+ <script>
809
+ async function considerBurrito() {
810
+ try {
811
+ const response = await fetch('/api/burrito/consider', {
812
+ method: 'POST',
813
+ headers: {
814
+ 'Content-Type': 'application/json'
815
+ }
816
+ });
817
+ const data = await response.json();
818
+ if (data.success) {
819
+ document.getElementById('burrito-count').textContent = data.count;
820
+ }
821
+ } catch (error) {
822
+ console.error('Error:', error);
823
+ }
824
+ }
825
+ </script>
826
+ {% endblock %}
827
+
828
+ ```
829
+
830
+ ---
831
+
832
+ ## app/templates/dashboard.html
833
+
834
+ ```html
835
+ {% extends "base.html" %}
836
+
837
+ {% block title %}Dashboard - Amplitude Flask Example{% endblock %}
838
+
839
+ {% block content %}
840
+ <div class="card">
841
+ <h1>Dashboard</h1>
842
+ <p>Welcome back, {{ current_user.email }}!</p>
843
+ </div>
844
+
845
+ <div class="card">
846
+ <h2>Amplitude Event Tracking</h2>
847
+ <p>This page is tracked with Amplitude on every visit.</p>
848
+
849
+ <h3 style="margin-top: 20px;">Code Example</h3>
850
+ <pre>
851
+ # Track dashboard view
852
+ client = get_amplitude_client()
853
+ if client:
854
+ client.track(BaseEvent(
855
+ event_type='Dashboard Viewed',
856
+ user_id=current_user.email,
857
+ event_properties={'is_staff': current_user.is_staff},
858
+ ))
859
+
860
+ # TODO: Use Amplitude Experiment for feature flags</pre>
861
+ </div>
862
+ {% endblock %}
863
+
864
+ ```
865
+
866
+ ---
867
+
868
+ ## app/templates/errors/404.html
869
+
870
+ ```html
871
+ {% extends "base.html" %}
872
+
873
+ {% block title %}404 - Page Not Found{% endblock %}
874
+
875
+ {% block content %}
876
+ <div class="card" style="text-align: center; padding: 60px 20px;">
877
+ <h1 style="font-size: 72px; color: #dc2626; margin-bottom: 10px;">404</h1>
878
+ <h2 style="color: #333; margin-bottom: 20px;">Page Not Found</h2>
879
+ <p style="font-size: 18px; color: #666; margin-bottom: 30px;">
880
+ The page you're looking for doesn't exist or has been moved.
881
+ </p>
882
+
883
+ {% if error_id %}
884
+ <div style="background: #fef3c7; border: 1px solid #fbbf24; border-radius: 8px; padding: 15px; margin: 30px 0;">
885
+ <p style="color: #92400e; margin-bottom: 5px; font-weight: 600;">Error Reference ID:</p>
886
+ <code style="background: #fff; padding: 5px 10px; border-radius: 4px; font-family: monospace; color: #1e40af;">{{ error_id }}</code>
887
+ <p style="color: #92400e; margin-top: 10px; font-size: 14px;">
888
+ Share this ID with support if you need assistance.
889
+ </p>
890
+ </div>
891
+ {% endif %}
892
+
893
+ <div style="margin-top: 40px;">
894
+ <a href="{{ url_for('main.home') }}" class="btn" style="margin-right: 10px;">Go to Home</a>
895
+ {% if current_user.is_authenticated %}
896
+ <a href="{{ url_for('main.dashboard') }}" class="btn">Go to Dashboard</a>
897
+ {% endif %}
898
+ </div>
899
+ </div>
900
+ {% endblock %}
901
+
902
+ ```
903
+
904
+ ---
905
+
906
+ ## app/templates/errors/500.html
907
+
908
+ ```html
909
+ {% extends "base.html" %}
910
+
911
+ {% block title %}500 - Internal Server Error{% endblock %}
912
+
913
+ {% block content %}
914
+ <div class="card" style="text-align: center; padding: 60px 20px;">
915
+ <h1 style="font-size: 72px; color: #dc2626; margin-bottom: 10px;">500</h1>
916
+ <h2 style="color: #333; margin-bottom: 20px;">Internal Server Error</h2>
917
+ <p style="font-size: 18px; color: #666; margin-bottom: 30px;">
918
+ Something went wrong on our end. We've been notified and are looking into it.
919
+ </p>
920
+
921
+ {% if error_id %}
922
+ <div style="background: #fef3c7; border: 1px solid #fbbf24; border-radius: 8px; padding: 15px; margin: 30px 0;">
923
+ <p style="color: #92400e; margin-bottom: 5px; font-weight: 600;">Error Reference ID:</p>
924
+ <code style="background: #fff; padding: 5px 10px; border-radius: 4px; font-family: monospace; color: #1e40af;">{{ error_id }}</code>
925
+ <p style="color: #92400e; margin-top: 10px; font-size: 14px;">
926
+ Share this ID with support if you need assistance.
927
+ </p>
928
+ </div>
929
+ {% endif %}
930
+
931
+ {% if error and config.DEBUG %}
932
+ <div style="background: #fee2e2; border: 1px solid #dc2626; border-radius: 8px; padding: 15px; margin: 30px 0; text-align: left;">
933
+ <p style="color: #7f1d1d; margin-bottom: 5px; font-weight: 600;">Debug Information:</p>
934
+ <code style="background: #fff; padding: 10px; border-radius: 4px; font-family: monospace; color: #dc2626; display: block; overflow-x: auto;">{{ error }}</code>
935
+ </div>
936
+ {% endif %}
937
+
938
+ <div style="margin-top: 40px;">
939
+ <a href="{{ url_for('main.home') }}" class="btn" style="margin-right: 10px;">Go to Home</a>
940
+ {% if current_user.is_authenticated %}
941
+ <a href="{{ url_for('main.dashboard') }}" class="btn">Go to Dashboard</a>
942
+ {% endif %}
943
+ </div>
944
+ </div>
945
+ {% endblock %}
946
+
947
+ ```
948
+
949
+ ---
950
+
951
+ ## app/templates/home.html
952
+
953
+ ```html
954
+ {% extends "base.html" %}
955
+
956
+ {% block title %}Login - Amplitude Flask Example{% endblock %}
957
+
958
+ {% block content %}
959
+ <div class="card">
960
+ <h1>Welcome to Amplitude Flask Example</h1>
961
+ <p>This example demonstrates how to integrate Amplitude with a Flask application.</p>
962
+
963
+ <form method="POST">
964
+ <label for="email">Email</label>
965
+ <input type="email" id="email" name="email" required>
966
+
967
+ <label for="password">Password</label>
968
+ <input type="password" id="password" name="password" required>
969
+
970
+ <button type="submit">Login</button>
971
+ </form>
972
+
973
+ <p style="margin-top: 16px; font-size: 14px; color: #666;">
974
+ Don't have an account? <a href="{{ url_for('main.signup') }}">Sign up here</a>
975
+ </p>
976
+ <p style="font-size: 14px; color: #666;">
977
+ <strong>Tip:</strong> Default credentials are admin@example.com/admin
978
+ </p>
979
+ </div>
980
+
981
+ <div class="card">
982
+ <h2>Features Demonstrated</h2>
983
+ <ul style="margin-left: 20px; color: #666;">
984
+ <li>User registration and identification</li>
985
+ <li>Event tracking</li>
986
+ <li>User properties</li>
987
+ </ul>
988
+ </div>
989
+ {% endblock %}
990
+
991
+ ```
992
+
993
+ ---
994
+
995
+ ## app/templates/profile.html
996
+
997
+ ```html
998
+ {% extends "base.html" %}
999
+
1000
+ {% block title %}Profile - Amplitude Flask Example{% endblock %}
1001
+
1002
+ {% block content %}
1003
+ <div class="card">
1004
+ <h1>Your Profile</h1>
1005
+ <p>This page demonstrates event tracking with Amplitude.</p>
1006
+
1007
+ <table>
1008
+ <tr>
1009
+ <th>Email</th>
1010
+ <td>{{ current_user.email }}</td>
1011
+ </tr>
1012
+ <tr>
1013
+ <th>Date Joined</th>
1014
+ <td>{{ current_user.date_joined.strftime('%Y-%m-%d %H:%M') }}</td>
1015
+ </tr>
1016
+ <tr>
1017
+ <th>Staff Status</th>
1018
+ <td>{{ 'Yes' if current_user.is_staff else 'No' }}</td>
1019
+ </tr>
1020
+ </table>
1021
+ </div>
1022
+
1023
+ <div class="card">
1024
+ <h3>Code Example</h3>
1025
+ <pre>
1026
+ # Track profile view
1027
+ client = get_amplitude_client()
1028
+ if client:
1029
+ client.track(BaseEvent(
1030
+ event_type='Profile Viewed',
1031
+ user_id=current_user.email,
1032
+ ))</pre>
1033
+ </div>
1034
+ {% endblock %}
1035
+
1036
+ ```
1037
+
1038
+ ---
1039
+
1040
+ ## app/templates/signup.html
1041
+
1042
+ ```html
1043
+ {% extends "base.html" %}
1044
+
1045
+ {% block title %}Sign Up - Amplitude Flask Example{% endblock %}
1046
+
1047
+ {% block content %}
1048
+ <div class="card">
1049
+ <h1>Create an Account</h1>
1050
+ <p>Sign up to explore the Amplitude Flask integration example.</p>
1051
+
1052
+ <form method="POST">
1053
+ <label for="email">Email *</label>
1054
+ <input type="email" id="email" name="email" required>
1055
+
1056
+ <label for="password">Password *</label>
1057
+ <input type="password" id="password" name="password" required>
1058
+
1059
+ <label for="password_confirm">Confirm Password *</label>
1060
+ <input type="password" id="password_confirm" name="password_confirm" required>
1061
+
1062
+ <button type="submit">Sign Up</button>
1063
+ </form>
1064
+
1065
+ <p style="margin-top: 16px; font-size: 14px; color: #666;">
1066
+ Already have an account? <a href="{{ url_for('main.home') }}">Login here</a>
1067
+ </p>
1068
+ </div>
1069
+
1070
+ <div class="card">
1071
+ <h2>Amplitude Integration</h2>
1072
+ <p>When you sign up, the following Amplitude events are captured:</p>
1073
+ <ul style="margin-left: 20px; color: #666;">
1074
+ <li><code>client.identify()</code> - Sets user properties (email, is_staff, date_joined)</li>
1075
+ <li><code>User Signed Up</code> event - Tracks the signup action</li>
1076
+ </ul>
1077
+
1078
+ <h3 style="margin-top: 20px;">Code Example</h3>
1079
+ <pre>
1080
+ # After creating the user
1081
+ client = get_amplitude_client()
1082
+ if client:
1083
+ identify_obj = Identify()
1084
+ identify_obj.set('email', user.email)
1085
+ identify_obj.set('is_staff', user.is_staff)
1086
+ identify_obj.set('date_joined', user.date_joined.isoformat())
1087
+ client.identify(identify_obj, {'user_id': user.email})
1088
+
1089
+ client.track(BaseEvent(
1090
+ event_type='User Signed Up',
1091
+ user_id=user.email,
1092
+ event_properties={'signup_method': 'form'},
1093
+ ))</pre>
1094
+ </div>
1095
+ {% endblock %}
1096
+
1097
+ ```
1098
+
1099
+ ---
1100
+
1101
+ ## requirements.txt
1102
+
1103
+ ```txt
1104
+ Flask>=3.1.0
1105
+ Flask-Login>=0.6.3
1106
+ Flask-SQLAlchemy>=3.1.0
1107
+ python-dotenv>=1.0.0
1108
+ amplitude-analytics>=1.0.0
1109
+ Werkzeug>=3.0.0
1110
+
1111
+ ```
1112
+
1113
+ ---
1114
+
1115
+ ## run.py
1116
+
1117
+ ```py
1118
+ """Development server entry point."""
1119
+
1120
+ from app import create_app
1121
+
1122
+ app = create_app()
1123
+
1124
+ if __name__ == "__main__":
1125
+ app.run(port=5001)
1126
+
1127
+ ```
1128
+
1129
+ ---
1130
+