moai-adk 0.25.4__py3-none-any.whl → 0.32.8__py3-none-any.whl

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.

Potentially problematic release.


This version of moai-adk might be problematic. Click here for more details.

Files changed (378) hide show
  1. moai_adk/__init__.py +2 -5
  2. moai_adk/__main__.py +114 -82
  3. moai_adk/cli/__init__.py +6 -1
  4. moai_adk/cli/commands/__init__.py +1 -3
  5. moai_adk/cli/commands/analyze.py +5 -16
  6. moai_adk/cli/commands/doctor.py +6 -18
  7. moai_adk/cli/commands/init.py +56 -125
  8. moai_adk/cli/commands/language.py +14 -35
  9. moai_adk/cli/commands/status.py +9 -15
  10. moai_adk/cli/commands/update.py +1555 -190
  11. moai_adk/cli/prompts/init_prompts.py +112 -56
  12. moai_adk/cli/spec_status.py +263 -0
  13. moai_adk/cli/ui/__init__.py +44 -0
  14. moai_adk/cli/ui/progress.py +422 -0
  15. moai_adk/cli/ui/prompts.py +389 -0
  16. moai_adk/cli/ui/theme.py +129 -0
  17. moai_adk/cli/worktree/__init__.py +27 -0
  18. moai_adk/cli/worktree/__main__.py +31 -0
  19. moai_adk/cli/worktree/cli.py +672 -0
  20. moai_adk/cli/worktree/exceptions.py +89 -0
  21. moai_adk/cli/worktree/manager.py +490 -0
  22. moai_adk/cli/worktree/models.py +65 -0
  23. moai_adk/cli/worktree/registry.py +128 -0
  24. moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
  25. moai_adk/core/analysis/session_analyzer.py +17 -56
  26. moai_adk/core/claude_integration.py +26 -54
  27. moai_adk/core/command_helpers.py +10 -10
  28. moai_adk/core/comprehensive_monitoring_system.py +1183 -0
  29. moai_adk/core/config/auto_spec_config.py +5 -11
  30. moai_adk/core/config/migration.py +19 -9
  31. moai_adk/core/config/unified.py +436 -0
  32. moai_adk/core/context_manager.py +6 -12
  33. moai_adk/core/enterprise_features.py +1404 -0
  34. moai_adk/core/error_recovery_system.py +725 -112
  35. moai_adk/core/event_driven_hook_system.py +1371 -0
  36. moai_adk/core/git/__init__.py +8 -0
  37. moai_adk/core/git/branch_manager.py +3 -11
  38. moai_adk/core/git/checkpoint.py +1 -3
  39. moai_adk/core/git/conflict_detector.py +413 -0
  40. moai_adk/core/git/manager.py +91 -1
  41. moai_adk/core/hooks/post_tool_auto_spec_completion.py +56 -80
  42. moai_adk/core/input_validation_middleware.py +1006 -0
  43. moai_adk/core/integration/engine.py +6 -18
  44. moai_adk/core/integration/integration_tester.py +10 -9
  45. moai_adk/core/integration/utils.py +1 -1
  46. moai_adk/core/issue_creator.py +10 -28
  47. moai_adk/core/jit_context_loader.py +956 -0
  48. moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
  49. moai_adk/core/language_config_resolver.py +485 -0
  50. moai_adk/core/language_validator.py +28 -41
  51. moai_adk/core/mcp/setup.py +15 -12
  52. moai_adk/core/merge/__init__.py +9 -0
  53. moai_adk/core/merge/analyzer.py +481 -0
  54. moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
  55. moai_adk/core/migration/backup_manager.py +78 -9
  56. moai_adk/core/migration/custom_element_scanner.py +358 -0
  57. moai_adk/core/migration/file_migrator.py +8 -17
  58. moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
  59. moai_adk/core/migration/selective_restorer.py +470 -0
  60. moai_adk/core/migration/template_utils.py +74 -0
  61. moai_adk/core/migration/user_selection_ui.py +338 -0
  62. moai_adk/core/migration/version_detector.py +6 -10
  63. moai_adk/core/migration/version_migrator.py +3 -3
  64. moai_adk/core/performance/cache_system.py +8 -10
  65. moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
  66. moai_adk/core/project/checker.py +2 -4
  67. moai_adk/core/project/detector.py +1 -3
  68. moai_adk/core/project/initializer.py +135 -23
  69. moai_adk/core/project/phase_executor.py +54 -81
  70. moai_adk/core/project/validator.py +6 -12
  71. moai_adk/core/quality/trust_checker.py +9 -27
  72. moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
  73. moai_adk/core/robust_json_parser.py +611 -0
  74. moai_adk/core/rollback_manager.py +73 -148
  75. moai_adk/core/session_manager.py +10 -26
  76. moai_adk/core/skill_loading_system.py +579 -0
  77. moai_adk/core/spec/confidence_scoring.py +31 -100
  78. moai_adk/core/spec/ears_template_engine.py +351 -286
  79. moai_adk/core/spec/quality_validator.py +35 -69
  80. moai_adk/core/spec_status_manager.py +64 -74
  81. moai_adk/core/template/backup.py +45 -20
  82. moai_adk/core/template/config.py +112 -39
  83. moai_adk/core/template/merger.py +11 -19
  84. moai_adk/core/template/processor.py +253 -149
  85. moai_adk/core/template_engine.py +73 -40
  86. moai_adk/core/template_variable_synchronizer.py +417 -0
  87. moai_adk/core/unified_permission_manager.py +745 -0
  88. moai_adk/core/user_behavior_analytics.py +851 -0
  89. moai_adk/core/version_sync.py +429 -0
  90. moai_adk/foundation/__init__.py +56 -0
  91. moai_adk/foundation/backend.py +1027 -0
  92. moai_adk/foundation/database.py +1115 -0
  93. moai_adk/foundation/devops.py +1585 -0
  94. moai_adk/foundation/ears.py +431 -0
  95. moai_adk/foundation/frontend.py +870 -0
  96. moai_adk/foundation/git/commit_templates.py +4 -12
  97. moai_adk/foundation/git.py +376 -0
  98. moai_adk/foundation/langs.py +484 -0
  99. moai_adk/foundation/ml_ops.py +1162 -0
  100. moai_adk/foundation/testing.py +1524 -0
  101. moai_adk/foundation/trust/trust_principles.py +23 -72
  102. moai_adk/foundation/trust/validation_checklist.py +57 -162
  103. moai_adk/project/__init__.py +0 -0
  104. moai_adk/project/configuration.py +1084 -0
  105. moai_adk/project/documentation.py +566 -0
  106. moai_adk/project/schema.py +447 -0
  107. moai_adk/statusline/alfred_detector.py +1 -3
  108. moai_adk/statusline/config.py +13 -4
  109. moai_adk/statusline/enhanced_output_style_detector.py +23 -15
  110. moai_adk/statusline/main.py +51 -15
  111. moai_adk/statusline/renderer.py +104 -48
  112. moai_adk/statusline/update_checker.py +3 -9
  113. moai_adk/statusline/version_reader.py +140 -46
  114. moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +549 -0
  115. moai_adk/templates/.claude/agents/moai/builder-agent.md +445 -0
  116. moai_adk/templates/.claude/agents/moai/builder-command.md +1132 -0
  117. moai_adk/templates/.claude/agents/moai/builder-skill.md +601 -0
  118. moai_adk/templates/.claude/agents/moai/expert-backend.md +831 -0
  119. moai_adk/templates/.claude/agents/moai/expert-database.md +774 -0
  120. moai_adk/templates/.claude/agents/moai/expert-debug.md +396 -0
  121. moai_adk/templates/.claude/agents/moai/expert-devops.md +711 -0
  122. moai_adk/templates/.claude/agents/moai/expert-frontend.md +666 -0
  123. moai_adk/templates/.claude/agents/moai/expert-security.md +474 -0
  124. moai_adk/templates/.claude/agents/moai/expert-uiux.md +1038 -0
  125. moai_adk/templates/.claude/agents/moai/manager-claude-code.md +429 -0
  126. moai_adk/templates/.claude/agents/moai/manager-docs.md +570 -0
  127. moai_adk/templates/.claude/agents/moai/manager-git.md +937 -0
  128. moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
  129. moai_adk/templates/.claude/agents/moai/manager-quality.md +598 -0
  130. moai_adk/templates/.claude/agents/moai/manager-spec.md +713 -0
  131. moai_adk/templates/.claude/agents/moai/manager-strategy.md +600 -0
  132. moai_adk/templates/.claude/agents/moai/manager-tdd.md +603 -0
  133. moai_adk/templates/.claude/agents/moai/mcp-context7.md +369 -0
  134. moai_adk/templates/.claude/agents/moai/mcp-figma.md +1567 -0
  135. moai_adk/templates/.claude/agents/moai/mcp-notion.md +749 -0
  136. moai_adk/templates/.claude/agents/moai/mcp-playwright.md +427 -0
  137. moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +994 -0
  138. moai_adk/templates/.claude/commands/moai/0-project.md +1143 -0
  139. moai_adk/templates/.claude/commands/moai/1-plan.md +1435 -0
  140. moai_adk/templates/.claude/commands/moai/2-run.md +883 -0
  141. moai_adk/templates/.claude/commands/moai/3-sync.md +993 -0
  142. moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
  143. moai_adk/templates/.claude/hooks/__init__.py +8 -0
  144. moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
  145. moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
  146. moai_adk/templates/.claude/hooks/moai/lib/checkpoint.py +244 -0
  147. moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
  148. moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
  149. moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
  150. moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
  151. moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
  152. moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
  153. moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
  154. moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
  155. moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
  156. moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
  157. moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
  158. moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
  159. moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
  160. moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +921 -0
  161. moai_adk/templates/.claude/output-styles/moai/r2d2.md +380 -0
  162. moai_adk/templates/.claude/output-styles/moai/yoda.md +338 -0
  163. moai_adk/templates/.claude/settings.json +172 -0
  164. moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +247 -0
  165. moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
  166. moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
  167. moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
  168. moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
  169. moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
  170. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +319 -0
  171. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +320 -0
  172. moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
  173. moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
  174. moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
  175. moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
  176. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +496 -0
  177. moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +453 -0
  178. moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
  179. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
  180. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
  181. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/design-system-tokens.md +405 -0
  182. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
  183. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
  184. moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
  185. moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +491 -0
  186. moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
  187. moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
  188. moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
  189. moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
  190. moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
  191. moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
  192. moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +201 -0
  193. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
  194. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
  195. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
  196. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
  197. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
  198. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
  199. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
  200. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
  201. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
  202. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
  203. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
  204. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
  205. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
  206. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
  207. moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +438 -0
  208. moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +515 -0
  209. moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
  210. moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +346 -0
  211. moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
  212. moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
  213. moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
  214. moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
  215. moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
  216. moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
  217. moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
  218. moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
  219. moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +362 -0
  220. moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
  221. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
  222. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
  223. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
  224. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
  225. moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
  226. moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
  227. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
  228. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
  229. moai_adk/templates/.claude/skills/moai-integration-mcp/SKILL.md +352 -0
  230. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/README.md +52 -0
  231. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/error-handling.md +334 -0
  232. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/integration-patterns.md +310 -0
  233. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/security-authentication.md +256 -0
  234. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/server-architecture.md +253 -0
  235. moai_adk/templates/.claude/skills/moai-lang-unified/README.md +133 -0
  236. moai_adk/templates/.claude/skills/moai-lang-unified/SKILL.md +296 -0
  237. moai_adk/templates/.claude/skills/moai-lang-unified/examples.md +1269 -0
  238. moai_adk/templates/.claude/skills/moai-lang-unified/reference.md +331 -0
  239. moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +298 -0
  240. moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
  241. moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
  242. moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
  243. moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
  244. moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +316 -0
  245. moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
  246. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
  247. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
  248. moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
  249. moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
  250. moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
  251. moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
  252. moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
  253. moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
  254. moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
  255. moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +370 -0
  256. moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
  257. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
  258. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
  259. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
  260. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
  261. moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
  262. moai_adk/templates/.claude/skills/moai-platform-baas/README.md +186 -0
  263. moai_adk/templates/.claude/skills/moai-platform-baas/SKILL.md +290 -0
  264. moai_adk/templates/.claude/skills/moai-platform-baas/examples.md +1225 -0
  265. moai_adk/templates/.claude/skills/moai-platform-baas/reference.md +567 -0
  266. moai_adk/templates/.claude/skills/moai-platform-baas/scripts/provider-selector.py +323 -0
  267. moai_adk/templates/.claude/skills/moai-platform-baas/templates/stack-config.yaml +204 -0
  268. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +446 -0
  269. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
  270. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
  271. moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
  272. moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +387 -0
  273. moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
  274. moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
  275. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
  276. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
  277. moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
  278. moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +135 -0
  279. moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
  280. moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
  281. moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
  282. moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
  283. moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
  284. moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
  285. moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
  286. moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
  287. moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
  288. moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
  289. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
  290. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1362 -0
  291. moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
  292. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
  293. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
  294. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +71 -0
  295. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
  296. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
  297. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
  298. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
  299. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
  300. moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
  301. moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +374 -0
  302. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
  303. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
  304. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
  305. moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
  306. moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +453 -0
  307. moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
  308. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
  309. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
  310. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
  311. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
  312. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
  313. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
  314. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
  315. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
  316. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
  317. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
  318. moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
  319. moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
  320. moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
  321. moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
  322. moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
  323. moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +410 -0
  324. moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
  325. moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
  326. moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
  327. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
  328. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
  329. moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
  330. moai_adk/templates/.git-hooks/pre-commit +103 -41
  331. moai_adk/templates/.git-hooks/pre-push +116 -21
  332. moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
  333. moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
  334. moai_adk/templates/.gitignore +184 -44
  335. moai_adk/templates/.mcp.json +7 -9
  336. moai_adk/templates/.moai/cache/personalization.json +10 -0
  337. moai_adk/templates/.moai/config/config.yaml +344 -0
  338. moai_adk/templates/.moai/config/presets/manual.yaml +28 -0
  339. moai_adk/templates/.moai/config/presets/personal.yaml +30 -0
  340. moai_adk/templates/.moai/config/presets/team.yaml +33 -0
  341. moai_adk/templates/.moai/config/questions/_schema.yaml +79 -0
  342. moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
  343. moai_adk/templates/.moai/config/questions/tab2-project.yaml +122 -0
  344. moai_adk/templates/.moai/config/questions/tab3-git.yaml +542 -0
  345. moai_adk/templates/.moai/config/questions/tab4-quality.yaml +167 -0
  346. moai_adk/templates/.moai/config/questions/tab5-system.yaml +152 -0
  347. moai_adk/templates/.moai/config/sections/git-strategy.yaml +40 -0
  348. moai_adk/templates/.moai/config/sections/language.yaml +11 -0
  349. moai_adk/templates/.moai/config/sections/project.yaml +13 -0
  350. moai_adk/templates/.moai/config/sections/quality.yaml +15 -0
  351. moai_adk/templates/.moai/config/sections/system.yaml +14 -0
  352. moai_adk/templates/.moai/config/sections/user.yaml +5 -0
  353. moai_adk/templates/.moai/config/statusline-config.yaml +86 -0
  354. moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
  355. moai_adk/templates/CLAUDE.md +382 -501
  356. moai_adk/utils/__init__.py +24 -1
  357. moai_adk/utils/banner.py +7 -10
  358. moai_adk/utils/common.py +16 -30
  359. moai_adk/utils/link_validator.py +4 -12
  360. moai_adk/utils/safe_file_reader.py +2 -6
  361. moai_adk/utils/timeout.py +160 -0
  362. moai_adk/utils/toon_utils.py +256 -0
  363. moai_adk/version.py +22 -0
  364. moai_adk-0.32.8.dist-info/METADATA +2478 -0
  365. moai_adk-0.32.8.dist-info/RECORD +396 -0
  366. {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/WHEEL +1 -1
  367. {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/entry_points.txt +1 -0
  368. moai_adk/cli/commands/backup.py +0 -82
  369. moai_adk/cli/commands/improve_user_experience.py +0 -348
  370. moai_adk/cli/commands/migrate.py +0 -158
  371. moai_adk/cli/commands/validate_links.py +0 -118
  372. moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -413
  373. moai_adk/templates/.github/workflows/moai-release-create.yml +0 -100
  374. moai_adk/templates/.github/workflows/moai-release-pipeline.yml +0 -188
  375. moai_adk/utils/user_experience.py +0 -531
  376. moai_adk-0.25.4.dist-info/METADATA +0 -2279
  377. moai_adk-0.25.4.dist-info/RECORD +0 -112
  378. {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,1225 @@
1
+ # BaaS Provider Implementation Examples
2
+
3
+ ## Quick Start Examples
4
+
5
+ ### Example 1: Next.js Enterprise SaaS with Auth0 + Supabase + Vercel
6
+
7
+ Stack Configuration:
8
+ ```typescript
9
+ // next.config.js
10
+ / @type {import('next').NextConfig} */
11
+ const nextConfig = {
12
+ experimental: {
13
+ serverComponentsExternalPackages: ['@supabase/supabase-js']
14
+ },
15
+ env: {
16
+ AUTH0_SECRET: process.env.AUTH0_SECRET,
17
+ AUTH0_BASE_URL: process.env.AUTH0_BASE_URL,
18
+ SUPABASE_URL: process.env.SUPABASE_URL,
19
+ SUPABASE_ANON_KEY: process.env.SUPABASE_ANON_KEY
20
+ }
21
+ }
22
+
23
+ module.exports = nextConfig
24
+ ```
25
+
26
+ Auth0 Configuration:
27
+ ```typescript
28
+ // lib/auth0.ts
29
+ import { Auth0Client } from '@auth0/auth0-react'
30
+
31
+ export const auth0Client = new Auth0Client({
32
+ domain: process.env.AUTH0_DOMAIN!,
33
+ clientId: process.env.AUTH0_CLIENT_ID!,
34
+ redirectUri: typeof window !== 'undefined' ? window.location.origin : undefined
35
+ })
36
+
37
+ // Auth0 Organization Management
38
+ export class Auth0OrgManager {
39
+ private managementToken = process.env.AUTH0_MANAGEMENT_TOKEN!
40
+ private domain = process.env.AUTH0_DOMAIN!
41
+
42
+ async createOrganization(name: string, displayName: string) {
43
+ const response = await fetch(`https://${this.domain}/api/v2/organizations`, {
44
+ method: 'POST',
45
+ headers: {
46
+ 'Authorization': `Bearer ${this.managementToken}`,
47
+ 'Content-Type': 'application/json'
48
+ },
49
+ body: JSON.stringify({ name, display_name: displayName })
50
+ })
51
+
52
+ return response.json()
53
+ }
54
+
55
+ async addMemberToOrganization(orgId: string, userId: string) {
56
+ const response = await fetch(
57
+ `https://${this.domain}/api/v2/organizations/${orgId}/members`,
58
+ {
59
+ method: 'POST',
60
+ headers: {
61
+ 'Authorization': `Bearer ${this.managementToken}`,
62
+ 'Content-Type': 'application/json'
63
+ },
64
+ body: JSON.stringify({
65
+ members: [{ user_id: userId }]
66
+ })
67
+ }
68
+ )
69
+
70
+ return response.json()
71
+ }
72
+ }
73
+ ```
74
+
75
+ Supabase Configuration with Row-Level Security:
76
+ ```typescript
77
+ // lib/supabase.ts
78
+ import { createClient } from '@supabase/supabase-js'
79
+
80
+ export const supabase = createClient(
81
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
82
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
83
+ {
84
+ auth: {
85
+ autoRefreshToken: true,
86
+ persistSession: true
87
+ },
88
+ realtime: {
89
+ params: {
90
+ eventsPerSecond: 10
91
+ }
92
+ }
93
+ }
94
+ )
95
+
96
+ // Row-Level Security Setup
97
+ export class SupabaseRLS {
98
+ async enableRLS() {
99
+ // Enable RLS on tables
100
+ const { error } = await supabase.rpc('enable_rls_on_tables')
101
+ if (error) throw error
102
+ }
103
+
104
+ async createTenantPolicies(tenantId: string) {
105
+ // Create tenant-specific policies
106
+ const policies = `
107
+ -- Tenants table policy
108
+ CREATE POLICY "Users can view their own tenant" ON tenants
109
+ FOR SELECT USING (auth.jwt() ->> 'org_id' = id);
110
+
111
+ CREATE POLICY "Users can update their own tenant" ON tenants
112
+ FOR UPDATE USING (auth.jwt() ->> 'org_id' = id);
113
+
114
+ -- Projects table policy
115
+ CREATE POLICY "Users can view projects in their tenant" ON projects
116
+ FOR SELECT USING (tenant_id = auth.jwt() ->> 'org_id');
117
+
118
+ CREATE POLICY "Users can create projects in their tenant" ON projects
119
+ FOR INSERT WITH CHECK (tenant_id = auth.jwt() ->> 'org_id');
120
+ `
121
+
122
+ const { error } = await supabase.rpc('execute_sql', { sql: policies })
123
+ if (error) throw error
124
+ }
125
+ }
126
+ ```
127
+
128
+ Real-time Features:
129
+ ```typescript
130
+ // hooks/useRealtime.ts
131
+ import { useEffect, useState } from 'react'
132
+ import { supabase } from '@/lib/supabase'
133
+
134
+ export function useRealtime<T>(table: string, filter?: object) {
135
+ const [data, setData] = useState<T[]>([])
136
+ const [loading, setLoading] = useState(true)
137
+
138
+ useEffect(() => {
139
+ let query = supabase.from(table).select('*')
140
+
141
+ if (filter) {
142
+ Object.entries(filter).forEach(([key, value]) => {
143
+ query = query.eq(key, value)
144
+ })
145
+ }
146
+
147
+ // Initial fetch
148
+ query.then(({ data, error }) => {
149
+ if (error) throw error
150
+ setData(data as T[])
151
+ setLoading(false)
152
+ })
153
+
154
+ // Real-time subscription
155
+ const subscription = supabase
156
+ .channel(`${table}_changes`)
157
+ .on('postgres_changes',
158
+ { event: '*', schema: 'public', table },
159
+ (payload) => {
160
+ if (payload.eventType === 'INSERT') {
161
+ setData(prev => [...prev, payload.new as T])
162
+ } else if (payload.eventType === 'UPDATE') {
163
+ setData(prev =>
164
+ prev.map(item =>
165
+ item.id === payload.new.id ? payload.new as T : item
166
+ )
167
+ )
168
+ } else if (payload.eventType === 'DELETE') {
169
+ setData(prev => prev.filter(item => item.id !== payload.old.id))
170
+ }
171
+ }
172
+ )
173
+ .subscribe()
174
+
175
+ return () => {
176
+ subscription.unsubscribe()
177
+ }
178
+ }, [table, JSON.stringify(filter)])
179
+
180
+ return { data, loading }
181
+ }
182
+ ```
183
+
184
+ ### Example 2: Modern Web App with Clerk + Neon + Railway
185
+
186
+ Clerk Authentication Setup:
187
+ ```typescript
188
+ // middleware.ts
189
+ import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
190
+
191
+ const isPublicRoute = createRouteMatcher(['/', '/sign-in(.*)', '/sign-up(.*)'])
192
+
193
+ export default clerkMiddleware((auth, req) => {
194
+ if (!isPublicRoute(req)) {
195
+ auth().protect()
196
+ }
197
+ })
198
+
199
+ export const config = {
200
+ matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)']
201
+ }
202
+ ```
203
+
204
+ Clerk Organizations:
205
+ ```typescript
206
+ // app/dashboard/organization/page.tsx
207
+ import { currentUser, OrganizationList } from '@clerk/nextjs'
208
+ import { OrganizationSwitcher } from '@clerk/nextjs'
209
+ import { redirect } from 'next/navigation'
210
+
211
+ export default async function OrganizationPage() {
212
+ const user = await currentUser()
213
+
214
+ if (!user) {
215
+ redirect('/sign-in')
216
+ }
217
+
218
+ return (
219
+ <div className="container mx-auto p-6">
220
+ <div className="flex justify-between items-center mb-6">
221
+ <h1 className="text-2xl font-bold">Organization Settings</h1>
222
+ <OrganizationSwitcher />
223
+ </div>
224
+
225
+ <div className="grid gap-6">
226
+ <div className="bg-white rounded-lg shadow p-6">
227
+ <h2 className="text-lg font-semibold mb-4">Your Organizations</h2>
228
+ <OrganizationList
229
+ hidePersonal={true}
230
+ afterSelectOrganizationUrl={`/organization/:slug`}
231
+ afterLeaveOrganizationUrl="/dashboard"
232
+ />
233
+ </div>
234
+
235
+ <div className="bg-white rounded-lg shadow p-6">
236
+ <h2 className="text-lg font-semibold mb-4">Organization Members</h2>
237
+ <OrganizationMembers />
238
+ </div>
239
+ </div>
240
+ </div>
241
+ )
242
+ }
243
+
244
+ async function OrganizationMembers() {
245
+ // Use Clerk backend API to fetch organization members
246
+ const response = await fetch(`${process.env.CLERK_API_URL}/organizations/members`, {
247
+ headers: {
248
+ 'Authorization': `Bearer ${process.env.CLERK_SECRET_KEY}`
249
+ }
250
+ })
251
+
252
+ const members = await response.json()
253
+
254
+ return (
255
+ <div className="space-y-2">
256
+ {members.map((member: any) => (
257
+ <div key={member.id} className="flex justify-between items-center p-2 border rounded">
258
+ <span>{member.public_user_data.first_name} {member.public_user_data.last_name}</span>
259
+ <span className="text-sm text-gray-500">{member.role}</span>
260
+ </div>
261
+ ))}
262
+ </div>
263
+ )
264
+ }
265
+ ```
266
+
267
+ Neon Database Setup:
268
+ ```typescript
269
+ // lib/neon.ts
270
+ import { Pool } from 'pg'
271
+
272
+ const pool = new Pool({
273
+ connectionString: process.env.DATABASE_URL,
274
+ ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false
275
+ })
276
+
277
+ export class NeonDatabase {
278
+ async query(text: string, params?: any[]) {
279
+ const start = Date.now()
280
+ const res = await pool.query(text, params)
281
+ const duration = Date.now() - start
282
+ console.log('executed query', { text, duration, rows: res.rowCount })
283
+ return res
284
+ }
285
+
286
+ async getCustomer(email: string) {
287
+ const result = await this.query(
288
+ 'SELECT * FROM customers WHERE email = $1',
289
+ [email]
290
+ )
291
+ return result.rows[0]
292
+ }
293
+
294
+ async createCustomer(data: {
295
+ email: string
296
+ first_name: string
297
+ last_name: string
298
+ organization_id?: string
299
+ }) {
300
+ const result = await this.query(
301
+ `INSERT INTO customers (email, first_name, last_name, organization_id, created_at)
302
+ VALUES ($1, $2, $3, $4, NOW())
303
+ RETURNING *`,
304
+ [data.email, data.first_name, data.last_name, data.organization_id]
305
+ )
306
+ return result.rows[0]
307
+ }
308
+
309
+ async createBranch(branchName: string, parentId: string = 'main') {
310
+ // Use Neon API to create database branch
311
+ const response = await fetch(`${process.env.NEON_API_URL}/branches`, {
312
+ method: 'POST',
313
+ headers: {
314
+ 'Authorization': `Bearer ${process.env.NEON_API_KEY}`,
315
+ 'Content-Type': 'application/json'
316
+ },
317
+ body: JSON.stringify({
318
+ branch_id: branchName,
319
+ parent_id: parentId
320
+ })
321
+ })
322
+
323
+ return response.json()
324
+ }
325
+ }
326
+ ```
327
+
328
+ Railway Deployment Configuration:
329
+ ```dockerfile
330
+ # Dockerfile
331
+ FROM node:18-alpine AS base
332
+
333
+ # Install dependencies only when needed
334
+ FROM base AS deps
335
+ WORKDIR /app
336
+ COPY package.json package-lock.json* ./
337
+ RUN npm ci
338
+
339
+ # Rebuild the source code only when needed
340
+ FROM base AS builder
341
+ WORKDIR /app
342
+ COPY --from=deps /app/node_modules ./node_modules
343
+ COPY . .
344
+
345
+ # Environment variables for the build
346
+ ENV NEXT_TELEMETRY_DISABLED 1
347
+
348
+ RUN npm run build
349
+
350
+ # Production image, copy all the files and run next
351
+ FROM base AS runner
352
+ WORKDIR /app
353
+
354
+ ENV NODE_ENV production
355
+ ENV NEXT_TELEMETRY_DISABLED 1
356
+
357
+ RUN addgroup --system --gid 1001 nodejs
358
+ RUN adduser --system --uid 1001 nextjs
359
+
360
+ COPY --from=builder /app/public ./public
361
+
362
+ # Set the correct permission for prerender cache
363
+ RUN mkdir .next
364
+ RUN chown nextjs:nodejs .next
365
+
366
+ # Automatically leverage output traces to reduce image size
367
+ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
368
+ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
369
+
370
+ USER nextjs
371
+
372
+ EXPOSE 3000
373
+
374
+ ENV PORT 3000
375
+ ENV HOSTNAME "0.0.0.0"
376
+
377
+ CMD ["node", "server.js"]
378
+ ```
379
+
380
+ ```yaml
381
+ # railway.toml
382
+ [build]
383
+ builder = "NIXPACKS"
384
+
385
+ [deploy]
386
+ startCommand = "npm start"
387
+ healthcheckPath = "/health"
388
+ healthcheckTimeout = 100
389
+ restartPolicyType = "ON_FAILURE"
390
+ restartPolicyMaxRetries = 10
391
+
392
+ [[services]]
393
+ name = "web"
394
+ [source]
395
+ image = "web"
396
+ dockerfilePath = "./Dockerfile"
397
+
398
+ [services.environment_variables]
399
+ NODE_ENV = "production"
400
+ PORT = "3000"
401
+
402
+ [services.health_checks]
403
+ [services.health_checks.http]
404
+ path = "/health"
405
+ port = 3000
406
+ ```
407
+
408
+ ### Example 3: Real-time Collaborative Platform with Clerk + Convex + Vercel
409
+
410
+ Convex Schema Definition:
411
+ ```typescript
412
+ // convex/schema.ts
413
+ import { defineSchema, defineTable } from 'convex/server'
414
+ import { v } from 'convex/values'
415
+
416
+ export default defineSchema({
417
+ documents: defineTable({
418
+ title: v.string(),
419
+ content: v.string(),
420
+ ownerId: v.string(),
421
+ organizationId: v.optional(v.string()),
422
+ lastModifiedBy: v.string(),
423
+ lastModifiedAt: v.number(),
424
+ isPublic: v.boolean(),
425
+ })
426
+ .index('by_owner', ['ownerId'])
427
+ .index('by_organization', ['organizationId'])
428
+ .searchIndex('by_title', { searchField: 'title' }),
429
+
430
+ users: defineTable({
431
+ clerkId: v.string(),
432
+ email: v.string(),
433
+ name: v.string(),
434
+ avatar: v.optional(v.string()),
435
+ organizationId: v.optional(v.string()),
436
+ lastActiveAt: v.number(),
437
+ })
438
+ .index('by_clerk', ['clerkId'])
439
+ .index('by_organization', ['organizationId']),
440
+
441
+ documentCollaborators: defineTable({
442
+ documentId: v.id('documents'),
443
+ userId: v.id('users'),
444
+ permission: v.union(v.literal('read'), v.literal('write'), v.literal('admin')),
445
+ addedAt: v.number(),
446
+ addedBy: v.id('users'),
447
+ })
448
+ .index('by_document', ['documentId'])
449
+ .index('by_user', ['userId']),
450
+ })
451
+ ```
452
+
453
+ Convex Functions:
454
+ ```typescript
455
+ // convex/documents.ts
456
+ import { mutation, query } from './_generated/server'
457
+ import { v } from 'convex/values'
458
+
459
+ export const createDocument = mutation({
460
+ args: {
461
+ title: v.string(),
462
+ content: v.string(),
463
+ organizationId: v.optional(v.id('organizations')),
464
+ isPublic: v.boolean(),
465
+ },
466
+ handler: async (ctx, args) => {
467
+ const identity = await ctx.auth.getUserIdentity()
468
+ if (!identity) {
469
+ throw new Error('Unauthorized')
470
+ }
471
+
472
+ const user = await ctx.db
473
+ .query('users')
474
+ .withIndex('by_clerk', q => q.eq('clerkId', identity.subject))
475
+ .unique()
476
+
477
+ if (!user) {
478
+ throw new Error('User not found')
479
+ }
480
+
481
+ const documentId = await ctx.db.insert('documents', {
482
+ title: args.title,
483
+ content: args.content,
484
+ ownerId: user._id,
485
+ organizationId: args.organizationId,
486
+ lastModifiedBy: user._id,
487
+ lastModifiedAt: Date.now(),
488
+ isPublic: args.isPublic,
489
+ })
490
+
491
+ // Add owner as admin collaborator
492
+ await ctx.db.insert('documentCollaborators', {
493
+ documentId,
494
+ userId: user._id,
495
+ permission: 'admin',
496
+ addedAt: Date.now(),
497
+ addedBy: user._id,
498
+ })
499
+
500
+ return documentId
501
+ }
502
+ })
503
+
504
+ export const getDocument = query({
505
+ args: { documentId: v.id('documents') },
506
+ handler: async (ctx, args) => {
507
+ const identity = await ctx.auth.getUserIdentity()
508
+ if (!identity) {
509
+ throw new Error('Unauthorized')
510
+ }
511
+
512
+ const document = await ctx.db.get(args.documentId)
513
+ if (!document) {
514
+ throw new Error('Document not found')
515
+ }
516
+
517
+ const user = await ctx.db
518
+ .query('users')
519
+ .withIndex('by_clerk', q => q.eq('clerkId', identity.subject))
520
+ .unique()
521
+
522
+ if (!user) {
523
+ throw new Error('User not found')
524
+ }
525
+
526
+ // Check access permissions
527
+ const hasAccess =
528
+ document.ownerId === user._id ||
529
+ document.isPublic ||
530
+ (document.organizationId &&
531
+ await ctx.db
532
+ .query('users')
533
+ .withIndex('by_organization', q => q.eq('organizationId', document.organizationId))
534
+ .filter(q => q.eq(q.field('clerkId'), identity.subject))
535
+ .unique() !== null)
536
+
537
+ if (!hasAccess) {
538
+ throw new Error('Access denied')
539
+ }
540
+
541
+ return document
542
+ }
543
+ })
544
+
545
+ export const updateDocumentContent = mutation({
546
+ args: {
547
+ documentId: v.id('documents'),
548
+ content: v.string(),
549
+ version: v.number(),
550
+ },
551
+ handler: async (ctx, args) => {
552
+ const identity = await ctx.auth.getUserIdentity()
553
+ if (!identity) {
554
+ throw new Error('Unauthorized')
555
+ }
556
+
557
+ const document = await ctx.db.get(args.documentId)
558
+ if (!document) {
559
+ throw new Error('Document not found')
560
+ }
561
+
562
+ const user = await ctx.db
563
+ .query('users')
564
+ .withIndex('by_clerk', q => q.eq('clerkId', identity.subject))
565
+ .unique()
566
+
567
+ if (!user) {
568
+ throw new Error('User not found')
569
+ }
570
+
571
+ // Check write permission
572
+ const collaborator = await ctx.db
573
+ .query('documentCollaborators')
574
+ .withIndex('by_document', q => q.eq('documentId', args.documentId))
575
+ .filter(q => q.eq('userId', user._id))
576
+ .unique()
577
+
578
+ const canWrite =
579
+ document.ownerId === user._id ||
580
+ (collaborator && (collaborator.permission === 'write' || collaborator.permission === 'admin'))
581
+
582
+ if (!canWrite) {
583
+ throw new Error('Write access denied')
584
+ }
585
+
586
+ await ctx.db.patch(args.documentId, {
587
+ content: args.content,
588
+ lastModifiedBy: user._id,
589
+ lastModifiedAt: Date.now(),
590
+ })
591
+
592
+ return { success: true }
593
+ }
594
+ })
595
+ ```
596
+
597
+ Real-time Document Editor:
598
+ ```typescript
599
+ // components/DocumentEditor.tsx
600
+ 'use client'
601
+
602
+ import { useMutation, useQuery } from 'convex/react'
603
+ import { api } from '@/convex/_generated/api'
604
+ import { useUser } from '@clerk/nextjs'
605
+ import { useEffect, useState } from 'react'
606
+ import { useOptimistic, useSubscription } from 'convex/react'
607
+
608
+ export function DocumentEditor({ documentId }: { documentId: string }) {
609
+ const { user } = useUser()
610
+ const document = useQuery(api.documents.getDocument, { documentId })
611
+ const updateContent = useMutation(api.documents.updateDocumentContent)
612
+
613
+ const [localContent, setLocalContent] = useState('')
614
+ const [version, setVersion] = useState(0)
615
+
616
+ // Subscribe to real-time updates
617
+ useSubscription(api.documents.onDocumentChange, { documentId }, (doc) => {
618
+ if (doc && doc.lastModifiedBy !== user?.id) {
619
+ setLocalContent(doc.content)
620
+ setVersion(v => v + 1)
621
+ }
622
+ })
623
+
624
+ useEffect(() => {
625
+ if (document) {
626
+ setLocalContent(document.content)
627
+ }
628
+ }, [document])
629
+
630
+ const optimisticUpdate = useOptimistic(
631
+ { content: localContent, version },
632
+ (currentState, newContent: string) => ({
633
+ content: newContent,
634
+ version: currentState.version + 1
635
+ })
636
+ )
637
+
638
+ const handleContentChange = async (newContent: string) => {
639
+ setLocalContent(newContent)
640
+
641
+ try {
642
+ await updateContent({
643
+ documentId,
644
+ content: newContent,
645
+ version: optimisticUpdate.version
646
+ })
647
+ } catch (error) {
648
+ console.error('Failed to update document:', error)
649
+ // Revert on error
650
+ if (document) {
651
+ setLocalContent(document.content)
652
+ }
653
+ }
654
+ }
655
+
656
+ return (
657
+ <div className="h-full flex flex-col">
658
+ <div className="border-b p-4">
659
+ <h2 className="text-xl font-semibold">{document?.title}</h2>
660
+ <p className="text-sm text-gray-500">
661
+ Last modified by {document?.lastModifiedBy} at{' '}
662
+ {document?.lastModifiedAt ? new Date(document.lastModifiedAt).toLocaleString() : ''}
663
+ </p>
664
+ </div>
665
+
666
+ <div className="flex-1 p-4">
667
+ <textarea
668
+ value={localContent}
669
+ onChange={(e) => handleContentChange(e.target.value)}
670
+ className="w-full h-full p-4 border rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500"
671
+ placeholder="Start typing..."
672
+ />
673
+ </div>
674
+
675
+ <div className="border-t p-4 bg-gray-50">
676
+ <div className="flex items-center justify-between">
677
+ <span className="text-sm text-gray-600">
678
+ Auto-saving... (Version {optimisticUpdate.version})
679
+ </span>
680
+ <div className="flex items-center space-x-2">
681
+ <div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
682
+ <span className="text-sm text-gray-600">Connected</span>
683
+ </div>
684
+ </div>
685
+ </div>
686
+ </div>
687
+ )
688
+ }
689
+ ```
690
+
691
+ Vercel Edge Functions for Global Performance:
692
+ ```typescript
693
+ // api/webhook/clerk.ts
694
+ import { Webhook } from 'svix'
695
+ import { headers } from 'next/headers'
696
+ import { NextRequest, NextResponse } from 'next/server'
697
+ import { client } from '@/convex/_generated/client'
698
+
699
+ export const runtime = 'edge'
700
+
701
+ export async function POST(req: NextRequest) {
702
+ const headerPayload = headers()
703
+ const svix_id = headerPayload.get('svix-id')
704
+ const svix_timestamp = headerPayload.get('svix-timestamp')
705
+ const svix_signature = headerPayload.get('svix-signature')
706
+
707
+ if (!svix_id || !svix_timestamp || !svix_signature) {
708
+ return NextResponse.json({ error: 'Missing svix headers' }, { status: 400 })
709
+ }
710
+
711
+ const payload = await req.json()
712
+ const body = JSON.stringify(payload)
713
+
714
+ const wh = new Webhook(process.env.CLERK_WEBHOOK_SECRET!)
715
+ let event: any
716
+
717
+ try {
718
+ event = wh.verify(body, {
719
+ 'svix-id': svix_id,
720
+ 'svix-timestamp': svix_timestamp,
721
+ 'svix-signature': svix_signature,
722
+ })
723
+ } catch (err) {
724
+ console.error('Webhook verification failed:', err)
725
+ return NextResponse.json({ error: 'Invalid signature' }, { status: 400 })
726
+ }
727
+
728
+ const convexClient = client(process.env.CONVEX_URL!, new WebSocket(process.env.CONVEX_WEBSOCKET_URL!))
729
+
730
+ try {
731
+ switch (event.type) {
732
+ case 'user.created':
733
+ await convexClient.mutation.api.users.createUser({
734
+ clerkId: event.data.id,
735
+ email: event.data.email_addresses[0].email_address,
736
+ name: `${event.data.first_name} ${event.data.last_name}`,
737
+ avatar: event.data.image_url,
738
+ })
739
+ break
740
+
741
+ case 'user.updated':
742
+ await convexClient.mutation.api.users.updateUser({
743
+ clerkId: event.data.id,
744
+ email: event.data.email_addresses[0].email_address,
745
+ name: `${event.data.first_name} ${event.data.last_name}`,
746
+ avatar: event.data.image_url,
747
+ })
748
+ break
749
+
750
+ case 'organization.created':
751
+ await convexClient.mutation.api.organizations.createOrganization({
752
+ clerkId: event.data.id,
753
+ name: event.data.name,
754
+ slug: event.data.slug,
755
+ })
756
+ break
757
+
758
+ case 'organizationMembership.created':
759
+ await convexClient.mutation.api.users.addToOrganization({
760
+ clerkId: event.data.public_user_data.user_id,
761
+ organizationId: event.data.organization.id,
762
+ role: event.data.role,
763
+ })
764
+ break
765
+ }
766
+
767
+ return NextResponse.json({ success: true })
768
+ } catch (error) {
769
+ console.error('Error processing webhook:', error)
770
+ return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
771
+ }
772
+ }
773
+ ```
774
+
775
+ ## Migration Examples
776
+
777
+ ### Auth0 to Clerk Migration Script
778
+ ```python
779
+ # migrate_auth0_to_clerk.py
780
+ import os
781
+ import asyncio
782
+ from auth0.management import Auth0
783
+ from clerk_backend_api import ClerkApiClient
784
+
785
+ class Auth0ToClerkMigrator:
786
+ def __init__(self):
787
+ self.auth0 = Auth0(
788
+ domain=os.getenv('AUTH0_DOMAIN'),
789
+ token=os.getenv('AUTH0_MANAGEMENT_TOKEN')
790
+ )
791
+ self.clerk = ClerkApiClient(
792
+ bearer_auth=os.getenv('CLERK_SECRET_KEY')
793
+ )
794
+
795
+ async def migrate_users(self):
796
+ """Migrate all users from Auth0 to Clerk."""
797
+
798
+ # Get all users from Auth0
799
+ auth0_users = []
800
+ page = 0
801
+ while True:
802
+ users_page = self.auth0.users.list(per_page=100, page=page)
803
+ if not users_page['users']:
804
+ break
805
+ auth0_users.extend(users_page['users'])
806
+ page += 1
807
+
808
+ print(f"Found {len(auth0_users)} users to migrate")
809
+
810
+ # Transform and import to Clerk
811
+ for i, auth0_user in enumerate(auth0_users):
812
+ try:
813
+ # Transform Auth0 user to Clerk format
814
+ clerk_user_data = {
815
+ 'email_addresses': [{
816
+ 'email_address': auth0_user['email'],
817
+ 'verification': {
818
+ 'status': 'verified' if auth0_user['email_verified'] else 'unverified'
819
+ }
820
+ }],
821
+ 'first_name': auth0_user.get('given_name', ''),
822
+ 'last_name': auth0_user.get('family_name', ''),
823
+ 'username': auth0_user.get('username'),
824
+ 'profile_image_url': auth0_user.get('picture'),
825
+ 'external_connections': [{
826
+ 'provider': 'oauth_google' if 'google' in auth0_user['user_id'] else 'oauth_github',
827
+ 'external_id': auth0_user['user_id'].split('|')[1],
828
+ 'scopes': ['openid', 'profile', 'email']
829
+ }] if any(provider in auth0_user['user_id'] for provider in ['google', 'github']) else []
830
+ }
831
+
832
+ # Create user in Clerk
833
+ clerk_user = self.clerk.users.create(clerk_user_data)
834
+ print(f"Migrated user {i+1}/{len(auth0_users)}: {auth0_user['email']} -> {clerk_user.id}")
835
+
836
+ except Exception as e:
837
+ print(f"Failed to migrate user {auth0_user['email']}: {str(e)}")
838
+ continue
839
+
840
+ print("User migration completed")
841
+
842
+ async def migrate_organizations(self):
843
+ """Migrate organizations from Auth0 to Clerk."""
844
+
845
+ # Get organizations from Auth0
846
+ auth0_orgs = self.auth0.organizations.all()
847
+
848
+ for org in auth0_orgs:
849
+ try:
850
+ # Transform organization
851
+ clerk_org_data = {
852
+ 'name': org['name'],
853
+ 'slug': org['display_name'].lower().replace(' ', '-'),
854
+ 'public_metadata': {
855
+ 'auth0_id': org['id']
856
+ }
857
+ }
858
+
859
+ # Create organization in Clerk
860
+ clerk_org = self.clerk.organizations.create(clerk_org_data)
861
+ print(f"Migrated organization: {org['name']} -> {clerk_org.id}")
862
+
863
+ # Migrate members
864
+ auth0_members = self.auth0.organizations.list_members(org['id'])
865
+ for member in auth0_members:
866
+ self.clerk.organizations.add_member(
867
+ clerk_org.id,
868
+ user_id=f"user_{member['user_id'].split('|')[1]}",
869
+ role=member['role'].lower()
870
+ )
871
+
872
+ except Exception as e:
873
+ print(f"Failed to migrate organization {org['name']}: {str(e)}")
874
+ continue
875
+
876
+ print("Organization migration completed")
877
+
878
+ async def main():
879
+ migrator = Auth0ToClerkMigrator()
880
+ await migrator.migrate_users()
881
+ await migrator.migrate_organizations()
882
+
883
+ if __name__ == '__main__':
884
+ asyncio.run(main())
885
+ ```
886
+
887
+ ### Supabase to Neon Migration Script
888
+ ```python
889
+ # migrate_supabase_to_neon.py
890
+ import os
891
+ import asyncio
892
+ from supabase import create_client, Client
893
+ from neon_api import NeonClient
894
+ from psycopg2 import sql
895
+ import psycopg2
896
+
897
+ class SupabaseToNeonMigrator:
898
+ def __init__(self):
899
+ self.supabase: Client = create_client(
900
+ os.getenv('SUPABASE_URL'),
901
+ os.getenv('SUPABASE_SERVICE_KEY')
902
+ )
903
+ self.neon = NeonClient(api_key=os.getenv('NEON_API_KEY'))
904
+ self.project_id = os.getenv('NEON_PROJECT_ID')
905
+
906
+ async def export_supabase_schema(self):
907
+ """Export schema from Supabase."""
908
+
909
+ print("Exporting schema from Supabase...")
910
+
911
+ # Get all tables
912
+ tables = self.supabase.table('information_schema.tables').select('table_name').eq('table_schema', 'public').execute()
913
+
914
+ schema_statements = []
915
+
916
+ for table in tables.data:
917
+ table_name = table['table_name']
918
+
919
+ # Get table structure
920
+ columns = self.supabase.table('information_schema.columns').select('*').eq('table_schema', 'public').eq('table_name', table_name).execute()
921
+
922
+ # Build CREATE TABLE statement
923
+ columns_sql = []
924
+ for col in columns.data:
925
+ col_def = f"{col['column_name']} {col['data_type']}"
926
+ if col['character_maximum_length']:
927
+ col_def += f"({col['character_maximum_length']})"
928
+ if col['is_nullable'] == 'NO':
929
+ col_def += ' NOT NULL'
930
+ if col['column_default']:
931
+ col_def += f" DEFAULT {col['column_default']}"
932
+ columns_sql.append(col_def)
933
+
934
+ create_table = f"CREATE TABLE {table_name} (\n {',\n '.join(columns_sql)}\n);"
935
+ schema_statements.append(create_table)
936
+
937
+ # Get indexes
938
+ indexes = self.supabase.table('pg_indexes').select('indexdef').eq('tablename', table_name).execute()
939
+ for index in indexes.data:
940
+ if not index['indexdef'].startswith('CREATE UNIQUE INDEX'):
941
+ schema_statements.append(index['indexdef'] + ';')
942
+
943
+ return '\n\n'.join(schema_statements)
944
+
945
+ async def export_supabase_data(self):
946
+ """Export data from Supabase."""
947
+
948
+ print("Exporting data from Supabase...")
949
+
950
+ tables = self.supabase.table('information_schema.tables').select('table_name').eq('table_schema', 'public').execute()
951
+
952
+ data_export = {}
953
+
954
+ for table in tables.data:
955
+ table_name = table['table_name']
956
+ if table_name in ['schema_migrations', 'flyway_schema_history']:
957
+ continue # Skip migration tables
958
+
959
+ print(f"Exporting data from {table_name}...")
960
+
961
+ # Get all data from table
962
+ try:
963
+ result = self.supabase.table(table_name).select('*').execute()
964
+ data_export[table_name] = result.data
965
+ print(f" Exported {len(result.data)} rows")
966
+ except Exception as e:
967
+ print(f" Error exporting {table_name}: {str(e)}")
968
+ continue
969
+
970
+ return data_export
971
+
972
+ async def create_neon_database(self):
973
+ """Create database in Neon."""
974
+
975
+ print("Creating Neon database...")
976
+
977
+ branch = self.neon.create_branch(
978
+ project_id=self.project_id,
979
+ branch_name='migration_target'
980
+ )
981
+
982
+ return branch
983
+
984
+ async def import_to_neon(self, schema: str, data: dict):
985
+ """Import schema and data to Neon."""
986
+
987
+ print("Importing to Neon...")
988
+
989
+ # Get connection string
990
+ branch = self.neon.get_branch(self.project_id, 'migration_target')
991
+ connection_string = branch.connection_uris[0].connection_string
992
+
993
+ # Connect to Neon
994
+ conn = psycopg2.connect(connection_string)
995
+ cursor = conn.cursor()
996
+
997
+ try:
998
+ # Import schema
999
+ print("Importing schema...")
1000
+ cursor.execute(schema)
1001
+ conn.commit()
1002
+
1003
+ # Import data
1004
+ print("Importing data...")
1005
+ for table_name, table_data in data.items():
1006
+ if not table_data:
1007
+ continue
1008
+
1009
+ # Get column names from first row
1010
+ columns = list(table_data[0].keys())
1011
+
1012
+ for row in table_data:
1013
+ values = []
1014
+ for col in columns:
1015
+ val = row.get(col)
1016
+ if val is None:
1017
+ values.append('NULL')
1018
+ elif isinstance(val, str):
1019
+ values.append(f"'{val.replace(\"'\", \"''\")}'")
1020
+ elif isinstance(val, bool):
1021
+ values.append('TRUE' if val else 'FALSE')
1022
+ elif isinstance(val, (int, float)):
1023
+ values.append(str(val))
1024
+ else:
1025
+ values.append(f"'{str(val)}'")
1026
+
1027
+ insert_sql = sql.SQL("INSERT INTO {} ({}) VALUES ({});").format(
1028
+ sql.Identifier(table_name),
1029
+ sql.SQL(', ').join(map(sql.Identifier, columns)),
1030
+ sql.SQL(', ').join(map(sql.Literal, values))
1031
+ )
1032
+
1033
+ cursor.execute(insert_sql)
1034
+
1035
+ print(f" Imported {len(table_data)} rows into {table_name}")
1036
+ conn.commit()
1037
+
1038
+ except Exception as e:
1039
+ print(f"Error importing to Neon: {str(e)}")
1040
+ conn.rollback()
1041
+ raise
1042
+ finally:
1043
+ cursor.close()
1044
+ conn.close()
1045
+
1046
+ print("Import completed successfully")
1047
+
1048
+ async def verify_migration(self):
1049
+ """Verify migration integrity."""
1050
+
1051
+ print("Verifying migration...")
1052
+
1053
+ # This would involve comparing row counts and potentially sample data
1054
+ # between Supabase and Neon to ensure data integrity
1055
+
1056
+ print("Migration verification completed")
1057
+
1058
+ async def main():
1059
+ migrator = SupabaseToNeonMigrator()
1060
+
1061
+ # Export from Supabase
1062
+ schema = await migrator.export_supabase_schema()
1063
+ data = await migrator.export_supabase_data()
1064
+
1065
+ # Create Neon database
1066
+ await migrator.create_neon_database()
1067
+
1068
+ # Import to Neon
1069
+ await migrator.import_to_neon(schema, data)
1070
+
1071
+ # Verify migration
1072
+ await migrator.verify_migration()
1073
+
1074
+ if __name__ == '__main__':
1075
+ asyncio.run(main())
1076
+ ```
1077
+
1078
+ ## Cost Optimization Examples
1079
+
1080
+ ### BaaS Cost Monitoring Dashboard
1081
+ ```typescript
1082
+ // app/dashboard/cost/page.tsx
1083
+ 'use client'
1084
+
1085
+ import { useState, useEffect } from 'react'
1086
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
1087
+
1088
+ interface CostData {
1089
+ provider: string
1090
+ service: string
1091
+ currentCost: number
1092
+ projectedCost: number
1093
+ usage: {
1094
+ current: number
1095
+ limit: number
1096
+ unit: string
1097
+ }
1098
+ recommendations: string[]
1099
+ }
1100
+
1101
+ export default function CostDashboard() {
1102
+ const [costData, setCostData] = useState<CostData[]>([])
1103
+ const [loading, setLoading] = useState(true)
1104
+ const [totalSavings, setTotalSavings] = useState(0)
1105
+
1106
+ useEffect(() => {
1107
+ fetchCostData()
1108
+ }, [])
1109
+
1110
+ const fetchCostData = async () => {
1111
+ try {
1112
+ // Fetch cost data from your monitoring service
1113
+ const response = await fetch('/api/cost/monitor')
1114
+ const data = await response.json()
1115
+
1116
+ setCostData(data.providers)
1117
+ setTotalSavings(data.potentialSavings)
1118
+ } catch (error) {
1119
+ console.error('Failed to fetch cost data:', error)
1120
+ } finally {
1121
+ setLoading(false)
1122
+ }
1123
+ }
1124
+
1125
+ const implementOptimization = async (provider: string, optimization: string) => {
1126
+ try {
1127
+ await fetch('/api/cost/optimize', {
1128
+ method: 'POST',
1129
+ headers: { 'Content-Type': 'application/json' },
1130
+ body: JSON.stringify({ provider, optimization })
1131
+ })
1132
+
1133
+ // Refresh data
1134
+ fetchCostData()
1135
+ } catch (error) {
1136
+ console.error('Failed to implement optimization:', error)
1137
+ }
1138
+ }
1139
+
1140
+ if (loading) {
1141
+ return <div>Loading cost data...</div>
1142
+ }
1143
+
1144
+ return (
1145
+ <div className="container mx-auto p-6">
1146
+ <div className="flex justify-between items-center mb-6">
1147
+ <h1 className="text-3xl font-bold">BaaS Cost Optimization</h1>
1148
+ <div className="text-right">
1149
+ <p className="text-sm text-gray-500">Potential Monthly Savings</p>
1150
+ <p className="text-2xl font-bold text-green-600">${totalSavings}</p>
1151
+ </div>
1152
+ </div>
1153
+
1154
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
1155
+ {costData.map((provider) => (
1156
+ <Card key={provider.provider}>
1157
+ <CardHeader>
1158
+ <CardTitle className="flex items-center justify-between">
1159
+ <span>{provider.provider}</span>
1160
+ <span className="text-sm font-normal text-gray-500">{provider.service}</span>
1161
+ </CardTitle>
1162
+ </CardHeader>
1163
+ <CardContent>
1164
+ <div className="space-y-4">
1165
+ <div>
1166
+ <p className="text-sm text-gray-500">Current Cost</p>
1167
+ <p className="text-xl font-bold">${provider.currentCost}</p>
1168
+ </div>
1169
+
1170
+ <div>
1171
+ <p className="text-sm text-gray-500">Projected Cost</p>
1172
+ <p className="text-lg font-semibold">${provider.projectedCost}</p>
1173
+ </div>
1174
+
1175
+ <div>
1176
+ <p className="text-sm text-gray-500">Usage</p>
1177
+ <div className="flex items-center space-x-2">
1178
+ <div className="flex-1 bg-gray-200 rounded-full h-2">
1179
+ <div
1180
+ className="bg-blue-600 h-2 rounded-full"
1181
+ style={{ width: `${(provider.usage.current / provider.usage.limit) * 100}%` }}
1182
+ />
1183
+ </div>
1184
+ <span className="text-sm text-gray-600">
1185
+ {provider.usage.current}/{provider.usage.limit} {provider.usage.unit}
1186
+ </span>
1187
+ </div>
1188
+ </div>
1189
+
1190
+ {provider.recommendations.length > 0 && (
1191
+ <div>
1192
+ <p className="text-sm font-medium text-gray-700 mb-2">Recommendations</p>
1193
+ <div className="space-y-2">
1194
+ {provider.recommendations.map((rec, index) => (
1195
+ <div key={index} className="flex items-start space-x-2">
1196
+ <div className="w-2 h-2 bg-yellow-400 rounded-full mt-1"></div>
1197
+ <div className="flex-1">
1198
+ <p className="text-sm text-gray-600">{rec}</p>
1199
+ <button
1200
+ onClick={() => implementOptimization(provider.provider, rec)}
1201
+ className="text-xs text-blue-600 hover:underline"
1202
+ >
1203
+ Implement
1204
+ </button>
1205
+ </div>
1206
+ </div>
1207
+ ))}
1208
+ </div>
1209
+ </div>
1210
+ )}
1211
+ </div>
1212
+ </CardContent>
1213
+ </Card>
1214
+ ))}
1215
+ </div>
1216
+ </div>
1217
+ )
1218
+ }
1219
+ ```
1220
+
1221
+ ---
1222
+
1223
+ Last Updated: 2025-11-25
1224
+ Examples: Production-ready implementations for all 9 providers
1225
+ Status: Production Ready (Enterprise)