@polymorphism-tech/morph-spec 3.1.0 → 4.2.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 (333) hide show
  1. package/CLAUDE.md +882 -3
  2. package/README.md +79 -18
  3. package/bin/detect-agents.js +1 -1
  4. package/bin/morph-spec.js +163 -26
  5. package/bin/task-manager.cjs +101 -7
  6. package/bin/validate.js +1 -1
  7. package/docs/cli-auto-detection.md +219 -0
  8. package/docs/getting-started.md +0 -5
  9. package/docs/llm-interaction-config.md +735 -0
  10. package/docs/troubleshooting.md +269 -0
  11. package/docs/v3.0/AGENTS.md +521 -0
  12. package/docs/v3.0/ANALYSIS.md +555 -0
  13. package/docs/v3.0/ARCHITECTURE.md +436 -0
  14. package/docs/v3.0/EXECUTION-FLOW.md +1304 -0
  15. package/docs/v3.0/FEATURES.md +688 -0
  16. package/docs/v3.0/README.md +231 -0
  17. package/docs/v3.0/ROADMAP.md +801 -0
  18. package/docs/validation-checklist.md +0 -1
  19. package/package.json +5 -1
  20. package/src/commands/agents/index.js +4 -0
  21. package/src/commands/agents/spawn-team.js +172 -0
  22. package/src/commands/{create-story.js → feature/create-story.js} +357 -354
  23. package/src/commands/feature/index.js +6 -0
  24. package/src/commands/{shard-spec.js → feature/shard-spec.js} +2 -2
  25. package/src/commands/{sprint-status.js → feature/sprint-status.js} +1 -1
  26. package/src/commands/{generate-context.js → generation/generate-context.js} +40 -40
  27. package/src/commands/{generate.js → generation/generate.js} +130 -3
  28. package/src/commands/generation/index.js +5 -0
  29. package/src/commands/index.js +16 -0
  30. package/src/commands/learning/capture-pattern.js +121 -0
  31. package/src/commands/learning/index.js +5 -0
  32. package/src/commands/learning/search-patterns.js +126 -0
  33. package/src/commands/{detect-agents.js → project/detect-agents.js} +178 -178
  34. package/src/commands/project/detect-workflow.js +174 -0
  35. package/src/commands/{detect.js → project/detect.js} +104 -104
  36. package/src/commands/{doctor.js → project/doctor.js} +356 -356
  37. package/src/commands/project/index.js +10 -0
  38. package/src/commands/{init.js → project/init.js} +305 -258
  39. package/src/commands/{sync.js → project/sync.js} +167 -167
  40. package/src/commands/{update.js → project/update.js} +240 -204
  41. package/src/commands/{advance-phase.js → state/advance-phase.js} +416 -266
  42. package/src/commands/state/approve.js +221 -0
  43. package/src/commands/state/index.js +8 -0
  44. package/src/commands/{rollback-phase.js → state/rollback-phase.js} +185 -185
  45. package/src/commands/{state.js → state/state.js} +334 -334
  46. package/src/commands/{validate-phase.js → state/validate-phase.js} +221 -221
  47. package/src/commands/tasks/index.js +4 -0
  48. package/src/commands/{task.js → tasks/task.js} +78 -78
  49. package/src/commands/templates/index.js +8 -0
  50. package/src/commands/templates/template-customize.js +101 -0
  51. package/src/commands/templates/template-list.js +128 -0
  52. package/src/commands/templates/template-render.js +95 -0
  53. package/src/commands/templates/template-show.js +131 -0
  54. package/src/commands/templates/template-validate.js +91 -0
  55. package/src/commands/utils/index.js +7 -0
  56. package/src/commands/utils/migrate-state.js +158 -0
  57. package/src/commands/{session-summary.js → utils/session-summary.js} +291 -291
  58. package/src/commands/{troubleshoot.js → utils/troubleshoot.js} +222 -222
  59. package/src/commands/utils/upgrade.js +346 -0
  60. package/src/commands/{analyze-blazor-concurrency.js → validation/analyze-blazor-concurrency.js} +193 -193
  61. package/src/commands/validation/index.js +8 -0
  62. package/src/commands/{lint-fluent.js → validation/lint-fluent.js} +352 -352
  63. package/src/commands/{validate-blazor-state.js → validation/validate-blazor-state.js} +210 -210
  64. package/src/commands/{validate-blazor.js → validation/validate-blazor.js} +156 -156
  65. package/src/commands/{validate-css.js → validation/validate-css.js} +84 -84
  66. package/src/core/index.js +10 -0
  67. package/src/core/registry/command-registry.js +302 -0
  68. package/src/core/registry/index.js +8 -0
  69. package/src/core/registry/validator-registry.js +204 -0
  70. package/src/core/state/index.js +8 -0
  71. package/src/core/state/phase-state-machine.js +214 -0
  72. package/src/{lib → core/state}/state-manager.js +572 -414
  73. package/src/core/templates/index.js +9 -0
  74. package/src/core/templates/template-data-sources.js +325 -0
  75. package/src/core/templates/template-registry.js +335 -0
  76. package/src/core/templates/template-renderer.js +477 -0
  77. package/src/core/templates/template-validator.js +296 -0
  78. package/src/core/workflows/index.js +7 -0
  79. package/src/core/workflows/workflow-detector.js +354 -0
  80. package/src/generator/config-generator.js +206 -0
  81. package/src/generator/templates/config.json.template +40 -0
  82. package/src/generator/templates/project.md.template +67 -0
  83. package/src/lib/{complexity-analyzer.js → analysis/complexity-analyzer.js} +441 -441
  84. package/src/lib/analysis/index.js +7 -0
  85. package/src/lib/checkpoints/checkpoint-hooks.js +258 -0
  86. package/src/lib/checkpoints/index.js +7 -0
  87. package/src/lib/detectors/config-detector.js +223 -223
  88. package/src/lib/detectors/conversation-analyzer.js +163 -163
  89. package/src/lib/{design-system-detector.js → detectors/design-system-detector.js} +187 -187
  90. package/src/lib/detectors/index.js +87 -84
  91. package/src/lib/detectors/standards-generator.js +275 -275
  92. package/src/lib/detectors/structure-detector.js +245 -245
  93. package/src/lib/{context-generator.js → generators/context-generator.js} +526 -516
  94. package/src/lib/generators/index.js +10 -0
  95. package/src/lib/generators/metadata-extractor.js +387 -0
  96. package/src/lib/{recap-generator.js → generators/recap-generator.js} +205 -205
  97. package/src/lib/learning/index.js +7 -0
  98. package/src/lib/orchestration/index.js +7 -0
  99. package/src/lib/{team-orchestrator.js → orchestration/team-orchestrator.js} +323 -323
  100. package/src/lib/stacks/index.js +7 -0
  101. package/src/lib/{stack-resolver.js → stacks/stack-resolver.js} +180 -148
  102. package/src/lib/standards/index.js +7 -0
  103. package/src/lib/{standards-context-injector.js → standards/standards-context-injector.js} +298 -288
  104. package/src/lib/troubleshooting/index.js +8 -0
  105. package/src/lib/{troubleshoot-grep.js → troubleshooting/troubleshoot-grep.js} +204 -204
  106. package/src/lib/{troubleshoot-index.js → troubleshooting/troubleshoot-index.js} +144 -144
  107. package/src/lib/validators/architecture/architecture-validator.js +387 -0
  108. package/src/lib/validators/architecture/index.js +7 -0
  109. package/src/lib/validators/architecture-validator.js +40 -367
  110. package/src/lib/{blazor-concurrency-analyzer.js → validators/blazor/blazor-concurrency-analyzer.js} +277 -288
  111. package/src/lib/{blazor-state-validator.js → validators/blazor/blazor-state-validator.js} +279 -291
  112. package/src/lib/{blazor-validator.js → validators/blazor/blazor-validator.js} +369 -374
  113. package/src/lib/validators/blazor/index.js +9 -0
  114. package/src/lib/validators/content/content-validator.js +351 -0
  115. package/src/lib/validators/content/index.js +7 -0
  116. package/src/lib/validators/content-validator.js +164 -0
  117. package/src/lib/validators/{contract-compliance-validator.js → contracts/contract-compliance-validator.js} +273 -273
  118. package/src/lib/validators/contracts/index.js +7 -0
  119. package/src/lib/{css-validator.js → validators/css/css-validator.js} +352 -352
  120. package/src/lib/validators/css/index.js +7 -0
  121. package/src/lib/validators/{design-system-validator.js → design-system/design-system-validator.js} +231 -231
  122. package/src/lib/validators/design-system/index.js +7 -0
  123. package/src/lib/validators/package-validator.js +41 -340
  124. package/src/lib/validators/packages/index.js +7 -0
  125. package/src/lib/validators/packages/package-validator.js +360 -0
  126. package/src/lib/validators/shared/index.js +12 -0
  127. package/src/lib/validators/shared/issue-counter.js +18 -0
  128. package/src/lib/validators/shared/result-formatter.js +124 -0
  129. package/src/lib/{spec-validator.js → validators/spec-validator.js} +258 -258
  130. package/src/lib/validators/ui/index.js +7 -0
  131. package/src/lib/validators/ui/ui-contrast-validator.js +422 -0
  132. package/src/lib/validators/ui-contrast-validator.js +31 -409
  133. package/src/lib/{validation-runner.js → validators/validation-runner.js} +286 -284
  134. package/src/llm/analyzer.js +215 -0
  135. package/src/llm/environment-detector.js +43 -0
  136. package/src/llm/few-shot-examples.js +216 -0
  137. package/src/llm/project-config-schema.json +188 -0
  138. package/src/llm/prompt-builder.js +96 -0
  139. package/src/orchestrator.js +206 -0
  140. package/src/sanitizer/context-sanitizer.js +221 -0
  141. package/src/sanitizer/patterns.js +163 -0
  142. package/src/scanner/project-scanner.js +242 -0
  143. package/src/ui/diff-display.js +91 -0
  144. package/src/ui/interactive-wizard.js +96 -0
  145. package/src/ui/user-review.js +211 -0
  146. package/src/ui/wizard-questions.js +188 -0
  147. package/src/utils/color-utils.js +70 -0
  148. package/src/utils/file-copier.js +188 -189
  149. package/src/utils/process-handler.js +97 -0
  150. package/src/writer/file-writer.js +86 -0
  151. package/stacks/blazor-azure/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +3 -3
  152. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/api-designer.md +59 -0
  153. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/dotnet-senior.md +45 -255
  154. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ef-modeler.md +33 -88
  155. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ms-agent-expert.md +25 -89
  156. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/hangfire-orchestrator.md +64 -0
  157. package/stacks/blazor-azure/.morph/config/agents.json +879 -764
  158. package/stacks/blazor-azure/.morph/hooks/{pre-commit-tests.sh → pre-commit/tests-csharp.sh} +3 -2
  159. package/stacks/blazor-azure/.morph/templates/.gitkeep +0 -0
  160. package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/cd-prod.yml.hbs +41 -0
  161. package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/cd-staging.yml.hbs +24 -0
  162. package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/ci-build.yml.hbs +23 -0
  163. package/stacks/nextjs-supabase/.claude/commands/morph-apply.md +221 -0
  164. package/stacks/nextjs-supabase/.claude/commands/morph-archive.md +79 -0
  165. package/stacks/nextjs-supabase/.claude/commands/morph-deploy.md +529 -0
  166. package/stacks/nextjs-supabase/.claude/commands/morph-infra.md +209 -0
  167. package/stacks/nextjs-supabase/.claude/commands/morph-preflight.md +227 -0
  168. package/stacks/nextjs-supabase/.claude/commands/morph-proposal.md +122 -0
  169. package/stacks/nextjs-supabase/.claude/commands/morph-status.md +86 -0
  170. package/stacks/nextjs-supabase/.claude/commands/morph-troubleshoot.md +122 -0
  171. package/stacks/nextjs-supabase/.claude/settings.local.json +6 -0
  172. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +30 -150
  173. package/stacks/nextjs-supabase/.morph/config/agents.json +345 -345
  174. package/stacks/nextjs-supabase/.morph/hooks/pre-commit/tests-typescript.sh +61 -0
  175. package/stacks/nextjs-supabase/.morph/templates/.gitkeep +0 -0
  176. package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/cd-prod.yml.hbs +22 -0
  177. package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/cd-staging.yml.hbs +22 -0
  178. package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/ci-build.yml.hbs +35 -0
  179. package/stacks/nextjs-supabase/README.md +6 -15
  180. package/bin/render-template.js +0 -303
  181. package/bin/semantic-detect-agents.js +0 -247
  182. package/bin/validate-agents-skills.js +0 -257
  183. package/bin/validate-agents.js +0 -70
  184. package/bin/validate-phase.js +0 -263
  185. package/docs/examples.md +0 -328
  186. package/scripts/reorganize-skills.cjs +0 -175
  187. package/scripts/validate-agents-structure.cjs +0 -52
  188. package/scripts/validate-skills.cjs +0 -180
  189. package/src/commands/deploy.js +0 -780
  190. package/src/lib/continuous-validator.js +0 -421
  191. package/src/lib/decision-constraint-loader.js +0 -109
  192. package/src/lib/design-system-scaffolder.js +0 -299
  193. package/src/lib/hook-executor.js +0 -257
  194. package/src/lib/mockup-generator.js +0 -366
  195. package/src/lib/ui-detector.js +0 -350
  196. package/stacks/blazor-azure/.azure/README.md +0 -293
  197. package/stacks/blazor-azure/.azure/docs/azure-devops-setup.md +0 -454
  198. package/stacks/blazor-azure/.azure/docs/branch-strategy.md +0 -398
  199. package/stacks/blazor-azure/.azure/docs/local-development.md +0 -515
  200. package/stacks/blazor-azure/.azure/pipelines/pipeline-variables.yml +0 -34
  201. package/stacks/blazor-azure/.azure/pipelines/prod-pipeline.yml +0 -319
  202. package/stacks/blazor-azure/.azure/pipelines/staging-pipeline.yml +0 -234
  203. package/stacks/blazor-azure/.azure/pipelines/templates/build-dotnet.yml +0 -75
  204. package/stacks/blazor-azure/.azure/pipelines/templates/deploy-app-service.yml +0 -94
  205. package/stacks/blazor-azure/.azure/pipelines/templates/deploy-container-app.yml +0 -120
  206. package/stacks/blazor-azure/.azure/pipelines/templates/infra-deploy.yml +0 -90
  207. package/stacks/blazor-azure/.claude/settings.local.json +0 -15
  208. package/stacks/blazor-azure/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +0 -392
  209. package/stacks/blazor-azure/.morph/docs/workflows/design-impl.md +0 -37
  210. package/stacks/blazor-azure/.morph/docs/workflows/enforcement-pipeline.md +0 -668
  211. package/stacks/blazor-azure/.morph/docs/workflows/fast-track.md +0 -29
  212. package/stacks/blazor-azure/.morph/docs/workflows/full-morph.md +0 -76
  213. package/stacks/blazor-azure/.morph/docs/workflows/standard.md +0 -44
  214. package/stacks/blazor-azure/.morph/docs/workflows/ui-refresh.md +0 -39
  215. package/stacks/blazor-azure/.morph/examples/api-nextjs/README.md +0 -241
  216. package/stacks/blazor-azure/.morph/examples/api-nextjs/contracts.ts +0 -307
  217. package/stacks/blazor-azure/.morph/examples/api-nextjs/spec.md +0 -399
  218. package/stacks/blazor-azure/.morph/examples/api-nextjs/tasks.md +0 -168
  219. package/stacks/blazor-azure/.morph/examples/micro-saas/README.md +0 -125
  220. package/stacks/blazor-azure/.morph/examples/micro-saas/contracts.cs +0 -358
  221. package/stacks/blazor-azure/.morph/examples/micro-saas/decisions.md +0 -246
  222. package/stacks/blazor-azure/.morph/examples/micro-saas/spec.md +0 -236
  223. package/stacks/blazor-azure/.morph/examples/micro-saas/tasks.md +0 -150
  224. package/stacks/blazor-azure/.morph/examples/multi-agent/README.md +0 -309
  225. package/stacks/blazor-azure/.morph/examples/multi-agent/contracts.cs +0 -433
  226. package/stacks/blazor-azure/.morph/examples/multi-agent/spec.md +0 -479
  227. package/stacks/blazor-azure/.morph/examples/multi-agent/tasks.md +0 -185
  228. package/stacks/blazor-azure/.morph/examples/scheduled-reports/decisions.md +0 -158
  229. package/stacks/blazor-azure/.morph/examples/scheduled-reports/proposal.md +0 -95
  230. package/stacks/blazor-azure/.morph/examples/scheduled-reports/spec.md +0 -267
  231. package/stacks/blazor-azure/.morph/examples/state-v3.json +0 -188
  232. package/stacks/blazor-azure/.morph/hooks/README.md +0 -348
  233. package/stacks/blazor-azure/.morph/hooks/pre-commit-agents.sh +0 -24
  234. package/stacks/blazor-azure/.morph/hooks/pre-commit-all.sh +0 -48
  235. package/stacks/blazor-azure/.morph/hooks/pre-commit-specs.sh +0 -49
  236. package/stacks/blazor-azure/.morph/hooks/task-completed.js +0 -73
  237. package/stacks/blazor-azure/.morph/hooks/teammate-idle.js +0 -68
  238. package/stacks/blazor-azure/.morph/standards/agent-framework-blazor-ui.md +0 -359
  239. package/stacks/blazor-azure/.morph/standards/agent-framework-production.md +0 -410
  240. package/stacks/blazor-azure/.morph/standards/agent-framework-setup.md +0 -413
  241. package/stacks/blazor-azure/.morph/standards/agent-framework-workflows.md +0 -349
  242. package/stacks/blazor-azure/.morph/standards/agent-teams-workflow.md +0 -474
  243. package/stacks/blazor-azure/.morph/standards/architecture.md +0 -325
  244. package/stacks/blazor-azure/.morph/standards/azure.md +0 -605
  245. package/stacks/blazor-azure/.morph/standards/coding.md +0 -377
  246. package/stacks/blazor-azure/.morph/standards/dotnet10-migration.md +0 -520
  247. package/stacks/blazor-azure/.morph/standards/fluent-ui-setup.md +0 -590
  248. package/stacks/blazor-azure/.morph/standards/migration-guide.md +0 -514
  249. package/stacks/blazor-azure/.morph/standards/passkeys-auth.md +0 -423
  250. package/stacks/blazor-azure/.morph/standards/vector-search-rag.md +0 -536
  251. package/stacks/blazor-azure/.morph/templates/CONTEXT-FEATURE.md +0 -276
  252. package/stacks/blazor-azure/.morph/templates/CONTEXT.md +0 -170
  253. package/stacks/blazor-azure/.morph/templates/FluentDesignTheme.cs +0 -149
  254. package/stacks/blazor-azure/.morph/templates/MudTheme.cs +0 -281
  255. package/stacks/blazor-azure/.morph/templates/agent.cs +0 -163
  256. package/stacks/blazor-azure/.morph/templates/clarify-questions.md +0 -159
  257. package/stacks/blazor-azure/.morph/templates/component.razor +0 -239
  258. package/stacks/blazor-azure/.morph/templates/contracts/Commands.cs +0 -74
  259. package/stacks/blazor-azure/.morph/templates/contracts/Entities.cs +0 -25
  260. package/stacks/blazor-azure/.morph/templates/contracts/Queries.cs +0 -74
  261. package/stacks/blazor-azure/.morph/templates/contracts/README.md +0 -74
  262. package/stacks/blazor-azure/.morph/templates/contracts.cs +0 -217
  263. package/stacks/blazor-azure/.morph/templates/decisions.md +0 -123
  264. package/stacks/blazor-azure/.morph/templates/design-system.css +0 -226
  265. package/stacks/blazor-azure/.morph/templates/infra/.dockerignore.example +0 -89
  266. package/stacks/blazor-azure/.morph/templates/infra/Dockerfile.example +0 -82
  267. package/stacks/blazor-azure/.morph/templates/infra/README.md +0 -286
  268. package/stacks/blazor-azure/.morph/templates/infra/app-insights.bicep +0 -63
  269. package/stacks/blazor-azure/.morph/templates/infra/app-service.bicep +0 -164
  270. package/stacks/blazor-azure/.morph/templates/infra/azure-pipelines-deploy.yml +0 -480
  271. package/stacks/blazor-azure/.morph/templates/infra/container-app-env.bicep +0 -49
  272. package/stacks/blazor-azure/.morph/templates/infra/container-app.bicep +0 -156
  273. package/stacks/blazor-azure/.morph/templates/infra/deploy-checklist.md +0 -426
  274. package/stacks/blazor-azure/.morph/templates/infra/deploy.ps1 +0 -229
  275. package/stacks/blazor-azure/.morph/templates/infra/deploy.sh +0 -208
  276. package/stacks/blazor-azure/.morph/templates/infra/key-vault.bicep +0 -91
  277. package/stacks/blazor-azure/.morph/templates/infra/main.bicep +0 -189
  278. package/stacks/blazor-azure/.morph/templates/infra/parameters.dev.json +0 -29
  279. package/stacks/blazor-azure/.morph/templates/infra/parameters.prod.json +0 -29
  280. package/stacks/blazor-azure/.morph/templates/infra/parameters.staging.json +0 -29
  281. package/stacks/blazor-azure/.morph/templates/infra/sql-database.bicep +0 -103
  282. package/stacks/blazor-azure/.morph/templates/infra/storage.bicep +0 -106
  283. package/stacks/blazor-azure/.morph/templates/integrations/asaas-client.cs +0 -387
  284. package/stacks/blazor-azure/.morph/templates/integrations/asaas-webhook.cs +0 -351
  285. package/stacks/blazor-azure/.morph/templates/integrations/azure-identity-config.cs +0 -288
  286. package/stacks/blazor-azure/.morph/templates/integrations/clerk-config.cs +0 -258
  287. package/stacks/blazor-azure/.morph/templates/job.cs +0 -171
  288. package/stacks/blazor-azure/.morph/templates/migration.cs +0 -83
  289. package/stacks/blazor-azure/.morph/templates/proposal.md +0 -141
  290. package/stacks/blazor-azure/.morph/templates/recap.md +0 -94
  291. package/stacks/blazor-azure/.morph/templates/repository.cs +0 -141
  292. package/stacks/blazor-azure/.morph/templates/saas/subscription.cs +0 -347
  293. package/stacks/blazor-azure/.morph/templates/saas/tenant.cs +0 -338
  294. package/stacks/blazor-azure/.morph/templates/service.cs +0 -139
  295. package/stacks/blazor-azure/.morph/templates/simulation.md +0 -353
  296. package/stacks/blazor-azure/.morph/templates/spec.md +0 -149
  297. package/stacks/blazor-azure/.morph/templates/sprint-status.yaml +0 -68
  298. package/stacks/blazor-azure/.morph/templates/state.template.json +0 -222
  299. package/stacks/blazor-azure/.morph/templates/story.md +0 -143
  300. package/stacks/blazor-azure/.morph/templates/tasks.md +0 -257
  301. package/stacks/blazor-azure/.morph/templates/test.cs +0 -239
  302. package/stacks/blazor-azure/.morph/templates/ui-components.md +0 -362
  303. package/stacks/blazor-azure/.morph/templates/ui-design-system.md +0 -286
  304. package/stacks/blazor-azure/.morph/templates/ui-flows.md +0 -336
  305. package/stacks/blazor-azure/.morph/templates/ui-mockups.md +0 -133
  306. package/stacks/nextjs-supabase/.morph/docs/easypanel-setup.md +0 -169
  307. package/stacks/nextjs-supabase/.morph/docs/supabase-mcp-setup.md +0 -247
  308. package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/README.md +0 -697
  309. package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/spec.md +0 -85
  310. package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/tasks.md +0 -86
  311. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/README.md +0 -498
  312. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/decisions.md +0 -121
  313. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/spec.md +0 -138
  314. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/tasks.md +0 -162
  315. package/stacks/nextjs-supabase/.morph/standards/easypanel-deploy.md +0 -191
  316. package/stacks/nextjs-supabase/.morph/standards/nextjs-patterns.md +0 -193
  317. package/stacks/nextjs-supabase/.morph/standards/supabase-auth.md +0 -171
  318. package/stacks/nextjs-supabase/.morph/standards/supabase-pgvector.md +0 -164
  319. package/stacks/nextjs-supabase/.morph/standards/supabase-rls.md +0 -179
  320. package/stacks/nextjs-supabase/.morph/standards/supabase-storage.md +0 -148
  321. package/stacks/nextjs-supabase/.morph/templates/contracts.cs +0 -173
  322. package/stacks/nextjs-supabase/.morph/templates/contracts.ts +0 -168
  323. package/stacks/nextjs-supabase/.morph/templates/decisions.md +0 -115
  324. package/stacks/nextjs-supabase/.morph/templates/dockerfile-api.dockerfile +0 -38
  325. package/stacks/nextjs-supabase/.morph/templates/dockerfile-web.dockerfile +0 -48
  326. package/stacks/nextjs-supabase/.morph/templates/proposal.md +0 -145
  327. package/stacks/nextjs-supabase/.morph/templates/recap.md +0 -134
  328. package/stacks/nextjs-supabase/.morph/templates/rls-policy.sql +0 -57
  329. package/stacks/nextjs-supabase/.morph/templates/spec.md +0 -231
  330. package/stacks/nextjs-supabase/.morph/templates/supabase-migration.sql +0 -100
  331. package/stacks/nextjs-supabase/.morph/templates/tasks.md +0 -257
  332. /package/src/lib/{design-system-generator.js → generators/design-system-generator.js} +0 -0
  333. /package/src/lib/{learning-system.js → learning/learning-system.js} +0 -0
@@ -1,121 +0,0 @@
1
- # Multi-Tenant SaaS - Architectural Decision Records
2
-
3
- ## ADR-001: RLS-Based Tenant Isolation vs Schema-Per-Tenant
4
-
5
- **Status**: Accepted
6
-
7
- **Context**: Choose a multi-tenancy strategy for data isolation. The two main approaches are (a) shared database with Row Level Security filtering by tenant_id, and (b) separate PostgreSQL schema per tenant.
8
-
9
- **Decision**: RLS-based tenant isolation with a single shared schema.
10
-
11
- **Rationale**:
12
- - Supabase natively supports RLS with built-in functions like `auth.uid()` and custom JWT claims
13
- - Single schema simplifies migrations (one migration applies to all tenants)
14
- - More cost-effective: one Supabase project serves all tenants
15
- - Scales well to thousands of small-to-medium tenants
16
- - Custom JWT claim `app_metadata.tenant_id` provides tenant context automatically
17
-
18
- **Alternatives Considered**:
19
- - Schema-per-tenant: Better isolation but Supabase does not natively manage multiple schemas per project. Migration management becomes complex. Operational overhead grows linearly with tenant count.
20
- - Database-per-tenant: Maximum isolation but requires separate Supabase projects. Cost-prohibitive ($25/tenant/month on Pro).
21
-
22
- **Consequences**:
23
- - All queries must include tenant_id (enforced by RLS, not application code)
24
- - Careful attention needed for admin/service-role queries that bypass RLS
25
- - Bulk data export for a single tenant requires explicit filtering
26
- - Index strategy must account for tenant_id prefix on all key queries
27
-
28
- ---
29
-
30
- ## ADR-002: Stripe for Subscription Billing
31
-
32
- **Status**: Accepted
33
-
34
- **Context**: Choose a billing provider for SaaS subscription management.
35
-
36
- **Decision**: Stripe Billing with Checkout Sessions and Customer Portal.
37
-
38
- **Rationale**:
39
- - Industry standard for SaaS billing with mature subscription lifecycle management
40
- - Stripe Checkout handles PCI compliance (no card data on our servers)
41
- - Customer Portal lets users self-manage subscriptions, reducing support burden
42
- - Webhook-driven architecture integrates cleanly with our event-based approach
43
- - Extensive test mode for development without real charges
44
- - Global reach with support for 135+ currencies
45
-
46
- **Alternatives Considered**:
47
- - Paddle: Simpler tax handling (Merchant of Record) but less customization and higher fees
48
- - LemonSqueezy: Good for indie hackers but less mature API and limited webhook events
49
- - Custom implementation: Too complex for MVP, PCI compliance burden
50
-
51
- **Consequences**:
52
- - Stripe fees: 2.9% + $0.30 per transaction
53
- - Webhook handler must be idempotent (Stripe retries on failure)
54
- - Subscription state must be synced between Stripe and our database
55
- - Need to handle edge cases: failed payments, plan changes mid-cycle, proration
56
-
57
- ---
58
-
59
- ## ADR-003: pgvector for AI-Powered Search
60
-
61
- **Status**: Accepted
62
-
63
- **Context**: Choose a vector storage and similarity search solution for semantic document search.
64
-
65
- **Decision**: pgvector extension on Supabase PostgreSQL.
66
-
67
- **Rationale**:
68
- - Native PostgreSQL extension, no additional infrastructure needed
69
- - Supabase Pro includes pgvector out of the box
70
- - Keeps vectors co-located with tenant data (RLS applies to vector queries too)
71
- - IVFFlat index provides good performance up to ~1M vectors per tenant
72
- - Cosine similarity search with SQL-native syntax
73
- - No vendor lock-in to proprietary vector databases
74
-
75
- **Alternatives Considered**:
76
- - Pinecone: Better performance at scale but adds another service, separate billing, and no native tenant isolation (would need namespace-per-tenant)
77
- - Qdrant: Open source and performant but requires self-hosting another service
78
- - Supabase Edge Functions + Pinecone: Adds latency and complexity for the AI path
79
-
80
- **Consequences**:
81
- - Embedding dimension fixed at 1536 (text-embedding-3-small). Changing models requires re-embedding all documents
82
- - IVFFlat index requires periodic `REINDEX` as data grows significantly
83
- - For >1M documents per tenant, consider HNSW index (higher memory, faster queries)
84
- - OpenAI API call required for each search query (adds ~200ms latency)
85
-
86
- ---
87
-
88
- ## ADR-004: Custom JWT Claims for Tenant Context
89
-
90
- **Status**: Accepted
91
-
92
- **Context**: Determine how to pass tenant context through the authentication flow so that RLS policies and API endpoints can identify the current tenant.
93
-
94
- **Decision**: Store `tenant_id` in Supabase Auth `app_metadata`, which is included in the JWT automatically.
95
-
96
- **Rationale**:
97
- - Supabase Auth includes `app_metadata` in every JWT token by default
98
- - No additional API calls needed to resolve tenant context
99
- - RLS policies can read `request.jwt.claims -> 'app_metadata' -> 'tenant_id'`
100
- - .NET API can extract tenant_id from JWT claims without database lookup
101
- - Set via database trigger when user joins a tenant (no application code needed for claim updates)
102
-
103
- **Alternatives Considered**:
104
- - Header-based (`X-Tenant-ID`): Requires client to send header on every request, vulnerable to spoofing unless validated server-side
105
- - Subdomain-based: Good UX but requires wildcard DNS, SSL, and URL parsing on every request. Supabase Auth redirect URLs become complex.
106
- - Database lookup per request: Adds latency and database load to every authenticated request
107
-
108
- **Implementation**:
109
- - Trigger on `tenant_members` INSERT sets `raw_app_meta_data.tenant_id`
110
- - User must re-authenticate (or refresh token) after joining a tenant to get updated claims
111
- - Multi-tenant users: current implementation supports one active tenant per session. Switching tenants requires token refresh.
112
-
113
- **Consequences**:
114
- - Token refresh needed when user switches tenants
115
- - app_metadata is read-only from client side (only service_role can modify)
116
- - JWT size increases slightly (~50 bytes for tenant_id claim)
117
- - Users without a tenant_id claim are redirected to onboarding
118
-
119
- ---
120
-
121
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,138 +0,0 @@
1
- # Multi-Tenant SaaS - Specification
2
-
3
- ## 1. Overview
4
-
5
- Multi-tenant SaaS platform with tenant isolation via PostgreSQL RLS, Stripe subscription billing, team management, and AI-powered semantic search using pgvector.
6
-
7
- ### 1.1 Objectives
8
-
9
- - Tenant isolation at the database level via RLS with custom JWT claims
10
- - Subscription billing with Stripe (free, starter, pro tiers)
11
- - Team management with invite flows and role-based access
12
- - AI-powered document search using OpenAI embeddings + pgvector
13
- - Dashboard with tenant-scoped metrics and usage tracking
14
-
15
- ### 1.2 Personas
16
-
17
- | Persona | Description |
18
- |---------|-------------|
19
- | **Tenant Owner** | Creates tenant, manages billing and team |
20
- | **Tenant Admin** | Manages team members and settings |
21
- | **Tenant Member** | Uses the platform (documents, search) |
22
- | **Platform Admin** | Super admin with cross-tenant visibility |
23
-
24
- ## 2. Functional Requirements
25
-
26
- ### 2.1 Tenant Management
27
-
28
- | ID | Requirement |
29
- |----|-------------|
30
- | TEN-001 | Create tenant during onboarding (name, slug) |
31
- | TEN-002 | Tenant slug used for identification (unique) |
32
- | TEN-003 | Tenant settings page (name, logo) |
33
- | TEN-004 | Tenant status lifecycle: active, past_due, suspended |
34
- | TEN-005 | tenant_id stored in Supabase Auth app_metadata for JWT claims |
35
-
36
- ### 2.2 Billing (Stripe)
37
-
38
- | ID | Requirement |
39
- |----|-------------|
40
- | BILL-001 | Plans: Free, Starter ($29/mo), Pro ($79/mo) |
41
- | BILL-002 | Stripe Checkout for subscription creation |
42
- | BILL-003 | Stripe Customer Portal for plan management |
43
- | BILL-004 | Webhook handling: subscription.created, updated, deleted |
44
- | BILL-005 | Webhook handling: invoice.payment_failed |
45
- | BILL-006 | Grace period of 7 days on payment failure before suspension |
46
-
47
- ### 2.3 Team Management
48
-
49
- | ID | Requirement |
50
- |----|-------------|
51
- | TEAM-001 | Invite members by email |
52
- | TEAM-002 | Roles: owner, admin, member |
53
- | TEAM-003 | Owner can promote/demote members |
54
- | TEAM-004 | Admin can invite and remove members |
55
- | TEAM-005 | Member limits per plan (Free: 2, Starter: 5, Pro: 25) |
56
-
57
- ### 2.4 AI Search (pgvector)
58
-
59
- | ID | Requirement |
60
- |----|-------------|
61
- | SEARCH-001 | Upload documents with automatic embedding generation |
62
- | SEARCH-002 | Semantic search across tenant documents |
63
- | SEARCH-003 | Configurable similarity threshold (default 0.7) |
64
- | SEARCH-004 | Search results ranked by cosine similarity |
65
- | SEARCH-005 | Search quota per plan (Free: 100/mo, Starter: 1K/mo, Pro: 10K/mo) |
66
-
67
- ### 2.5 Dashboard
68
-
69
- | ID | Requirement |
70
- |----|-------------|
71
- | DASH-001 | Overview: total documents, team size, storage used, plan |
72
- | DASH-002 | Search usage counter (monthly resets) |
73
- | DASH-003 | Quick actions: invite member, upload document, search |
74
- | DASH-004 | Billing status and upgrade prompt |
75
-
76
- ## 3. Non-Functional Requirements
77
-
78
- ### 3.1 Performance
79
-
80
- | ID | Requirement |
81
- |----|-------------|
82
- | PERF-001 | API response < 200ms (P95) for CRUD endpoints |
83
- | PERF-002 | Semantic search < 500ms (P95) for 100K documents |
84
- | PERF-003 | pgvector IVFFlat index for sub-linear search time |
85
-
86
- ### 3.2 Security
87
-
88
- | ID | Requirement |
89
- |----|-------------|
90
- | SEC-001 | RLS enforced on all tenant-scoped tables |
91
- | SEC-002 | Stripe webhook signature validation |
92
- | SEC-003 | Service role key never exposed to frontend |
93
- | SEC-004 | Rate limiting per tenant (not per user) |
94
- | SEC-005 | Audit log for team management actions |
95
-
96
- ### 3.3 Data Isolation
97
-
98
- | ID | Requirement |
99
- |----|-------------|
100
- | ISO-001 | Single database with tenant_id column on all data tables |
101
- | ISO-002 | RLS policies read tenant_id from JWT app_metadata |
102
- | ISO-003 | No cross-tenant data leakage (validated by tests) |
103
-
104
- ## 4. Plans and Limits
105
-
106
- | Feature | Free | Starter | Pro |
107
- |---------|------|---------|-----|
108
- | Team Members | 2 | 5 | 25 |
109
- | Documents | 100 | 1,000 | 10,000 |
110
- | Storage | 100MB | 1GB | 10GB |
111
- | Searches/month | 100 | 1,000 | 10,000 |
112
- | Support | Community | Email | Priority |
113
- | Price/month | $0 | $29 | $79 |
114
-
115
- ## 5. Integrations
116
-
117
- ### 5.1 Stripe
118
-
119
- - Customer management (one customer per tenant)
120
- - Subscription lifecycle
121
- - Checkout sessions and Customer Portal
122
- - Webhook handling for payment events
123
-
124
- ### 5.2 OpenAI
125
-
126
- - text-embedding-3-small for document embeddings (1536 dimensions)
127
- - Called server-side only (API key never on frontend)
128
-
129
- ### 5.3 Supabase
130
-
131
- - Auth with custom claims (tenant_id in app_metadata)
132
- - PostgreSQL with RLS for tenant isolation
133
- - pgvector extension for similarity search
134
- - Storage for document files (per-tenant buckets)
135
-
136
- ---
137
-
138
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,162 +0,0 @@
1
- # Multi-Tenant SaaS - Tasks
2
-
3
- ## Phase 1: Supabase Setup
4
-
5
- | ID | Task | Dependencies | Estimate |
6
- |----|------|--------------|----------|
7
- | T001 | Create Supabase Pro project with pgvector extension enabled | - | S |
8
- | T002 | Create tenants table and tenant_members table with RLS policies | T001 | M |
9
- | T003 | Create auth.tenant_id() helper function for RLS | T001 | S |
10
- | T004 | Create trigger to set app_metadata.tenant_id on tenant_members INSERT | T002 | M |
11
-
12
- ## Phase 2: Tenant Data Model
13
-
14
- | ID | Task | Dependencies | Estimate |
15
- |----|------|--------------|----------|
16
- | T005 | Create documents table with tenant_id, embedding column (vector 1536), and RLS | T003 | M |
17
- | T006 | Create IVFFlat index on documents.embedding for cosine similarity search | T005 | S |
18
- | T007 | Create search_logs table for usage tracking (searches per month per tenant) | T003 | S |
19
- | T008 | Create Supabase Storage bucket with per-tenant folder policies | T001 | S |
20
-
21
- ## Phase 3: .NET API Core
22
-
23
- | ID | Task | Dependencies | Estimate |
24
- |----|------|--------------|----------|
25
- | T009 | Create .NET 10 Minimal API project with Dapper, Npgsql, Stripe.net | - | S |
26
- | T010 | Configure JWT authentication with Supabase JWT secret and tenant_id claim extraction | T001, T009 | M |
27
- | T011 | Create TenantMiddleware to extract and validate tenant_id from JWT claims | T010 | M |
28
- | T012 | Configure CORS and health check endpoints | T009 | S |
29
-
30
- ## Phase 4: Stripe Billing Integration
31
-
32
- | ID | Task | Dependencies | Estimate |
33
- |----|------|--------------|----------|
34
- | T013 | Create Stripe products and prices (Free, Starter $29, Pro $79) in Stripe Dashboard | - | S |
35
- | T014 | Implement CreateCheckoutSession endpoint (creates Stripe customer + checkout) | T009, T013 | M |
36
- | T015 | Implement Stripe Customer Portal endpoint for subscription management | T014 | S |
37
- | T016 | Implement Stripe webhook handler (subscription.created/updated/deleted, invoice.payment_failed) | T009, T013 | L |
38
- | T017 | Add plan enforcement middleware (check limits: members, documents, searches) | T016 | M |
39
-
40
- ## Phase 5: Team Management Endpoints
41
-
42
- | ID | Task | Dependencies | Estimate |
43
- |----|------|--------------|----------|
44
- | T018 | Implement invite member endpoint (create tenant_member, trigger claim update) | T011 | M |
45
- | T019 | Implement list members, update role, remove member endpoints | T011 | M |
46
- | T020 | Add member count validation against plan limits | T017 | S |
47
-
48
- ## Phase 6: AI Search Endpoints
49
-
50
- | ID | Task | Dependencies | Estimate |
51
- |----|------|--------------|----------|
52
- | T021 | Implement document upload endpoint with OpenAI embedding generation | T005, T011 | L |
53
- | T022 | Implement semantic search endpoint with pgvector cosine similarity | T006, T011 | M |
54
- | T023 | Implement search quota tracking and enforcement per plan | T007, T017 | M |
55
-
56
- ## Phase 7: Dashboard Endpoint
57
-
58
- | ID | Task | Dependencies | Estimate |
59
- |----|------|--------------|----------|
60
- | T024 | Implement dashboard metrics endpoint (documents, members, storage, plan, searches) | T011 | M |
61
-
62
- ## Phase 8: Next.js Frontend Core
63
-
64
- | ID | Task | Dependencies | Estimate |
65
- |----|------|--------------|----------|
66
- | T025 | Create Next.js 15 project with Tailwind CSS, @supabase/ssr | - | S |
67
- | T026 | Implement Supabase client (browser) and server client with cookie handling | T025, T001 | M |
68
- | T027 | Create login/signup pages with Supabase Auth | T026 | M |
69
- | T028 | Create auth callback route and Next.js middleware for protected routes | T026 | M |
70
- | T029 | Create onboarding page (create tenant for new users without tenant_id) | T026 | M |
71
-
72
- ## Phase 9: Next.js Dashboard Pages
73
-
74
- | ID | Task | Dependencies | Estimate |
75
- |----|------|--------------|----------|
76
- | T030 | Create TenantProvider context component (reads tenant from session) | T028 | M |
77
- | T031 | Create dashboard layout with sidebar navigation | T030 | M |
78
- | T032 | Create dashboard overview page with metric cards | T024, T031 | M |
79
- | T033 | Create documents page (list, upload, delete) | T021, T031 | M |
80
- | T034 | Create search page with query input and ranked results | T022, T031 | M |
81
-
82
- ## Phase 10: Team and Billing Pages
83
-
84
- | ID | Task | Dependencies | Estimate |
85
- |----|------|--------------|----------|
86
- | T035 | Create team management page (list members, invite, remove, change role) | T018, T031 | M |
87
- | T036 | Create billing page (current plan, upgrade button, Stripe Portal link) | T014, T031 | M |
88
- | T037 | Create settings page (tenant name, logo) | T031 | S |
89
-
90
- ## Phase 11: Docker and Deploy
91
-
92
- | ID | Task | Dependencies | Estimate |
93
- |----|------|--------------|----------|
94
- | T038 | Create Dockerfile.api (multi-stage .NET build) | T024 | S |
95
- | T039 | Create Dockerfile.web (Next.js standalone output) | T037 | S |
96
- | T040 | Create docker-compose.yml for local development | T038, T039 | S |
97
- | T041 | Configure EasyPanel services (API + Web) with env vars and health checks | T040 | M |
98
-
99
- ## Phase 12: Testing and Validation
100
-
101
- | ID | Task | Dependencies | Estimate |
102
- |----|------|--------------|----------|
103
- | T042 | Write RLS isolation tests (verify no cross-tenant data leakage) | T005 | M |
104
- | T043 | Write Stripe webhook handler tests (idempotency, signature validation) | T016 | M |
105
- | T044 | Write search endpoint tests (embedding, similarity threshold, quota) | T022 | M |
106
-
107
- ## Checkpoints
108
-
109
- | Checkpoint | After Tasks | Validation |
110
- |------------|-------------|------------|
111
- | CP1 | T004 | Supabase tenant setup complete, auth claims working |
112
- | CP2 | T008 | Full data model with RLS, pgvector, and storage |
113
- | CP3 | T012 | API skeleton with JWT auth and tenant middleware |
114
- | CP4 | T017 | Stripe billing fully integrated with webhooks |
115
- | CP5 | T020 | Team management working with plan limits |
116
- | CP6 | T024 | All API endpoints complete (search, dashboard, team, billing) |
117
- | CP7 | T029 | Auth flow complete (login, signup, onboarding, protected routes) |
118
- | CP8 | T037 | All frontend pages complete |
119
- | CP9 | T041 | Docker setup and EasyPanel deployment ready |
120
- | CP10 | T044 | All tests passing, no cross-tenant leakage |
121
-
122
- ## Legend
123
-
124
- - **S** = Small (< 1h)
125
- - **M** = Medium (1-3h)
126
- - **L** = Large (3-8h)
127
-
128
- ## Execution Order
129
-
130
- ```
131
- Supabase Setup (independent):
132
- T001 -> T002 -> T003 -> T004 (CP1)
133
- T005 -> T006 -> T007 -> T008 (CP2)
134
-
135
- API Core (after T001):
136
- T009 -> T010 -> T011 -> T012 (CP3)
137
-
138
- Billing (after API core):
139
- T013 -> T014 -> T015 -> T016 -> T017 (CP4)
140
-
141
- Team + Search + Dashboard (after billing):
142
- T018 -> T019 -> T020 (CP5)
143
- T021 -> T022 -> T023
144
- T024 (CP6)
145
-
146
- Frontend (after T001):
147
- T025 -> T026 -> T027 -> T028 -> T029 (CP7)
148
-
149
- Frontend Pages (after API + auth):
150
- T030 -> T031 -> T032 -> T033 -> T034
151
- T035 -> T036 -> T037 (CP8)
152
-
153
- Deploy:
154
- T038 -> T039 -> T040 -> T041 (CP9)
155
-
156
- Tests:
157
- T042 -> T043 -> T044 (CP10)
158
- ```
159
-
160
- ---
161
-
162
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,191 +0,0 @@
1
- # EasyPanel Deployment Standard
2
-
3
- > Stack: Next.js 15 + Supabase + .NET Backend
4
-
5
- ## Core Rules
6
-
7
- - ALWAYS use multi-stage Docker builds for minimal image size
8
- - ALWAYS configure health checks for zero-downtime deploys
9
- - NEVER hardcode secrets in Dockerfiles -- use EasyPanel environment variables
10
- - ALWAYS use `.dockerignore` to exclude node_modules, .git, .env files
11
- - SSL is automatic via Let's Encrypt -- no manual certificate management
12
-
13
- ## .NET 10 Dockerfile
14
-
15
- ```dockerfile
16
- FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
17
- WORKDIR /src
18
- COPY *.csproj .
19
- RUN dotnet restore
20
- COPY . .
21
- RUN dotnet publish -c Release -o /app/publish --no-restore
22
-
23
- FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
24
- WORKDIR /app
25
- RUN adduser --disabled-password --gecos "" appuser
26
- USER appuser
27
- COPY --from=build /app/publish .
28
- ENV ASPNETCORE_URLS=http://+:8080
29
- EXPOSE 8080
30
- HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
31
- CMD curl -f http://localhost:8080/health || exit 1
32
- ENTRYPOINT ["dotnet", "MyApp.Api.dll"]
33
- ```
34
-
35
- ## Next.js Standalone Dockerfile
36
-
37
- ```dockerfile
38
- FROM node:22-alpine AS base
39
-
40
- FROM base AS builder
41
- WORKDIR /app
42
- COPY package.json package-lock.json ./
43
- RUN npm ci
44
- COPY . .
45
- ENV NEXT_TELEMETRY_DISABLED=1
46
- RUN npm run build
47
-
48
- FROM base AS runner
49
- WORKDIR /app
50
- ENV NODE_ENV=production NEXT_TELEMETRY_DISABLED=1
51
- RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs
52
- COPY --from=builder /app/public ./public
53
- COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
54
- COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
55
- USER nextjs
56
- EXPOSE 3000
57
- ENV PORT=3000 HOSTNAME="0.0.0.0"
58
- HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
59
- CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
60
- CMD ["node", "server.js"]
61
- ```
62
-
63
- Required: `output: "standalone"` in `next.config.ts`.
64
-
65
- ## .dockerignore
66
-
67
- ```
68
- node_modules
69
- .next
70
- .git
71
- .env*
72
- *.md
73
- .vscode
74
- coverage
75
- test
76
- __tests__
77
- ```
78
-
79
- ## EasyPanel Service Config
80
-
81
- | Setting | .NET Backend | Next.js Frontend |
82
- |---------|-------------|-----------------|
83
- | Source | GitHub | GitHub |
84
- | Build method | Dockerfile | Dockerfile |
85
- | Dockerfile path | `./backend/Dockerfile` | `./frontend/Dockerfile` |
86
- | Port | 8080 | 3000 |
87
- | Domain | api.example.com | app.example.com |
88
-
89
- ### GitHub Integration
90
-
91
- 1. Generate GitHub PAT with `repo` scope
92
- 2. EasyPanel: Settings > GitHub > Add token
93
- 3. Select repository and branch
94
- 4. Enable "Auto Deploy" for webhook-triggered deploys
95
-
96
- ### Domain and SSL
97
-
98
- DNS setup (CNAME to EasyPanel server):
99
- ```
100
- app.example.com CNAME your-server.easypanel.host
101
- api.example.com CNAME your-server.easypanel.host
102
- ```
103
-
104
- SSL via Let's Encrypt is automatic. Force HTTPS enabled by default.
105
-
106
- ## Environment Variables
107
-
108
- ### .NET Backend
109
-
110
- ```env
111
- ASPNETCORE_ENVIRONMENT=Production
112
- ASPNETCORE_URLS=http://+:8080
113
- ConnectionStrings__DefaultConnection=Host=...;Database=...;Username=...;Password=...
114
- Supabase__Url=https://xxx.supabase.co
115
- Supabase__ServiceRoleKey=eyJ...
116
- Supabase__JwtSecret=your-jwt-secret
117
- ```
118
-
119
- ### Next.js Frontend
120
-
121
- ```env
122
- NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
123
- NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
124
- NEXT_PUBLIC_API_URL=https://api.example.com
125
- ```
126
-
127
- ## Health Check Endpoints
128
-
129
- ```csharp
130
- // .NET: Program.cs
131
- builder.Services.AddHealthChecks()
132
- .AddNpgSql(connectionString, name: "database");
133
- app.MapHealthChecks("/health");
134
- ```
135
-
136
- ```ts
137
- // Next.js: app/api/health/route.ts
138
- export async function GET() {
139
- return Response.json({ status: "healthy", timestamp: new Date().toISOString() });
140
- }
141
- ```
142
-
143
- ## Zero-Downtime Deploys
144
-
145
- EasyPanel uses Docker HEALTHCHECK to determine container readiness:
146
-
147
- 1. New container starts alongside old container
148
- 2. Health check passes after start-period + retries
149
- 3. Traffic shifts to new container
150
- 4. Old container stopped
151
-
152
- | HEALTHCHECK Param | Value | Purpose |
153
- |-------------------|-------|---------|
154
- | `--interval` | 30s | Time between checks |
155
- | `--timeout` | 5s | Max response wait |
156
- | `--start-period` | 10s | Startup grace period |
157
- | `--retries` | 3 | Failures before unhealthy |
158
-
159
- ## Monitoring
160
-
161
- - **Logs**: Real-time in EasyPanel UI
162
- - **Metrics**: CPU, memory, network via dashboard
163
- - **Restart**: Auto-restart on crash (default)
164
-
165
- Structured logging:
166
-
167
- ```csharp
168
- // .NET: Serilog with JSON output
169
- builder.Host.UseSerilog((ctx, cfg) => cfg
170
- .ReadFrom.Configuration(ctx.Configuration)
171
- .WriteTo.Console(new JsonFormatter()));
172
- ```
173
-
174
- ```ts
175
- // Next.js: pino
176
- import pino from "pino";
177
- const logger = pino({ level: process.env.LOG_LEVEL ?? "info" });
178
- ```
179
-
180
- ## Deployment Checklist
181
-
182
- | Step | Action |
183
- |------|--------|
184
- | 1 | Verify `output: "standalone"` in next.config.ts |
185
- | 2 | Test Docker build locally |
186
- | 3 | Test health endpoint |
187
- | 4 | Configure env vars in EasyPanel |
188
- | 5 | Set up custom domain + DNS |
189
- | 6 | Verify SSL certificate |
190
- | 7 | Enable auto-deploy from GitHub |
191
- | 8 | Push to main, verify deployment |