@polymorphism-tech/morph-spec 3.2.0 → 4.3.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.
- package/README.md +1 -14
- package/bin/detect-agents.js +1 -1
- package/bin/morph-spec.js +403 -40
- package/bin/validate.js +5 -5
- package/docs/getting-started.md +0 -5
- package/docs/next-generation/AGENTS.md +521 -0
- package/docs/next-generation/ANALYSIS.md +555 -0
- package/docs/next-generation/ARCHITECTURE.md +436 -0
- package/docs/next-generation/CONTEXT-OPTIMIZATION.md +267 -0
- package/docs/next-generation/EXECUTION-FLOW.md +274 -0
- package/docs/next-generation/FEATURES.md +688 -0
- package/docs/next-generation/META-PROMPTS.md +235 -0
- package/docs/next-generation/MIGRATION-GUIDE.md +253 -0
- package/docs/next-generation/README.md +231 -0
- package/docs/next-generation/ROADMAP.md +801 -0
- package/docs/next-generation/THREAD-MANAGEMENT.md +240 -0
- package/docs/validation-checklist.md +0 -1
- package/package.json +5 -5
- package/src/commands/agents/agents-fuse.js +96 -0
- package/src/commands/agents/index.js +4 -0
- package/src/commands/agents/micro-agent.js +112 -0
- package/src/commands/{spawn-team.js → agents/spawn-team.js} +237 -172
- package/src/commands/agents/squad-template.js +146 -0
- package/src/commands/analytics/analytics.js +176 -0
- package/src/commands/context/context-prime.js +63 -0
- package/src/commands/context/core-four.js +54 -0
- package/src/commands/{create-story.js → feature/create-story.js} +357 -354
- package/src/commands/feature/index.js +6 -0
- package/src/commands/{shard-spec.js → feature/shard-spec.js} +2 -2
- package/src/commands/{sprint-status.js → feature/sprint-status.js} +1 -1
- package/src/commands/{generate-context.js → generation/generate-context.js} +40 -40
- package/src/commands/{generate.js → generation/generate.js} +4 -4
- package/src/commands/generation/index.js +5 -0
- package/src/commands/index.js +16 -0
- package/src/commands/{capture-pattern.js → learning/capture-pattern.js} +121 -121
- package/src/commands/learning/index.js +5 -0
- package/src/commands/mcp/mcp.js +102 -0
- package/src/commands/{detect-agents.js → project/detect-agents.js} +178 -178
- package/src/commands/project/detect-workflow.js +174 -0
- package/src/commands/{detect.js → project/detect.js} +104 -104
- package/src/commands/{doctor.js → project/doctor.js} +221 -4
- package/src/commands/project/index.js +10 -0
- package/src/commands/{init.js → project/init.js} +305 -295
- package/src/commands/{sync.js → project/sync.js} +167 -167
- package/src/commands/{update.js → project/update.js} +240 -240
- package/src/commands/{advance-phase.js → state/advance-phase.js} +101 -25
- package/src/commands/{approve.js → state/approve.js} +221 -221
- package/src/commands/state/index.js +8 -0
- package/src/commands/{rollback-phase.js → state/rollback-phase.js} +185 -185
- package/src/commands/{state.js → state/state.js} +334 -334
- package/src/commands/{validate-phase.js → state/validate-phase.js} +221 -221
- package/src/commands/tasks/index.js +4 -0
- package/src/commands/{task.js → tasks/task.js} +78 -78
- package/src/commands/templates/index.js +8 -0
- package/src/commands/templates/template-customize.js +101 -0
- package/src/commands/templates/template-list.js +128 -0
- package/src/commands/templates/template-render.js +174 -0
- package/src/commands/templates/template-show.js +131 -0
- package/src/commands/templates/template-validate.js +91 -0
- package/src/commands/threads/thread-template.js +103 -0
- package/src/commands/threads/threads.js +261 -0
- package/src/commands/trust/trust.js +205 -0
- package/src/commands/utils/index.js +7 -0
- package/src/commands/{session-summary.js → utils/session-summary.js} +291 -291
- package/src/commands/{troubleshoot.js → utils/troubleshoot.js} +222 -222
- package/src/commands/{analyze-blazor-concurrency.js → validation/analyze-blazor-concurrency.js} +193 -193
- package/src/commands/validation/index.js +8 -0
- package/src/commands/{lint-fluent.js → validation/lint-fluent.js} +352 -352
- package/src/commands/{validate-blazor-state.js → validation/validate-blazor-state.js} +210 -210
- package/src/commands/{validate-blazor.js → validation/validate-blazor.js} +156 -156
- package/src/commands/{validate-css.js → validation/validate-css.js} +84 -84
- package/src/core/index.js +10 -0
- package/src/{orchestrator.js → core/orchestrator.js} +8 -8
- package/src/core/registry/command-registry.js +302 -0
- package/src/core/registry/index.js +8 -0
- package/src/core/registry/validator-registry.js +204 -0
- package/src/core/state/index.js +8 -0
- package/src/{lib → core/state}/phase-state-machine.js +214 -214
- package/src/{lib → core/state}/state-manager.js +588 -534
- package/src/core/templates/index.js +9 -0
- package/src/core/templates/template-registry.js +335 -0
- package/src/core/templates/template-renderer.js +477 -0
- package/src/core/templates/template-validator.js +296 -0
- package/src/core/workflows/index.js +7 -0
- package/src/core/workflows/workflow-detector.js +452 -0
- package/src/lib/agents/micro-agent-factory.js +161 -0
- package/src/lib/{complexity-analyzer.js → analysis/complexity-analyzer.js} +441 -441
- package/src/lib/analysis/index.js +7 -0
- package/src/lib/analytics/analytics-engine.js +345 -0
- package/src/lib/{checkpoint-hooks.js → checkpoints/checkpoint-hooks.js} +35 -0
- package/src/lib/checkpoints/index.js +7 -0
- package/src/lib/context/context-bundler.js +240 -0
- package/src/lib/context/context-optimizer.js +212 -0
- package/src/lib/context/context-tracker.js +273 -0
- package/src/lib/context/core-four-tracker.js +201 -0
- package/src/lib/context/mcp-optimizer.js +200 -0
- package/src/lib/detectors/config-detector.js +223 -223
- package/src/lib/detectors/conversation-analyzer.js +163 -163
- package/src/lib/{design-system-detector.js → detectors/design-system-detector.js} +187 -187
- package/src/lib/detectors/index.js +87 -84
- package/src/lib/detectors/standards-generator.js +275 -275
- package/src/lib/detectors/structure-detector.js +245 -245
- package/src/lib/execution/fusion-executor.js +304 -0
- package/src/lib/execution/parallel-executor.js +270 -0
- package/src/lib/{context-generator.js → generators/context-generator.js} +526 -516
- package/src/lib/generators/index.js +10 -0
- package/src/lib/{metadata-extractor.js → generators/metadata-extractor.js} +387 -380
- package/src/lib/{recap-generator.js → generators/recap-generator.js} +205 -205
- package/src/lib/hooks/hook-executor.js +169 -0
- package/src/lib/hooks/stop-hook-executor.js +286 -0
- package/src/lib/hops/hop-composer.js +221 -0
- package/src/lib/learning/index.js +7 -0
- package/src/lib/orchestration/index.js +7 -0
- package/src/lib/{team-orchestrator.js → orchestration/team-orchestrator.js} +323 -323
- package/src/lib/stacks/index.js +7 -0
- package/src/lib/{stack-resolver.js → stacks/stack-resolver.js} +180 -148
- package/src/lib/standards/index.js +7 -0
- package/src/lib/{standards-context-injector.js → standards/standards-context-injector.js} +298 -288
- package/src/lib/threads/thread-coordinator.js +238 -0
- package/src/lib/threads/thread-manager.js +317 -0
- package/src/lib/tracking/artifact-trail.js +202 -0
- package/src/lib/troubleshooting/index.js +8 -0
- package/src/lib/{troubleshoot-grep.js → troubleshooting/troubleshoot-grep.js} +204 -204
- package/src/lib/{troubleshoot-index.js → troubleshooting/troubleshoot-index.js} +144 -144
- package/src/lib/trust/trust-manager.js +269 -0
- package/src/lib/validators/{architecture-validator.js → architecture/architecture-validator.js} +8 -8
- package/src/lib/validators/architecture/index.js +7 -0
- package/src/lib/{blazor-concurrency-analyzer.js → validators/blazor/blazor-concurrency-analyzer.js} +277 -288
- package/src/lib/{blazor-state-validator.js → validators/blazor/blazor-state-validator.js} +279 -291
- package/src/lib/{blazor-validator.js → validators/blazor/blazor-validator.js} +369 -374
- package/src/lib/validators/blazor/index.js +9 -0
- package/src/lib/validators/{content-validator.js → content/content-validator.js} +351 -351
- package/src/lib/validators/content/index.js +7 -0
- package/src/lib/validators/{contract-compliance-validator.js → contracts/contract-compliance-validator.js} +273 -273
- package/src/lib/validators/contracts/index.js +7 -0
- package/src/lib/{css-validator.js → validators/css/css-validator.js} +352 -352
- package/src/lib/validators/css/index.js +7 -0
- package/src/lib/validators/{design-system-validator.js → design-system/design-system-validator.js} +231 -231
- package/src/lib/validators/design-system/index.js +7 -0
- package/src/lib/validators/packages/index.js +7 -0
- package/src/lib/validators/shared/index.js +12 -0
- package/src/lib/validators/shared/issue-counter.js +18 -0
- package/src/lib/validators/shared/result-formatter.js +124 -0
- package/src/lib/{spec-validator.js → validators/spec-validator.js} +258 -258
- package/src/lib/validators/ui/index.js +7 -0
- package/src/lib/{validation-runner.js → validators/validation-runner.js} +286 -284
- package/src/ui/wizard-questions.js +0 -2
- package/src/utils/color-utils.js +70 -0
- package/src/utils/file-copier.js +188 -189
- package/src/utils/process-handler.js +97 -0
- package/stacks/blazor-azure/.morph/config/agents.json +948 -764
- package/stacks/blazor-azure/.morph/hooks/{pre-commit-tests.sh → pre-commit/tests-csharp.sh} +3 -2
- package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/cd-prod.yml.hbs +41 -0
- package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/cd-staging.yml.hbs +24 -0
- package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/ci-build.yml.hbs +23 -0
- package/stacks/nextjs-supabase/.morph/config/agents.json +345 -345
- package/stacks/nextjs-supabase/.morph/hooks/pre-commit/tests-typescript.sh +61 -0
- package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/cd-prod.yml.hbs +22 -0
- package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/cd-staging.yml.hbs +22 -0
- package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/ci-build.yml.hbs +35 -0
- package/stacks/nextjs-supabase/README.md +6 -15
- package/CLAUDE.md +0 -648
- package/bin/render-template.js +0 -349
- package/bin/semantic-detect-agents.js +0 -247
- package/bin/validate-agents-skills.js +0 -257
- package/bin/validate-agents.js +0 -70
- package/bin/validate-phase.js +0 -263
- package/docs/examples.md +0 -328
- package/docs/llm-interaction-config.md +0 -735
- package/scripts/reorganize-skills.cjs +0 -175
- package/scripts/validate-agents-structure.cjs +0 -52
- package/scripts/validate-skills.cjs +0 -180
- package/src/commands/deploy.js +0 -780
- package/src/commands/migrate-state.js +0 -158
- package/src/commands/upgrade.js +0 -346
- package/src/lib/continuous-validator.js +0 -421
- package/src/lib/decision-constraint-loader.js +0 -109
- package/src/lib/design-system-scaffolder.js +0 -299
- package/src/lib/hook-executor.js +0 -257
- package/src/lib/mockup-generator.js +0 -366
- package/src/lib/ui-detector.js +0 -350
- package/src/llm/schema-validator.js +0 -121
- package/src/sanitizer/.gitkeep +0 -0
- package/src/scanner/.gitkeep +0 -0
- package/src/types/index.js +0 -477
- package/src/ui/.gitkeep +0 -0
- package/src/writer/.gitkeep +0 -0
- package/stacks/blazor-azure/.azure/README.md +0 -293
- package/stacks/blazor-azure/.azure/docs/azure-devops-setup.md +0 -454
- package/stacks/blazor-azure/.azure/docs/branch-strategy.md +0 -398
- package/stacks/blazor-azure/.azure/docs/local-development.md +0 -515
- package/stacks/blazor-azure/.azure/pipelines/pipeline-variables.yml +0 -34
- package/stacks/blazor-azure/.azure/pipelines/prod-pipeline.yml +0 -319
- package/stacks/blazor-azure/.azure/pipelines/staging-pipeline.yml +0 -234
- package/stacks/blazor-azure/.azure/pipelines/templates/build-dotnet.yml +0 -75
- package/stacks/blazor-azure/.azure/pipelines/templates/deploy-app-service.yml +0 -94
- package/stacks/blazor-azure/.azure/pipelines/templates/deploy-container-app.yml +0 -120
- package/stacks/blazor-azure/.azure/pipelines/templates/infra-deploy.yml +0 -90
- package/stacks/blazor-azure/.claude/commands/morph-apply.md +0 -221
- package/stacks/blazor-azure/.claude/commands/morph-archive.md +0 -79
- package/stacks/blazor-azure/.claude/commands/morph-deploy.md +0 -529
- package/stacks/blazor-azure/.claude/commands/morph-infra.md +0 -209
- package/stacks/blazor-azure/.claude/commands/morph-preflight.md +0 -227
- package/stacks/blazor-azure/.claude/commands/morph-proposal.md +0 -122
- package/stacks/blazor-azure/.claude/commands/morph-status.md +0 -86
- package/stacks/blazor-azure/.claude/commands/morph-troubleshoot.md +0 -122
- package/stacks/blazor-azure/.claude/settings.local.json +0 -15
- package/stacks/blazor-azure/.claude/skills/level-0-meta/README.md +0 -7
- package/stacks/blazor-azure/.claude/skills/level-0-meta/code-review.md +0 -226
- package/stacks/blazor-azure/.claude/skills/level-0-meta/morph-checklist.md +0 -117
- package/stacks/blazor-azure/.claude/skills/level-0-meta/simulation-checklist.md +0 -77
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/README.md +0 -7
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/morph-replicate.md +0 -213
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-clarify.md +0 -131
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-design.md +0 -213
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-setup.md +0 -106
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-tasks.md +0 -164
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-uiux.md +0 -169
- package/stacks/blazor-azure/.claude/skills/level-2-domains/README.md +0 -14
- package/stacks/blazor-azure/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +0 -192
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/po-pm-advisor.md +0 -197
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/prompt-engineer.md +0 -189
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/seo-growth-hacker.md +0 -320
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/standards-architect.md +0 -156
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/dotnet-senior.md +0 -287
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ef-modeler.md +0 -113
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +0 -126
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ms-agent-expert.md +0 -109
- package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/blazor-builder.md +0 -210
- package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/nextjs-expert.md +0 -154
- package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +0 -191
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-architect.md +0 -142
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +0 -699
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +0 -126
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/container-specialist.md +0 -131
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +0 -119
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/asaas-financial.md +0 -130
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/azure-identity.md +0 -142
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/clerk-auth.md +0 -108
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/resend-email.md +0 -119
- package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/code-analyzer.md +0 -235
- package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/testing-specialist.md +0 -126
- package/stacks/blazor-azure/.claude/skills/level-3-technologies/README.md +0 -7
- package/stacks/blazor-azure/.claude/skills/level-4-patterns/README.md +0 -7
- package/stacks/blazor-azure/.morph/archive/.gitkeep +0 -25
- package/stacks/blazor-azure/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +0 -392
- package/stacks/blazor-azure/.morph/docs/workflows/design-impl.md +0 -37
- package/stacks/blazor-azure/.morph/docs/workflows/enforcement-pipeline.md +0 -668
- package/stacks/blazor-azure/.morph/docs/workflows/fast-track.md +0 -29
- package/stacks/blazor-azure/.morph/docs/workflows/full-morph.md +0 -76
- package/stacks/blazor-azure/.morph/docs/workflows/standard.md +0 -44
- package/stacks/blazor-azure/.morph/docs/workflows/ui-refresh.md +0 -39
- package/stacks/blazor-azure/.morph/examples/api-nextjs/README.md +0 -241
- package/stacks/blazor-azure/.morph/examples/api-nextjs/contracts.ts +0 -307
- package/stacks/blazor-azure/.morph/examples/api-nextjs/spec.md +0 -399
- package/stacks/blazor-azure/.morph/examples/api-nextjs/tasks.md +0 -168
- package/stacks/blazor-azure/.morph/examples/micro-saas/README.md +0 -125
- package/stacks/blazor-azure/.morph/examples/micro-saas/contracts.cs +0 -358
- package/stacks/blazor-azure/.morph/examples/micro-saas/decisions.md +0 -246
- package/stacks/blazor-azure/.morph/examples/micro-saas/spec.md +0 -236
- package/stacks/blazor-azure/.morph/examples/micro-saas/tasks.md +0 -150
- package/stacks/blazor-azure/.morph/examples/multi-agent/README.md +0 -309
- package/stacks/blazor-azure/.morph/examples/multi-agent/contracts.cs +0 -433
- package/stacks/blazor-azure/.morph/examples/multi-agent/spec.md +0 -479
- package/stacks/blazor-azure/.morph/examples/multi-agent/tasks.md +0 -185
- package/stacks/blazor-azure/.morph/examples/scheduled-reports/decisions.md +0 -158
- package/stacks/blazor-azure/.morph/examples/scheduled-reports/proposal.md +0 -95
- package/stacks/blazor-azure/.morph/examples/scheduled-reports/spec.md +0 -267
- package/stacks/blazor-azure/.morph/examples/state-v3.json +0 -188
- package/stacks/blazor-azure/.morph/features/.gitkeep +0 -25
- package/stacks/blazor-azure/.morph/hooks/README.md +0 -348
- package/stacks/blazor-azure/.morph/hooks/pre-commit-agents.sh +0 -24
- package/stacks/blazor-azure/.morph/hooks/pre-commit-all.sh +0 -48
- package/stacks/blazor-azure/.morph/hooks/pre-commit-specs.sh +0 -49
- package/stacks/blazor-azure/.morph/hooks/task-completed.js +0 -73
- package/stacks/blazor-azure/.morph/hooks/teammate-idle.js +0 -68
- package/stacks/blazor-azure/.morph/schemas/agent.schema.json +0 -296
- package/stacks/blazor-azure/.morph/schemas/tasks.schema.json +0 -220
- package/stacks/blazor-azure/.morph/specs/.gitkeep +0 -20
- package/stacks/blazor-azure/.morph/standards/agent-framework-blazor-ui.md +0 -359
- package/stacks/blazor-azure/.morph/standards/agent-framework-production.md +0 -410
- package/stacks/blazor-azure/.morph/standards/agent-framework-setup.md +0 -413
- package/stacks/blazor-azure/.morph/standards/agent-framework-workflows.md +0 -349
- package/stacks/blazor-azure/.morph/standards/agent-teams-workflow.md +0 -474
- package/stacks/blazor-azure/.morph/standards/architecture.md +0 -325
- package/stacks/blazor-azure/.morph/standards/azure.md +0 -605
- package/stacks/blazor-azure/.morph/standards/coding.md +0 -377
- package/stacks/blazor-azure/.morph/standards/dotnet10-migration.md +0 -520
- package/stacks/blazor-azure/.morph/standards/fluent-ui-setup.md +0 -590
- package/stacks/blazor-azure/.morph/standards/migration-guide.md +0 -514
- package/stacks/blazor-azure/.morph/standards/passkeys-auth.md +0 -423
- package/stacks/blazor-azure/.morph/standards/vector-search-rag.md +0 -536
- package/stacks/blazor-azure/.morph/templates/CONTEXT-FEATURE.md +0 -276
- package/stacks/blazor-azure/.morph/templates/CONTEXT.md +0 -170
- package/stacks/blazor-azure/.morph/templates/FluentDesignTheme.cs +0 -149
- package/stacks/blazor-azure/.morph/templates/MudTheme.cs +0 -281
- package/stacks/blazor-azure/.morph/templates/agent.cs +0 -163
- package/stacks/blazor-azure/.morph/templates/clarify-questions.md +0 -159
- package/stacks/blazor-azure/.morph/templates/component.razor +0 -239
- package/stacks/blazor-azure/.morph/templates/contracts/Commands.cs +0 -74
- package/stacks/blazor-azure/.morph/templates/contracts/Entities.cs +0 -25
- package/stacks/blazor-azure/.morph/templates/contracts/Queries.cs +0 -74
- package/stacks/blazor-azure/.morph/templates/contracts/README.md +0 -74
- package/stacks/blazor-azure/.morph/templates/contracts.cs +0 -217
- package/stacks/blazor-azure/.morph/templates/decisions.md +0 -123
- package/stacks/blazor-azure/.morph/templates/design-system.css +0 -226
- package/stacks/blazor-azure/.morph/templates/infra/.dockerignore.example +0 -89
- package/stacks/blazor-azure/.morph/templates/infra/Dockerfile.example +0 -82
- package/stacks/blazor-azure/.morph/templates/infra/README.md +0 -286
- package/stacks/blazor-azure/.morph/templates/infra/app-insights.bicep +0 -63
- package/stacks/blazor-azure/.morph/templates/infra/app-service.bicep +0 -164
- package/stacks/blazor-azure/.morph/templates/infra/azure-pipelines-deploy.yml +0 -480
- package/stacks/blazor-azure/.morph/templates/infra/container-app-env.bicep +0 -49
- package/stacks/blazor-azure/.morph/templates/infra/container-app.bicep +0 -156
- package/stacks/blazor-azure/.morph/templates/infra/deploy-checklist.md +0 -426
- package/stacks/blazor-azure/.morph/templates/infra/deploy.ps1 +0 -229
- package/stacks/blazor-azure/.morph/templates/infra/deploy.sh +0 -208
- package/stacks/blazor-azure/.morph/templates/infra/key-vault.bicep +0 -91
- package/stacks/blazor-azure/.morph/templates/infra/main.bicep +0 -189
- package/stacks/blazor-azure/.morph/templates/infra/parameters.dev.json +0 -29
- package/stacks/blazor-azure/.morph/templates/infra/parameters.prod.json +0 -29
- package/stacks/blazor-azure/.morph/templates/infra/parameters.staging.json +0 -29
- package/stacks/blazor-azure/.morph/templates/infra/sql-database.bicep +0 -103
- package/stacks/blazor-azure/.morph/templates/infra/storage.bicep +0 -106
- package/stacks/blazor-azure/.morph/templates/integrations/asaas-client.cs +0 -387
- package/stacks/blazor-azure/.morph/templates/integrations/asaas-webhook.cs +0 -351
- package/stacks/blazor-azure/.morph/templates/integrations/azure-identity-config.cs +0 -288
- package/stacks/blazor-azure/.morph/templates/integrations/clerk-config.cs +0 -258
- package/stacks/blazor-azure/.morph/templates/job.cs +0 -171
- package/stacks/blazor-azure/.morph/templates/migration.cs +0 -83
- package/stacks/blazor-azure/.morph/templates/proposal.md +0 -141
- package/stacks/blazor-azure/.morph/templates/recap.md +0 -94
- package/stacks/blazor-azure/.morph/templates/repository.cs +0 -141
- package/stacks/blazor-azure/.morph/templates/saas/subscription.cs +0 -347
- package/stacks/blazor-azure/.morph/templates/saas/tenant.cs +0 -338
- package/stacks/blazor-azure/.morph/templates/service.cs +0 -139
- package/stacks/blazor-azure/.morph/templates/simulation.md +0 -353
- package/stacks/blazor-azure/.morph/templates/spec.md +0 -149
- package/stacks/blazor-azure/.morph/templates/sprint-status.yaml +0 -68
- package/stacks/blazor-azure/.morph/templates/state.template.json +0 -222
- package/stacks/blazor-azure/.morph/templates/story.md +0 -143
- package/stacks/blazor-azure/.morph/templates/tasks.md +0 -257
- package/stacks/blazor-azure/.morph/templates/test.cs +0 -239
- package/stacks/blazor-azure/.morph/templates/ui-components.md +0 -362
- package/stacks/blazor-azure/.morph/templates/ui-design-system.md +0 -286
- package/stacks/blazor-azure/.morph/templates/ui-flows.md +0 -336
- package/stacks/blazor-azure/.morph/templates/ui-mockups.md +0 -133
- package/stacks/blazor-azure/.morph/test-infra/example.bicep +0 -59
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/backend/dotnet-supabase.md +0 -244
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/frontend/nextjs-supabase.md +0 -335
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/infrastructure/easypanel-deployer.md +0 -189
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +0 -170
- package/stacks/nextjs-supabase/.morph/docs/easypanel-setup.md +0 -169
- package/stacks/nextjs-supabase/.morph/docs/supabase-mcp-setup.md +0 -247
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/README.md +0 -697
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/spec.md +0 -85
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/tasks.md +0 -86
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/README.md +0 -498
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/decisions.md +0 -121
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/spec.md +0 -138
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/tasks.md +0 -162
- package/stacks/nextjs-supabase/.morph/standards/easypanel-deploy.md +0 -191
- package/stacks/nextjs-supabase/.morph/standards/nextjs-patterns.md +0 -193
- package/stacks/nextjs-supabase/.morph/standards/supabase-auth.md +0 -171
- package/stacks/nextjs-supabase/.morph/standards/supabase-pgvector.md +0 -164
- package/stacks/nextjs-supabase/.morph/standards/supabase-rls.md +0 -179
- package/stacks/nextjs-supabase/.morph/standards/supabase-storage.md +0 -148
- package/stacks/nextjs-supabase/.morph/templates/contracts.cs +0 -173
- package/stacks/nextjs-supabase/.morph/templates/contracts.ts +0 -168
- package/stacks/nextjs-supabase/.morph/templates/decisions.md +0 -115
- package/stacks/nextjs-supabase/.morph/templates/dockerfile-api.dockerfile +0 -38
- package/stacks/nextjs-supabase/.morph/templates/dockerfile-web.dockerfile +0 -48
- package/stacks/nextjs-supabase/.morph/templates/proposal.md +0 -145
- package/stacks/nextjs-supabase/.morph/templates/recap.md +0 -134
- package/stacks/nextjs-supabase/.morph/templates/rls-policy.sql +0 -57
- package/stacks/nextjs-supabase/.morph/templates/spec.md +0 -231
- package/stacks/nextjs-supabase/.morph/templates/supabase-migration.sql +0 -100
- package/stacks/nextjs-supabase/.morph/templates/tasks.md +0 -257
- /package/src/commands/{search-patterns.js → learning/search-patterns.js} +0 -0
- /package/src/{lib → core/templates}/template-data-sources.js +0 -0
- /package/src/lib/{design-system-generator.js → generators/design-system-generator.js} +0 -0
- /package/src/lib/{learning-system.js → learning/learning-system.js} +0 -0
- /package/src/lib/validators/{package-validator.js → packages/package-validator.js} +0 -0
- /package/src/lib/validators/{ui-contrast-validator.js → ui/ui-contrast-validator.js} +0 -0
- /package/{src/generator → stacks/blazor-azure/.morph/templates}/.gitkeep +0 -0
- /package/{src/llm → stacks/nextjs-supabase/.morph/templates}/.gitkeep +0 -0
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
# Next.js + Supabase Frontend
|
|
2
|
-
|
|
3
|
-
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** nextjs, supabase, ssr, auth, react-query, shadcn, tailwind, middleware
|
|
4
|
-
|
|
5
|
-
## Identity
|
|
6
|
-
|
|
7
|
-
Frontend specialist for Next.js App Router with Supabase. Implements @supabase/ssr for server and browser clients, auth middleware for route protection, React Query for data fetching with Supabase, shadcn/ui components with Tailwind CSS, and Realtime subscriptions.
|
|
8
|
-
|
|
9
|
-
## Domains
|
|
10
|
-
|
|
11
|
-
- auth-ui
|
|
12
|
-
- data-fetching
|
|
13
|
-
- realtime
|
|
14
|
-
- components
|
|
15
|
-
|
|
16
|
-
## Standards
|
|
17
|
-
|
|
18
|
-
- css-naming.md -- Tailwind utility class ordering conventions
|
|
19
|
-
- architecture.md -- Server vs Client component boundaries
|
|
20
|
-
|
|
21
|
-
## Patterns
|
|
22
|
-
|
|
23
|
-
### @supabase/ssr Client Setup
|
|
24
|
-
|
|
25
|
-
```typescript
|
|
26
|
-
// lib/supabase/client.ts (Browser client)
|
|
27
|
-
import { createBrowserClient } from "@supabase/ssr";
|
|
28
|
-
import type { Database } from "@/types/database";
|
|
29
|
-
|
|
30
|
-
export function createClient() {
|
|
31
|
-
return createBrowserClient<Database>(
|
|
32
|
-
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
33
|
-
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
// lib/supabase/server.ts (Server client)
|
|
40
|
-
import { createServerClient } from "@supabase/ssr";
|
|
41
|
-
import { cookies } from "next/headers";
|
|
42
|
-
import type { Database } from "@/types/database";
|
|
43
|
-
|
|
44
|
-
export async function createServerSupabaseClient() {
|
|
45
|
-
const cookieStore = await cookies();
|
|
46
|
-
|
|
47
|
-
return createServerClient<Database>(
|
|
48
|
-
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
49
|
-
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
50
|
-
{
|
|
51
|
-
cookies: {
|
|
52
|
-
getAll() {
|
|
53
|
-
return cookieStore.getAll();
|
|
54
|
-
},
|
|
55
|
-
setAll(cookiesToSet) {
|
|
56
|
-
try {
|
|
57
|
-
cookiesToSet.forEach(({ name, value, options }) =>
|
|
58
|
-
cookieStore.set(name, value, options)
|
|
59
|
-
);
|
|
60
|
-
} catch {
|
|
61
|
-
// The `setAll` method is called from a Server Component
|
|
62
|
-
// if middleware refreshes the session. Ignore in that context.
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
}
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Auth Middleware
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
// middleware.ts
|
|
75
|
-
import { createServerClient } from "@supabase/ssr";
|
|
76
|
-
import { NextResponse, type NextRequest } from "next/server";
|
|
77
|
-
|
|
78
|
-
const publicRoutes = ["/", "/login", "/signup", "/auth/callback"];
|
|
79
|
-
|
|
80
|
-
export async function middleware(request: NextRequest) {
|
|
81
|
-
let response = NextResponse.next({ request });
|
|
82
|
-
|
|
83
|
-
const supabase = createServerClient(
|
|
84
|
-
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
85
|
-
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
86
|
-
{
|
|
87
|
-
cookies: {
|
|
88
|
-
getAll() {
|
|
89
|
-
return request.cookies.getAll();
|
|
90
|
-
},
|
|
91
|
-
setAll(cookiesToSet) {
|
|
92
|
-
cookiesToSet.forEach(({ name, value }) =>
|
|
93
|
-
request.cookies.set(name, value)
|
|
94
|
-
);
|
|
95
|
-
response = NextResponse.next({ request });
|
|
96
|
-
cookiesToSet.forEach(({ name, value, options }) =>
|
|
97
|
-
response.cookies.set(name, value, options)
|
|
98
|
-
);
|
|
99
|
-
},
|
|
100
|
-
},
|
|
101
|
-
}
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
const {
|
|
105
|
-
data: { user },
|
|
106
|
-
} = await supabase.auth.getUser();
|
|
107
|
-
|
|
108
|
-
const isPublicRoute = publicRoutes.some((route) =>
|
|
109
|
-
request.nextUrl.pathname.startsWith(route)
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
if (!user && !isPublicRoute) {
|
|
113
|
-
const url = request.nextUrl.clone();
|
|
114
|
-
url.pathname = "/login";
|
|
115
|
-
url.searchParams.set("redirectTo", request.nextUrl.pathname);
|
|
116
|
-
return NextResponse.redirect(url);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return response;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export const config = {
|
|
123
|
-
matcher: ["/((?!_next/static|_next/image|favicon.ico|api/health).*)"],
|
|
124
|
-
};
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### Auth Callback Route
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
// app/auth/callback/route.ts
|
|
131
|
-
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
|
132
|
-
import { NextResponse } from "next/server";
|
|
133
|
-
|
|
134
|
-
export async function GET(request: Request) {
|
|
135
|
-
const { searchParams, origin } = new URL(request.url);
|
|
136
|
-
const code = searchParams.get("code");
|
|
137
|
-
const next = searchParams.get("next") ?? "/dashboard";
|
|
138
|
-
|
|
139
|
-
if (code) {
|
|
140
|
-
const supabase = await createServerSupabaseClient();
|
|
141
|
-
const { error } = await supabase.auth.exchangeCodeForSession(code);
|
|
142
|
-
if (!error) {
|
|
143
|
-
return NextResponse.redirect(`${origin}${next}`);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return NextResponse.redirect(`${origin}/login?error=auth_failed`);
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### React Query + Supabase
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
// hooks/use-documents.ts
|
|
155
|
-
"use client";
|
|
156
|
-
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
157
|
-
import { createClient } from "@/lib/supabase/client";
|
|
158
|
-
import type { Document, CreateDocumentInput } from "@/types/database";
|
|
159
|
-
|
|
160
|
-
const supabase = createClient();
|
|
161
|
-
|
|
162
|
-
export function useDocuments(page = 1, pageSize = 10) {
|
|
163
|
-
return useQuery({
|
|
164
|
-
queryKey: ["documents", page, pageSize],
|
|
165
|
-
queryFn: async () => {
|
|
166
|
-
const from = (page - 1) * pageSize;
|
|
167
|
-
const to = from + pageSize - 1;
|
|
168
|
-
|
|
169
|
-
const { data, error, count } = await supabase
|
|
170
|
-
.from("documents")
|
|
171
|
-
.select("*", { count: "exact" })
|
|
172
|
-
.order("created_at", { ascending: false })
|
|
173
|
-
.range(from, to);
|
|
174
|
-
|
|
175
|
-
if (error) throw error;
|
|
176
|
-
return { items: data as Document[], totalCount: count ?? 0, page, pageSize };
|
|
177
|
-
},
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export function useCreateDocument() {
|
|
182
|
-
const queryClient = useQueryClient();
|
|
183
|
-
|
|
184
|
-
return useMutation({
|
|
185
|
-
mutationFn: async (input: CreateDocumentInput) => {
|
|
186
|
-
const { data, error } = await supabase
|
|
187
|
-
.from("documents")
|
|
188
|
-
.insert(input)
|
|
189
|
-
.select()
|
|
190
|
-
.single();
|
|
191
|
-
|
|
192
|
-
if (error) throw error;
|
|
193
|
-
return data as Document;
|
|
194
|
-
},
|
|
195
|
-
onSuccess: () => {
|
|
196
|
-
queryClient.invalidateQueries({ queryKey: ["documents"] });
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### Form with react-hook-form + zod
|
|
203
|
-
|
|
204
|
-
```typescript
|
|
205
|
-
// components/document-form.tsx
|
|
206
|
-
"use client";
|
|
207
|
-
import { useForm } from "react-hook-form";
|
|
208
|
-
import { zodResolver } from "@hookform/resolvers/zod";
|
|
209
|
-
import { z } from "zod";
|
|
210
|
-
import { Button } from "@/components/ui/button";
|
|
211
|
-
import { Input } from "@/components/ui/input";
|
|
212
|
-
import { Textarea } from "@/components/ui/textarea";
|
|
213
|
-
import { useCreateDocument } from "@/hooks/use-documents";
|
|
214
|
-
|
|
215
|
-
const schema = z.object({
|
|
216
|
-
title: z.string().min(1, "Title is required").max(200),
|
|
217
|
-
content: z.string().min(1, "Content is required"),
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
type FormData = z.infer<typeof schema>;
|
|
221
|
-
|
|
222
|
-
export function DocumentForm({ onSuccess }: { onSuccess?: () => void }) {
|
|
223
|
-
const { register, handleSubmit, formState: { errors }, reset } = useForm<FormData>({
|
|
224
|
-
resolver: zodResolver(schema),
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
const createDocument = useCreateDocument();
|
|
228
|
-
|
|
229
|
-
const onSubmit = async (data: FormData) => {
|
|
230
|
-
await createDocument.mutateAsync(data);
|
|
231
|
-
reset();
|
|
232
|
-
onSuccess?.();
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
return (
|
|
236
|
-
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
|
237
|
-
<div>
|
|
238
|
-
<Input placeholder="Document title" {...register("title")} />
|
|
239
|
-
{errors.title && <p className="text-sm text-destructive mt-1">{errors.title.message}</p>}
|
|
240
|
-
</div>
|
|
241
|
-
<div>
|
|
242
|
-
<Textarea placeholder="Content..." rows={6} {...register("content")} />
|
|
243
|
-
{errors.content && <p className="text-sm text-destructive mt-1">{errors.content.message}</p>}
|
|
244
|
-
</div>
|
|
245
|
-
<Button type="submit" disabled={createDocument.isPending}>
|
|
246
|
-
{createDocument.isPending ? "Creating..." : "Create Document"}
|
|
247
|
-
</Button>
|
|
248
|
-
</form>
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
### Realtime Subscription Hook
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
// hooks/use-realtime.ts
|
|
257
|
-
"use client";
|
|
258
|
-
import { useEffect } from "react";
|
|
259
|
-
import { useQueryClient } from "@tanstack/react-query";
|
|
260
|
-
import { createClient } from "@/lib/supabase/client";
|
|
261
|
-
import type { RealtimePostgresChangesPayload } from "@supabase/supabase-js";
|
|
262
|
-
|
|
263
|
-
export function useRealtimeSubscription<T extends Record<string, unknown>>(
|
|
264
|
-
table: string,
|
|
265
|
-
queryKey: string[]
|
|
266
|
-
) {
|
|
267
|
-
const queryClient = useQueryClient();
|
|
268
|
-
const supabase = createClient();
|
|
269
|
-
|
|
270
|
-
useEffect(() => {
|
|
271
|
-
const channel = supabase
|
|
272
|
-
.channel(`${table}-changes`)
|
|
273
|
-
.on<T>(
|
|
274
|
-
"postgres_changes",
|
|
275
|
-
{ event: "*", schema: "public", table },
|
|
276
|
-
(payload: RealtimePostgresChangesPayload<T>) => {
|
|
277
|
-
queryClient.invalidateQueries({ queryKey });
|
|
278
|
-
}
|
|
279
|
-
)
|
|
280
|
-
.subscribe();
|
|
281
|
-
|
|
282
|
-
return () => {
|
|
283
|
-
supabase.removeChannel(channel);
|
|
284
|
-
};
|
|
285
|
-
}, [table, queryKey, queryClient, supabase]);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Usage in component:
|
|
289
|
-
// useRealtimeSubscription<Document>("documents", ["documents"]);
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Server Component Data Fetching
|
|
293
|
-
|
|
294
|
-
```typescript
|
|
295
|
-
// app/dashboard/page.tsx
|
|
296
|
-
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
|
297
|
-
import { DocumentList } from "@/components/document-list";
|
|
298
|
-
|
|
299
|
-
export default async function DashboardPage() {
|
|
300
|
-
const supabase = await createServerSupabaseClient();
|
|
301
|
-
const { data: user } = await supabase.auth.getUser();
|
|
302
|
-
|
|
303
|
-
const { data: documents } = await supabase
|
|
304
|
-
.from("documents")
|
|
305
|
-
.select("*")
|
|
306
|
-
.order("created_at", { ascending: false })
|
|
307
|
-
.limit(20);
|
|
308
|
-
|
|
309
|
-
return (
|
|
310
|
-
<main className="container mx-auto py-8">
|
|
311
|
-
<h1 className="text-2xl font-bold mb-6">
|
|
312
|
-
Welcome, {user.user?.email}
|
|
313
|
-
</h1>
|
|
314
|
-
<DocumentList initialDocuments={documents ?? []} />
|
|
315
|
-
</main>
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
## Checklist
|
|
321
|
-
|
|
322
|
-
- [ ] @supabase/ssr used (not @supabase/auth-helpers-nextjs)
|
|
323
|
-
- [ ] Server and browser clients in separate files
|
|
324
|
-
- [ ] Middleware refreshes session on every request
|
|
325
|
-
- [ ] Public routes excluded from auth check
|
|
326
|
-
- [ ] Auth callback route handles code exchange
|
|
327
|
-
- [ ] React Query configured with QueryClientProvider
|
|
328
|
-
- [ ] Forms validated with zod schemas
|
|
329
|
-
- [ ] Realtime subscriptions clean up on unmount
|
|
330
|
-
- [ ] Server Components fetch data directly (no useEffect)
|
|
331
|
-
- [ ] Environment variables: NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY
|
|
332
|
-
|
|
333
|
-
---
|
|
334
|
-
|
|
335
|
-
*MORPH-SPEC by Polymorphism Tech*
|
package/stacks/nextjs-supabase/.claude/skills/level-2-domains/infrastructure/easypanel-deployer.md
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
# EasyPanel Deployer
|
|
2
|
-
|
|
3
|
-
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** easypanel, deploy, docker, ssl, domain, vps, container
|
|
4
|
-
|
|
5
|
-
## Identity
|
|
6
|
-
|
|
7
|
-
Infrastructure and deployment specialist for EasyPanel on VPS. Builds multi-stage Dockerfiles for .NET API and Next.js frontend, configures GitHub integration for auto-deploy, manages SSL certificates, and sets up health check endpoints.
|
|
8
|
-
|
|
9
|
-
## Domains
|
|
10
|
-
|
|
11
|
-
- deployment
|
|
12
|
-
- docker
|
|
13
|
-
- ssl
|
|
14
|
-
- monitoring
|
|
15
|
-
|
|
16
|
-
## Standards
|
|
17
|
-
|
|
18
|
-
- architecture.md -- Layer separation reflected in Docker build stages
|
|
19
|
-
- coding.md -- Health check endpoint patterns
|
|
20
|
-
|
|
21
|
-
## Patterns
|
|
22
|
-
|
|
23
|
-
### Dockerfile Multi-Stage (.NET API)
|
|
24
|
-
|
|
25
|
-
```dockerfile
|
|
26
|
-
# Stage 1: Build
|
|
27
|
-
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
|
28
|
-
WORKDIR /src
|
|
29
|
-
COPY *.csproj .
|
|
30
|
-
RUN dotnet restore
|
|
31
|
-
COPY . .
|
|
32
|
-
RUN dotnet publish -c Release -o /app/publish --no-restore
|
|
33
|
-
|
|
34
|
-
# Stage 2: Runtime
|
|
35
|
-
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
|
|
36
|
-
WORKDIR /app
|
|
37
|
-
COPY --from=build /app/publish .
|
|
38
|
-
ENV ASPNETCORE_URLS=http://+:8080
|
|
39
|
-
ENV ASPNETCORE_ENVIRONMENT=Production
|
|
40
|
-
EXPOSE 8080
|
|
41
|
-
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
42
|
-
CMD curl -f http://localhost:8080/health || exit 1
|
|
43
|
-
ENTRYPOINT ["dotnet", "Api.dll"]
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Dockerfile Multi-Stage (Next.js)
|
|
47
|
-
|
|
48
|
-
```dockerfile
|
|
49
|
-
# Stage 1: Dependencies
|
|
50
|
-
FROM node:22-alpine AS deps
|
|
51
|
-
WORKDIR /app
|
|
52
|
-
COPY package.json package-lock.json ./
|
|
53
|
-
RUN npm ci --omit=dev
|
|
54
|
-
|
|
55
|
-
# Stage 2: Build
|
|
56
|
-
FROM node:22-alpine AS builder
|
|
57
|
-
WORKDIR /app
|
|
58
|
-
COPY --from=deps /app/node_modules ./node_modules
|
|
59
|
-
COPY . .
|
|
60
|
-
ENV NEXT_TELEMETRY_DISABLED=1
|
|
61
|
-
RUN npm run build
|
|
62
|
-
|
|
63
|
-
# Stage 3: Runtime
|
|
64
|
-
FROM node:22-alpine AS runner
|
|
65
|
-
WORKDIR /app
|
|
66
|
-
ENV NODE_ENV=production
|
|
67
|
-
ENV NEXT_TELEMETRY_DISABLED=1
|
|
68
|
-
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs
|
|
69
|
-
COPY --from=builder /app/public ./public
|
|
70
|
-
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
71
|
-
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
72
|
-
USER nextjs
|
|
73
|
-
EXPOSE 3000
|
|
74
|
-
ENV PORT=3000
|
|
75
|
-
ENV HOSTNAME="0.0.0.0"
|
|
76
|
-
CMD ["node", "server.js"]
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### EasyPanel GitHub Integration
|
|
80
|
-
|
|
81
|
-
```yaml
|
|
82
|
-
# EasyPanel service configuration (via UI or API)
|
|
83
|
-
# 1. Connect GitHub repository
|
|
84
|
-
# 2. Configure build settings:
|
|
85
|
-
Service:
|
|
86
|
-
name: my-app-api
|
|
87
|
-
source: github
|
|
88
|
-
repository: org/repo
|
|
89
|
-
branch: main
|
|
90
|
-
dockerfile: ./backend/Dockerfile
|
|
91
|
-
port: 8080
|
|
92
|
-
env:
|
|
93
|
-
- SUPABASE_URL=https://xxx.supabase.co
|
|
94
|
-
- SUPABASE_SERVICE_KEY=${SECRET}
|
|
95
|
-
- ASPNETCORE_ENVIRONMENT=Production
|
|
96
|
-
|
|
97
|
-
# Auto-deploy: triggers on push to configured branch
|
|
98
|
-
# Rollback: EasyPanel keeps previous image for instant rollback
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### SSL Setup
|
|
102
|
-
|
|
103
|
-
```
|
|
104
|
-
# EasyPanel handles SSL automatically via Let's Encrypt
|
|
105
|
-
# Configuration steps:
|
|
106
|
-
# 1. Add custom domain in EasyPanel service settings
|
|
107
|
-
# 2. Point DNS A record to VPS IP
|
|
108
|
-
# 3. EasyPanel auto-provisions SSL certificate
|
|
109
|
-
# 4. Auto-renewal handled by EasyPanel
|
|
110
|
-
|
|
111
|
-
# Force HTTPS redirect (handled by EasyPanel reverse proxy)
|
|
112
|
-
# No application-level SSL configuration needed
|
|
113
|
-
|
|
114
|
-
# Multi-domain setup:
|
|
115
|
-
# - api.myapp.com -> API service (port 8080)
|
|
116
|
-
# - myapp.com -> Web service (port 3000)
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### Health Checks
|
|
120
|
-
|
|
121
|
-
```csharp
|
|
122
|
-
// .NET API health check endpoint
|
|
123
|
-
// Program.cs
|
|
124
|
-
builder.Services.AddHealthChecks()
|
|
125
|
-
.AddNpgSql(connectionString, name: "supabase-db")
|
|
126
|
-
.AddUrlGroup(new Uri($"{supabaseUrl}/rest/v1/"), name: "supabase-api");
|
|
127
|
-
|
|
128
|
-
app.MapHealthChecks("/health", new HealthCheckOptions
|
|
129
|
-
{
|
|
130
|
-
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
app.MapGet("/health/ready", () => Results.Ok(new { status = "ready", timestamp = DateTime.UtcNow }));
|
|
134
|
-
app.MapGet("/health/live", () => Results.Ok(new { status = "alive" }));
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
// Next.js health check (app/api/health/route.ts)
|
|
139
|
-
export async function GET() {
|
|
140
|
-
return Response.json({
|
|
141
|
-
status: "healthy",
|
|
142
|
-
timestamp: new Date().toISOString(),
|
|
143
|
-
version: process.env.npm_package_version ?? "unknown",
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Docker Compose (Local Development)
|
|
149
|
-
|
|
150
|
-
```yaml
|
|
151
|
-
services:
|
|
152
|
-
api:
|
|
153
|
-
build:
|
|
154
|
-
context: ./backend
|
|
155
|
-
dockerfile: Dockerfile
|
|
156
|
-
ports: ["8080:8080"]
|
|
157
|
-
environment:
|
|
158
|
-
- SUPABASE_URL=http://supabase-kong:8000
|
|
159
|
-
- SUPABASE_SERVICE_KEY=${SERVICE_ROLE_KEY}
|
|
160
|
-
- ASPNETCORE_ENVIRONMENT=Development
|
|
161
|
-
depends_on: [supabase-db]
|
|
162
|
-
|
|
163
|
-
web:
|
|
164
|
-
build:
|
|
165
|
-
context: ./frontend
|
|
166
|
-
dockerfile: Dockerfile
|
|
167
|
-
ports: ["3000:3000"]
|
|
168
|
-
environment:
|
|
169
|
-
- NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
|
|
170
|
-
- NEXT_PUBLIC_SUPABASE_ANON_KEY=${ANON_KEY}
|
|
171
|
-
- NEXT_PUBLIC_API_URL=http://localhost:8080
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
## Checklist
|
|
175
|
-
|
|
176
|
-
- [ ] Dockerfiles use multi-stage builds (small final images)
|
|
177
|
-
- [ ] Next.js uses standalone output mode
|
|
178
|
-
- [ ] .dockerignore excludes node_modules, .next, .git, .env*
|
|
179
|
-
- [ ] Health check endpoints configured
|
|
180
|
-
- [ ] Environment variables set in EasyPanel (not hardcoded)
|
|
181
|
-
- [ ] SSL certificates provisioned via EasyPanel
|
|
182
|
-
- [ ] DNS records point to VPS IP
|
|
183
|
-
- [ ] Auto-deploy configured on main branch
|
|
184
|
-
- [ ] Resource limits set (CPU/memory) in EasyPanel
|
|
185
|
-
- [ ] Logs accessible via EasyPanel dashboard
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
*MORPH-SPEC by Polymorphism Tech*
|
package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
# Supabase Expert
|
|
2
|
-
|
|
3
|
-
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** supabase, postgres, rls, auth, storage, realtime, pgvector, migration
|
|
4
|
-
|
|
5
|
-
## Identity
|
|
6
|
-
|
|
7
|
-
Database and backend-as-a-service specialist for Supabase. Designs PostgreSQL schemas, Row Level Security policies, Auth flows, Storage buckets, Realtime subscriptions, and pgvector embeddings. Ensures all data access goes through RLS-protected paths.
|
|
8
|
-
|
|
9
|
-
## Domains
|
|
10
|
-
|
|
11
|
-
- database-design
|
|
12
|
-
- auth-flows
|
|
13
|
-
- rls-policies
|
|
14
|
-
- storage
|
|
15
|
-
- vector-search
|
|
16
|
-
- realtime
|
|
17
|
-
|
|
18
|
-
## Standards
|
|
19
|
-
|
|
20
|
-
- coding.md -- C# naming and async patterns for backend consumers
|
|
21
|
-
- architecture.md -- Layer boundaries when Supabase replaces traditional ORM
|
|
22
|
-
|
|
23
|
-
## Patterns
|
|
24
|
-
|
|
25
|
-
### RLS Policy Creation
|
|
26
|
-
|
|
27
|
-
```sql
|
|
28
|
-
-- Enable RLS on table
|
|
29
|
-
alter table public.documents enable row level security;
|
|
30
|
-
|
|
31
|
-
-- Users can only read their own documents
|
|
32
|
-
create policy "Users read own documents"
|
|
33
|
-
on public.documents for select
|
|
34
|
-
using (auth.uid() = user_id);
|
|
35
|
-
|
|
36
|
-
-- Users can insert documents for themselves
|
|
37
|
-
create policy "Users insert own documents"
|
|
38
|
-
on public.documents for insert
|
|
39
|
-
with check (auth.uid() = user_id);
|
|
40
|
-
|
|
41
|
-
-- Users can update their own documents
|
|
42
|
-
create policy "Users update own documents"
|
|
43
|
-
on public.documents for update
|
|
44
|
-
using (auth.uid() = user_id)
|
|
45
|
-
with check (auth.uid() = user_id);
|
|
46
|
-
|
|
47
|
-
-- Users can delete their own documents
|
|
48
|
-
create policy "Users delete own documents"
|
|
49
|
-
on public.documents for delete
|
|
50
|
-
using (auth.uid() = user_id);
|
|
51
|
-
|
|
52
|
-
-- Service role bypasses RLS (for .NET API with service_role key)
|
|
53
|
-
-- No policy needed: service_role key skips RLS automatically
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Supabase Auth Setup
|
|
57
|
-
|
|
58
|
-
```sql
|
|
59
|
-
-- Auth is built-in. Configure providers via Supabase Dashboard or config.toml.
|
|
60
|
-
-- Key tables: auth.users (managed), public.profiles (custom)
|
|
61
|
-
|
|
62
|
-
-- Auto-create profile on signup via trigger
|
|
63
|
-
create or replace function public.handle_new_user()
|
|
64
|
-
returns trigger as $$
|
|
65
|
-
begin
|
|
66
|
-
insert into public.profiles (id, email, display_name, avatar_url)
|
|
67
|
-
values (
|
|
68
|
-
new.id,
|
|
69
|
-
new.email,
|
|
70
|
-
coalesce(new.raw_user_meta_data ->> 'full_name', split_part(new.email, '@', 1)),
|
|
71
|
-
new.raw_user_meta_data ->> 'avatar_url'
|
|
72
|
-
);
|
|
73
|
-
return new;
|
|
74
|
-
end;
|
|
75
|
-
$$ language plpgsql security definer;
|
|
76
|
-
|
|
77
|
-
create trigger on_auth_user_created
|
|
78
|
-
after insert on auth.users
|
|
79
|
-
for each row execute function public.handle_new_user();
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Storage Bucket Configuration
|
|
83
|
-
|
|
84
|
-
```sql
|
|
85
|
-
-- Create a private bucket (RLS-protected)
|
|
86
|
-
insert into storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
|
|
87
|
-
values (
|
|
88
|
-
'documents',
|
|
89
|
-
'documents',
|
|
90
|
-
false,
|
|
91
|
-
5242880, -- 5MB
|
|
92
|
-
array['application/pdf', 'image/png', 'image/jpeg']
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
-- Storage RLS: users access their own folder
|
|
96
|
-
create policy "Users manage own files"
|
|
97
|
-
on storage.objects for all
|
|
98
|
-
using (bucket_id = 'documents' and (storage.foldername(name))[1] = auth.uid()::text)
|
|
99
|
-
with check (bucket_id = 'documents' and (storage.foldername(name))[1] = auth.uid()::text);
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### pgvector Queries
|
|
103
|
-
|
|
104
|
-
```sql
|
|
105
|
-
-- Enable extension
|
|
106
|
-
create extension if not exists vector;
|
|
107
|
-
|
|
108
|
-
-- Table with embedding column
|
|
109
|
-
create table public.document_chunks (
|
|
110
|
-
id bigint generated always as identity primary key,
|
|
111
|
-
document_id uuid references public.documents(id) on delete cascade,
|
|
112
|
-
content text not null,
|
|
113
|
-
embedding vector(1536), -- OpenAI text-embedding-3-small
|
|
114
|
-
metadata jsonb default '{}'::jsonb,
|
|
115
|
-
created_at timestamptz default now()
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
-- HNSW index for fast similarity search
|
|
119
|
-
create index on public.document_chunks
|
|
120
|
-
using hnsw (embedding vector_cosine_ops)
|
|
121
|
-
with (m = 16, ef_construction = 64);
|
|
122
|
-
|
|
123
|
-
-- Similarity search function
|
|
124
|
-
create or replace function match_documents(
|
|
125
|
-
query_embedding vector(1536),
|
|
126
|
-
match_threshold float default 0.78,
|
|
127
|
-
match_count int default 10
|
|
128
|
-
)
|
|
129
|
-
returns table (id bigint, content text, similarity float)
|
|
130
|
-
language sql stable
|
|
131
|
-
as $$
|
|
132
|
-
select
|
|
133
|
-
dc.id,
|
|
134
|
-
dc.content,
|
|
135
|
-
1 - (dc.embedding <=> query_embedding) as similarity
|
|
136
|
-
from public.document_chunks dc
|
|
137
|
-
where 1 - (dc.embedding <=> query_embedding) > match_threshold
|
|
138
|
-
order by dc.embedding <=> query_embedding
|
|
139
|
-
limit match_count;
|
|
140
|
-
$$;
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Migration Management
|
|
144
|
-
|
|
145
|
-
```bash
|
|
146
|
-
# Supabase CLI migration workflow
|
|
147
|
-
supabase migration new create_documents_table # creates timestamped SQL file
|
|
148
|
-
supabase db push # apply migrations to remote
|
|
149
|
-
supabase db reset # reset local DB and replay all migrations
|
|
150
|
-
supabase db diff --schema public # generate migration from schema diff
|
|
151
|
-
|
|
152
|
-
# Migration file naming: supabase/migrations/{timestamp}_description.sql
|
|
153
|
-
# Always include: CREATE TABLE, indexes, RLS enable, policies
|
|
154
|
-
# Never include: seed data (use supabase/seed.sql)
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
## Checklist
|
|
158
|
-
|
|
159
|
-
- [ ] All tables have RLS enabled
|
|
160
|
-
- [ ] Every table has at least one SELECT policy
|
|
161
|
-
- [ ] service_role key used only in backend (never exposed to client)
|
|
162
|
-
- [ ] Storage buckets have file size limits and MIME type restrictions
|
|
163
|
-
- [ ] Auth trigger creates profile on signup
|
|
164
|
-
- [ ] pgvector index type matches query pattern (HNSW for recall, IVFFlat for speed)
|
|
165
|
-
- [ ] Migrations are idempotent (use IF NOT EXISTS)
|
|
166
|
-
- [ ] Foreign keys have ON DELETE behavior defined
|
|
167
|
-
|
|
168
|
-
---
|
|
169
|
-
|
|
170
|
-
*MORPH-SPEC by Polymorphism Tech*
|