@amplitude/wizard 1.0.0-beta.2 → 1.0.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 (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 +6 -5
  9. package/dist/src/lib/constants.js +13 -13
  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 +6 -6
  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,899 @@
1
+ # Amplitude Angular Example Project
2
+
3
+ Repository: https://github.com/amplitude/context-hub
4
+ Path: basics/angular
5
+
6
+ ---
7
+
8
+ ## README.md
9
+
10
+ # Amplitude Angular Example
11
+
12
+ This is an [Angular](https://angular.dev/) example demonstrating Amplitude integration with product analytics.
13
+
14
+ The app runs in the browser and uses the [Browser Unified SDK (npm)](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk#unified-sdk-npm): `@amplitude/unified` with one `initAll(apiKey)` call (see `AmplitudeService`). [Initialize the Unified SDK](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk#initialize-the-unified-sdk) describes that call as initializing every product bundled into the npm package; use an optional second argument for [Unified SDK configuration](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk#configuration) (`serverZone`, `instanceName`, and the `analytics`, `sessionReplay`, `experiment`, and `engagement` sections). `analytics` settings match [Browser SDK 2](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2#initialize-the-sdk).
15
+
16
+ The `experiment` section configures **Feature Experiment** (`@amplitude/experiment-js-client`). Per Amplitude’s [product support table](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk#product-support-by-installation-method), **Web Experiment** (`@amplitude/experiment-tag`, including the visual editor) is listed for the Unified **CDN** script, not the Unified **npm** row—the npm `experiment` options still cover code-based flags and the Experiment JS client bundled with `@amplitude/unified`.
17
+
18
+ This sample does not send events from Node. For API or server-only analytics, use [`@amplitude/analytics-node`](https://www.npmjs.com/package/@amplitude/analytics-node).
19
+
20
+ ## Features
21
+
22
+ - **Product analytics**: Track user events and behaviors
23
+ - **User authentication**: Demo login system with Amplitude user identification
24
+ - **SSR-safe**: Uses platform checks for browser-only Amplitude calls
25
+
26
+ ## Getting started
27
+
28
+ ### 1. Install dependencies
29
+
30
+ ```bash
31
+ pnpm install
32
+ ```
33
+
34
+ ### 2. Configure environment variables
35
+
36
+ Create a `.env` file in the root directory:
37
+
38
+ ```bash
39
+ NG_APP_AMPLITUDE_API_KEY=your_amplitude_api_key
40
+ ```
41
+
42
+ Get your Amplitude API key from your [Amplitude project settings](https://app.amplitude.com/).
43
+
44
+ ### 3. Run the development server
45
+
46
+ ```bash
47
+ pnpm start
48
+ ```
49
+
50
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the app.
51
+
52
+ ## Project structure
53
+
54
+ ```
55
+ src/
56
+ ├── app/
57
+ │ ├── components/
58
+ │ │ └── header/ # Navigation header with auth state
59
+ │ ├── pages/
60
+ │ │ ├── home/ # Home/Login page
61
+ │ │ ├── burrito/ # Demo feature page with event tracking
62
+ │ │ └── profile/ # User profile page
63
+ │ ├── services/
64
+ │ │ ├── amplitude.service.ts # Amplitude service wrapper (SSR-safe)
65
+ │ │ └── auth.service.ts # Auth service with Amplitude integration
66
+ │ ├── guards/
67
+ │ │ └── auth.guard.ts # Route guard for protected pages
68
+ │ ├── app.component.ts # Root component with Amplitude init
69
+ │ ├── app.routes.ts # Route definitions
70
+ │ └── app.config.ts # App configuration
71
+ ├── environments/
72
+ │ ├── environment.ts # Dev environment config
73
+ │ └── environment.production.ts
74
+ └── main.ts # App entry point
75
+ ```
76
+
77
+ ## Key integration points
78
+
79
+ ### Amplitude service (services/amplitude.service.ts)
80
+
81
+ A wrapper service that handles SSR safety and provides access to the Amplitude instance:
82
+
83
+ ```typescript
84
+ import { Injectable, inject, PLATFORM_ID } from '@angular/core';
85
+ import { isPlatformBrowser } from '@angular/common';
86
+ import * as amplitude from '@amplitude/unified';
87
+
88
+ @Injectable({ providedIn: 'root' })
89
+ export class AmplitudeService {
90
+ private readonly platformId = inject(PLATFORM_ID);
91
+ private initialized = false;
92
+
93
+ get amplitude(): typeof amplitude {
94
+ if (isPlatformBrowser(this.platformId) && this.initialized) {
95
+ return amplitude;
96
+ }
97
+ return new Proxy({} as typeof amplitude, {
98
+ get: () => () => undefined,
99
+ });
100
+ }
101
+
102
+ init(apiKey: string): void {
103
+ if (isPlatformBrowser(this.platformId) && !this.initialized) {
104
+ void amplitude.initAll(apiKey);
105
+ this.initialized = true;
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Amplitude initialization (app.component.ts)
112
+
113
+ Amplitude is initialized in the root component's `ngOnInit`:
114
+
115
+ ```typescript
116
+ import { AmplitudeService } from './services/amplitude.service';
117
+ import { environment } from '../environments/environment';
118
+
119
+ export class AppComponent implements OnInit {
120
+ private readonly amplitudeService = inject(AmplitudeService);
121
+
122
+ ngOnInit(): void {
123
+ this.amplitudeService.init(environment.amplitudeApiKey);
124
+ }
125
+ }
126
+ ```
127
+
128
+ ### User identification (services/auth.service.ts)
129
+
130
+ ```typescript
131
+ import { AmplitudeService } from './amplitude.service';
132
+ import { Identify } from '@amplitude/unified';
133
+
134
+ const amplitudeService = inject(AmplitudeService);
135
+
136
+ amplitudeService.amplitude.setUserId(username);
137
+ const identifyObj = new Identify();
138
+ identifyObj.set('username', username);
139
+ amplitudeService.amplitude.identify(identifyObj);
140
+ ```
141
+
142
+ ### Event tracking (pages/burrito/burrito.component.ts)
143
+
144
+ ```typescript
145
+ import { AmplitudeService } from '../../services/amplitude.service';
146
+
147
+ const amplitudeService = inject(AmplitudeService);
148
+
149
+ amplitudeService.amplitude.track('Burrito Considered', {
150
+ total_considerations: count,
151
+ username: username,
152
+ });
153
+ ```
154
+
155
+ ## Angular-specific details
156
+
157
+ This example uses Angular 21 with modern features:
158
+
159
+ 1. **Standalone components**: No NgModules, all components use `standalone: true`
160
+ 2. **Signals**: Reactive state management with Angular signals
161
+ 3. **SSR support**: Uses `isPlatformBrowser()` checks for SSR safety
162
+ 4. **Dependency injection**: Amplitude wrapped in an injectable service
163
+ 5. **Environment files**: Generated from `.env` at build time via prebuild script
164
+
165
+ ## Learn more
166
+
167
+ - [Amplitude Documentation](https://www.docs.developers.amplitude.com/)
168
+ - [Angular Documentation](https://angular.dev/)
169
+ - [Amplitude Browser SDK](https://www.docs.developers.amplitude.com/data/sdks/browser-2/)
170
+
171
+ ---
172
+
173
+ ## .env.example
174
+
175
+ ```example
176
+ NG_APP_AMPLITUDE_API_KEY=your_amplitude_api_key
177
+
178
+ ```
179
+
180
+ ---
181
+
182
+ ## src/app/app.component.ts
183
+
184
+ ```ts
185
+ import {
186
+ Component,
187
+ inject,
188
+ OnInit,
189
+ PLATFORM_ID,
190
+ ChangeDetectionStrategy,
191
+ } from '@angular/core';
192
+ import { isPlatformBrowser } from '@angular/common';
193
+ import { RouterOutlet } from '@angular/router';
194
+ import { HeaderComponent } from './components/header/header.component';
195
+ import { AmplitudeService } from './services/amplitude.service';
196
+ import { environment } from '../environments/environment';
197
+
198
+ @Component({
199
+ selector: 'app-root',
200
+ imports: [RouterOutlet, HeaderComponent],
201
+ template: `
202
+ <app-header />
203
+ <router-outlet />
204
+ `,
205
+ changeDetection: ChangeDetectionStrategy.OnPush,
206
+ })
207
+ export class AppComponent implements OnInit {
208
+ private readonly platformId = inject(PLATFORM_ID);
209
+ private readonly amplitudeService = inject(AmplitudeService);
210
+
211
+ ngOnInit(): void {
212
+ if (isPlatformBrowser(this.platformId)) {
213
+ this.amplitudeService.init(environment.amplitudeApiKey);
214
+ }
215
+ }
216
+ }
217
+
218
+ ```
219
+
220
+ ---
221
+
222
+ ## src/app/app.config.server.ts
223
+
224
+ ```ts
225
+ import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
226
+ import { provideServerRendering, withRoutes } from '@angular/ssr';
227
+ import { appConfig } from './app.config';
228
+ import { serverRoutes } from './app.routes.server';
229
+
230
+ const serverConfig: ApplicationConfig = {
231
+ providers: [provideServerRendering(withRoutes(serverRoutes))],
232
+ };
233
+
234
+ export const config = mergeApplicationConfig(appConfig, serverConfig);
235
+
236
+ ```
237
+
238
+ ---
239
+
240
+ ## src/app/app.config.ts
241
+
242
+ ```ts
243
+ import { ApplicationConfig } from '@angular/core';
244
+ import { provideRouter, withComponentInputBinding } from '@angular/router';
245
+ import {
246
+ provideClientHydration,
247
+ withEventReplay,
248
+ } from '@angular/platform-browser';
249
+ import { provideHttpClient, withFetch } from '@angular/common/http';
250
+ import { routes } from './app.routes';
251
+
252
+ export const appConfig: ApplicationConfig = {
253
+ providers: [
254
+ provideRouter(routes, withComponentInputBinding()),
255
+ provideHttpClient(withFetch()),
256
+ provideClientHydration(withEventReplay()),
257
+ ],
258
+ };
259
+
260
+ ```
261
+
262
+ ---
263
+
264
+ ## src/app/app.routes.server.ts
265
+
266
+ ```ts
267
+ import { RenderMode, ServerRoute } from '@angular/ssr';
268
+
269
+ export const serverRoutes: ServerRoute[] = [
270
+ {
271
+ path: '',
272
+ renderMode: RenderMode.Server,
273
+ },
274
+ {
275
+ path: 'burrito',
276
+ renderMode: RenderMode.Client, // Protected route, render client-side
277
+ },
278
+ {
279
+ path: 'profile',
280
+ renderMode: RenderMode.Client, // Protected route, render client-side
281
+ },
282
+ {
283
+ path: '**',
284
+ renderMode: RenderMode.Server,
285
+ },
286
+ ];
287
+
288
+ ```
289
+
290
+ ---
291
+
292
+ ## src/app/app.routes.ts
293
+
294
+ ```ts
295
+ import { Routes } from '@angular/router';
296
+ import { authGuard } from './guards/auth.guard';
297
+
298
+ export const routes: Routes = [
299
+ {
300
+ path: '',
301
+ title: 'Burrito Consideration App',
302
+ loadComponent: () =>
303
+ import('./pages/home/home.component').then((m) => m.HomeComponent),
304
+ },
305
+ {
306
+ path: 'burrito',
307
+ title: 'Burrito Consideration - Burrito Consideration App',
308
+ loadComponent: () =>
309
+ import('./pages/burrito/burrito.component').then(
310
+ (m) => m.BurritoComponent
311
+ ),
312
+ canActivate: [authGuard],
313
+ },
314
+ {
315
+ path: 'profile',
316
+ title: 'Profile - Burrito Consideration App',
317
+ loadComponent: () =>
318
+ import('./pages/profile/profile.component').then(
319
+ (m) => m.ProfileComponent
320
+ ),
321
+ canActivate: [authGuard],
322
+ },
323
+ {
324
+ path: '**',
325
+ redirectTo: '',
326
+ },
327
+ ];
328
+
329
+ ```
330
+
331
+ ---
332
+
333
+ ## src/app/components/header/header.component.ts
334
+
335
+ ```ts
336
+ import { Component, inject, ChangeDetectionStrategy } from '@angular/core';
337
+ import { RouterLink } from '@angular/router';
338
+ import { AuthService } from '../../services/auth.service';
339
+
340
+ @Component({
341
+ selector: 'app-header',
342
+ imports: [RouterLink],
343
+ template: `
344
+ <a class="skip-link" href="#main-content">Skip to main content</a>
345
+ <header class="header" role="banner">
346
+ <div class="header-container">
347
+ <nav aria-label="Main navigation">
348
+ <a routerLink="/">Home</a>
349
+ @if (auth.isAuthenticated()) {
350
+ <a routerLink="/burrito">Burrito Consideration</a>
351
+ <a routerLink="/profile">Profile</a>
352
+ }
353
+ </nav>
354
+ <div class="user-section">
355
+ @if (auth.user(); as user) {
356
+ <span>Welcome, {{ user.username }}!</span>
357
+ <button (click)="auth.logout()" class="btn-logout">Logout</button>
358
+ } @else {
359
+ <span>Not logged in</span>
360
+ }
361
+ </div>
362
+ </div>
363
+ </header>
364
+ `,
365
+ changeDetection: ChangeDetectionStrategy.OnPush,
366
+ })
367
+ export class HeaderComponent {
368
+ readonly auth = inject(AuthService);
369
+ }
370
+
371
+ ```
372
+
373
+ ---
374
+
375
+ ## src/app/guards/auth.guard.ts
376
+
377
+ ```ts
378
+ import { inject } from '@angular/core';
379
+ import { Router, CanActivateFn } from '@angular/router';
380
+ import { AuthService } from '../services/auth.service';
381
+
382
+ export const authGuard: CanActivateFn = () => {
383
+ const auth = inject(AuthService);
384
+ const router = inject(Router);
385
+
386
+ if (auth.isAuthenticated()) {
387
+ return true;
388
+ }
389
+
390
+ return router.createUrlTree(['/']);
391
+ };
392
+
393
+ ```
394
+
395
+ ---
396
+
397
+ ## src/app/pages/burrito/burrito.component.ts
398
+
399
+ ```ts
400
+ import {
401
+ Component,
402
+ inject,
403
+ signal,
404
+ ChangeDetectionStrategy,
405
+ } from '@angular/core';
406
+ import { Router } from '@angular/router';
407
+ import { AuthService } from '../../services/auth.service';
408
+ import { AmplitudeService } from '../../services/amplitude.service';
409
+
410
+ @Component({
411
+ selector: 'app-burrito',
412
+ template: `
413
+ <main id="main-content" tabindex="-1">
414
+ <div class="container">
415
+ <h1>Burrito consideration zone</h1>
416
+ <p>Take a moment to truly consider the potential of burritos.</p>
417
+
418
+ <div style="text-align: center">
419
+ <button (click)="handleConsideration()" class="btn-burrito">
420
+ I have considered the burrito potential
421
+ </button>
422
+
423
+ @if (hasConsidered()) {
424
+ <p class="success" role="status" aria-live="polite">
425
+ Thank you for your consideration! Count:
426
+ {{ auth.user()?.burritoConsiderations }}
427
+ </p>
428
+ }
429
+ </div>
430
+
431
+ <div class="stats">
432
+ <h3>Consideration stats</h3>
433
+ <p>Total considerations: {{ auth.user()?.burritoConsiderations }}</p>
434
+ </div>
435
+ </div>
436
+ </main>
437
+ `,
438
+ changeDetection: ChangeDetectionStrategy.OnPush,
439
+ })
440
+ export class BurritoComponent {
441
+ readonly auth = inject(AuthService);
442
+ private readonly amplitudeService = inject(AmplitudeService);
443
+ private readonly router = inject(Router);
444
+
445
+ hasConsidered = signal(false);
446
+
447
+ constructor() {
448
+ // Redirect if not authenticated
449
+ if (!this.auth.isAuthenticated()) {
450
+ this.router.navigate(['/']);
451
+ }
452
+ }
453
+
454
+ handleConsideration(): void {
455
+ const user = this.auth.user();
456
+ if (!user) return;
457
+
458
+ this.auth.incrementBurritoConsiderations();
459
+ this.hasConsidered.set(true);
460
+ setTimeout(() => this.hasConsidered.set(false), 2000);
461
+
462
+ this.amplitudeService.amplitude.track('Burrito Considered', {
463
+ total_considerations: user.burritoConsiderations + 1,
464
+ username: user.username,
465
+ });
466
+ }
467
+ }
468
+
469
+ ```
470
+
471
+ ---
472
+
473
+ ## src/app/pages/home/home.component.ts
474
+
475
+ ```ts
476
+ import {
477
+ Component,
478
+ inject,
479
+ signal,
480
+ ChangeDetectionStrategy,
481
+ } from '@angular/core';
482
+ import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
483
+ import { AuthService } from '../../services/auth.service';
484
+
485
+ @Component({
486
+ selector: 'app-home',
487
+ imports: [ReactiveFormsModule],
488
+ template: `
489
+ <main id="main-content" tabindex="-1">
490
+ @if (auth.user(); as user) {
491
+ <div class="container">
492
+ <h1>Welcome back, {{ user.username }}!</h1>
493
+ <p>You are now logged in. Feel free to explore:</p>
494
+ <ul>
495
+ <li>Consider the potential of burritos</li>
496
+ <li>View your profile and statistics</li>
497
+ </ul>
498
+ </div>
499
+ } @else {
500
+ <div class="container">
501
+ <h1>Welcome to Burrito Consideration App</h1>
502
+ <p>Please sign in to begin your burrito journey</p>
503
+
504
+ <form [formGroup]="loginForm" (ngSubmit)="handleSubmit()" class="form">
505
+ <div class="form-group">
506
+ <label for="username">Username:</label>
507
+ <input
508
+ type="text"
509
+ id="username"
510
+ formControlName="username"
511
+ placeholder="Enter any username"
512
+ autocomplete="username"
513
+ />
514
+ </div>
515
+
516
+ <div class="form-group">
517
+ <label for="password">Password:</label>
518
+ <input
519
+ type="password"
520
+ id="password"
521
+ formControlName="password"
522
+ placeholder="Enter any password"
523
+ autocomplete="current-password"
524
+ />
525
+ </div>
526
+
527
+ @if (error()) {
528
+ <p class="error" role="alert">{{ error() }}</p>
529
+ }
530
+
531
+ <button type="submit" class="btn-primary">Sign In</button>
532
+ </form>
533
+
534
+ <p class="note">
535
+ Note: This is a demo app. Use any username and password to sign in.
536
+ </p>
537
+ </div>
538
+ }
539
+ </main>
540
+ `,
541
+ changeDetection: ChangeDetectionStrategy.OnPush,
542
+ })
543
+ export class HomeComponent {
544
+ private readonly fb = inject(FormBuilder);
545
+ readonly auth = inject(AuthService);
546
+
547
+ loginForm = this.fb.nonNullable.group({
548
+ username: ['', Validators.required],
549
+ password: ['', Validators.required],
550
+ });
551
+
552
+ error = signal('');
553
+
554
+ handleSubmit(): void {
555
+ this.error.set('');
556
+
557
+ if (this.loginForm.invalid) {
558
+ this.error.set('Please provide both username and password');
559
+ return;
560
+ }
561
+
562
+ const { username, password } = this.loginForm.getRawValue();
563
+
564
+ const success = this.auth.login(username, password);
565
+ if (success) {
566
+ this.loginForm.reset();
567
+ } else {
568
+ this.error.set('Please provide both username and password');
569
+ }
570
+ }
571
+ }
572
+
573
+ ```
574
+
575
+ ---
576
+
577
+ ## src/app/pages/profile/profile.component.ts
578
+
579
+ ```ts
580
+ import {
581
+ Component,
582
+ inject,
583
+ computed,
584
+ ChangeDetectionStrategy,
585
+ } from '@angular/core';
586
+ import { Router } from '@angular/router';
587
+ import { AuthService } from '../../services/auth.service';
588
+
589
+ @Component({
590
+ selector: 'app-profile',
591
+ template: `
592
+ <main id="main-content" tabindex="-1">
593
+ <div class="container">
594
+ <h1>User Profile</h1>
595
+
596
+ <div class="stats">
597
+ <h2>Your Information</h2>
598
+ <p><strong>Username:</strong> {{ auth.user()?.username }}</p>
599
+ <p>
600
+ <strong>Burrito Considerations:</strong>
601
+ {{ auth.user()?.burritoConsiderations }}
602
+ </p>
603
+ </div>
604
+
605
+ <div style="margin-top: 2rem">
606
+ <h3>Your Burrito Journey</h3>
607
+ <p>{{ journeyMessage() }}</p>
608
+ </div>
609
+ </div>
610
+ </main>
611
+ `,
612
+ changeDetection: ChangeDetectionStrategy.OnPush,
613
+ })
614
+ export class ProfileComponent {
615
+ readonly auth = inject(AuthService);
616
+ private readonly router = inject(Router);
617
+
618
+ journeyMessage = computed(() => {
619
+ const count = this.auth.user()?.burritoConsiderations ?? 0;
620
+
621
+ if (count === 0) {
622
+ return "You haven't considered any burritos yet. Visit the Burrito Consideration page to start!";
623
+ } else if (count === 1) {
624
+ return "You've considered the burrito potential once. Keep going!";
625
+ } else if (count < 5) {
626
+ return "You're getting the hang of burrito consideration!";
627
+ } else if (count < 10) {
628
+ return "You're becoming a burrito consideration expert!";
629
+ } else {
630
+ return 'You are a true burrito consideration master!';
631
+ }
632
+ });
633
+
634
+ constructor() {
635
+ if (!this.auth.isAuthenticated()) {
636
+ this.router.navigate(['/']);
637
+ }
638
+ }
639
+ }
640
+
641
+ ```
642
+
643
+ ---
644
+
645
+ ## src/app/services/amplitude.service.ts
646
+
647
+ ```ts
648
+ import { Injectable, inject, PLATFORM_ID } from '@angular/core';
649
+ import { isPlatformBrowser } from '@angular/common';
650
+ import * as amplitude from '@amplitude/unified';
651
+
652
+ @Injectable({ providedIn: 'root' })
653
+ export class AmplitudeService {
654
+ private readonly platformId = inject(PLATFORM_ID);
655
+ private initialized = false;
656
+
657
+ /**
658
+ * The amplitude instance. Use this directly to call amplitude methods.
659
+ * Returns the actual amplitude instance on browser, or a no-op proxy on server.
660
+ */
661
+ get amplitude(): typeof amplitude {
662
+ if (isPlatformBrowser(this.platformId) && this.initialized) {
663
+ return amplitude;
664
+ }
665
+ // Return a no-op proxy for SSR safety
666
+ return new Proxy({} as typeof amplitude, {
667
+ get: () => () => undefined,
668
+ });
669
+ }
670
+
671
+ init(apiKey: string): void {
672
+ if (isPlatformBrowser(this.platformId) && !this.initialized) {
673
+ void amplitude.initAll(apiKey);
674
+ this.initialized = true;
675
+ }
676
+ }
677
+ }
678
+
679
+ ```
680
+
681
+ ---
682
+
683
+ ## src/app/services/auth.service.ts
684
+
685
+ ```ts
686
+ import {
687
+ Injectable,
688
+ signal,
689
+ computed,
690
+ inject,
691
+ PLATFORM_ID,
692
+ } from '@angular/core';
693
+ import { isPlatformBrowser } from '@angular/common';
694
+ import { AmplitudeService } from './amplitude.service';
695
+ import { Identify } from '@amplitude/unified';
696
+
697
+ export interface User {
698
+ username: string;
699
+ burritoConsiderations: number;
700
+ }
701
+
702
+ @Injectable({ providedIn: 'root' })
703
+ export class AuthService {
704
+ private readonly platformId = inject(PLATFORM_ID);
705
+ private readonly amplitudeService = inject(AmplitudeService);
706
+
707
+ // In-memory user store (matches TanStack behavior)
708
+ private readonly users = new Map<string, User>();
709
+
710
+ // Signals for reactive state
711
+ private readonly _user = signal<User | null>(null);
712
+
713
+ // Public computed signals
714
+ readonly user = this._user.asReadonly();
715
+ readonly isAuthenticated = computed(() => this._user() !== null);
716
+
717
+ constructor() {
718
+ // Initialize from localStorage on browser
719
+ if (isPlatformBrowser(this.platformId)) {
720
+ const storedUsername = localStorage.getItem('currentUser');
721
+ if (storedUsername) {
722
+ const existingUser = this.users.get(storedUsername);
723
+ if (existingUser) {
724
+ this._user.set(existingUser);
725
+ }
726
+ }
727
+ }
728
+ }
729
+
730
+ login(username: string, password: string): boolean {
731
+ if (!username || !password) {
732
+ return false;
733
+ }
734
+
735
+ // Get or create user in local map (no API call)
736
+ let user = this.users.get(username);
737
+ const isNewUser = !user;
738
+
739
+ if (!user) {
740
+ user = { username, burritoConsiderations: 0 };
741
+ this.users.set(username, user);
742
+ }
743
+
744
+ this._user.set(user);
745
+
746
+ if (isPlatformBrowser(this.platformId)) {
747
+ localStorage.setItem('currentUser', username);
748
+ }
749
+
750
+ // Amplitude identification (client-side only)
751
+ this.amplitudeService.amplitude.setUserId(username);
752
+ const identifyObj = new Identify();
753
+ identifyObj.set('username', username);
754
+ identifyObj.set('isNewUser', isNewUser);
755
+ this.amplitudeService.amplitude.identify(identifyObj);
756
+
757
+ this.amplitudeService.amplitude.track('User Logged In', {
758
+ username,
759
+ isNewUser,
760
+ });
761
+
762
+ return true;
763
+ }
764
+
765
+ logout(): void {
766
+ this.amplitudeService.amplitude.track('User Logged Out');
767
+ this.amplitudeService.amplitude.reset();
768
+
769
+ this._user.set(null);
770
+
771
+ if (isPlatformBrowser(this.platformId)) {
772
+ localStorage.removeItem('currentUser');
773
+ }
774
+ }
775
+
776
+ incrementBurritoConsiderations(): void {
777
+ const currentUser = this._user();
778
+ if (currentUser) {
779
+ const updated = {
780
+ ...currentUser,
781
+ burritoConsiderations: currentUser.burritoConsiderations + 1,
782
+ };
783
+ this.users.set(currentUser.username, updated);
784
+ this._user.set(updated);
785
+ }
786
+ }
787
+ }
788
+
789
+ ```
790
+
791
+ ---
792
+
793
+ ## src/env.d.ts
794
+
795
+ ```ts
796
+ // Define the type of the environment variables.
797
+ declare interface Env {
798
+ readonly NODE_ENV: string;
799
+ readonly NG_APP_AMPLITUDE_API_KEY: string;
800
+ }
801
+
802
+ // Use import.meta.env.YOUR_ENV_VAR in your code.
803
+ declare interface ImportMeta {
804
+ readonly env: Env;
805
+ }
806
+
807
+ ```
808
+
809
+ ---
810
+
811
+ ## src/environments/environment.prod.ts
812
+
813
+ ```ts
814
+ export const environment = {
815
+ production: true,
816
+ amplitudeApiKey: import.meta.env['NG_APP_AMPLITUDE_API_KEY'] || '',
817
+ };
818
+
819
+ ```
820
+
821
+ ---
822
+
823
+ ## src/environments/environment.production.ts
824
+
825
+ ```ts
826
+ export const environment = {
827
+ production: true,
828
+ amplitudeApiKey: import.meta.env['NG_APP_AMPLITUDE_API_KEY'] || '',
829
+ };
830
+
831
+ ```
832
+
833
+ ---
834
+
835
+ ## src/environments/environment.ts
836
+
837
+ ```ts
838
+ export const environment = {
839
+ production: false,
840
+ amplitudeApiKey: import.meta.env['NG_APP_AMPLITUDE_API_KEY'] || '',
841
+ };
842
+
843
+ ```
844
+
845
+ ---
846
+
847
+ ## src/index.html
848
+
849
+ ```html
850
+ <!doctype html>
851
+ <html lang="en">
852
+ <head>
853
+ <meta charset="utf-8">
854
+ <title>Burrito Consideration App</title>
855
+ <base href="/">
856
+ <meta name="viewport" content="width=device-width, initial-scale=1">
857
+ <meta name="description" content="Consider the potential of burritos">
858
+ <link rel="icon" type="image/x-icon" href="favicon.ico">
859
+ </head>
860
+ <body>
861
+ <app-root></app-root>
862
+ </body>
863
+ </html>
864
+
865
+ ```
866
+
867
+ ---
868
+
869
+ ## src/main.server.ts
870
+
871
+ ```ts
872
+ import { bootstrapApplication, BootstrapContext } from '@angular/platform-browser';
873
+ import { AppComponent } from './app/app.component';
874
+ import { config } from './app/app.config.server';
875
+
876
+ const bootstrap = (context: BootstrapContext) =>
877
+ bootstrapApplication(AppComponent, config, context);
878
+
879
+ export default bootstrap;
880
+
881
+ ```
882
+
883
+ ---
884
+
885
+ ## src/main.ts
886
+
887
+ ```ts
888
+ import { bootstrapApplication } from '@angular/platform-browser';
889
+ import { appConfig } from './app/app.config';
890
+ import { AppComponent } from './app/app.component';
891
+
892
+ bootstrapApplication(AppComponent, appConfig).catch((err) =>
893
+ console.error(err)
894
+ );
895
+
896
+ ```
897
+
898
+ ---
899
+