@polymorphism-tech/morph-spec 4.7.1 → 4.7.2
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/.morph/.morphversion +5 -0
- package/.morph/analytics/threads-log.jsonl +5 -0
- package/.morph/config/config.json +8 -0
- package/.morph/framework/agents.json +1815 -0
- package/.morph/framework/hooks/README.md +205 -0
- package/.morph/framework/hooks/claude-code/notification/approval-reminder.js +54 -0
- package/.morph/framework/hooks/claude-code/post-tool-use/dispatch.js +83 -0
- package/.morph/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +42 -0
- package/.morph/framework/hooks/claude-code/pre-compact/save-morph-context.js +61 -0
- package/.morph/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +71 -0
- package/.morph/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +58 -0
- package/.morph/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +64 -0
- package/.morph/framework/hooks/claude-code/session-start/inject-morph-context.js +94 -0
- package/.morph/framework/hooks/claude-code/statusline.py +538 -0
- package/.morph/framework/hooks/claude-code/statusline.sh +7 -0
- package/.morph/framework/hooks/claude-code/stop/validate-completion.js +88 -0
- package/.morph/framework/hooks/claude-code/user-prompt/enrich-prompt.js +91 -0
- package/.morph/framework/hooks/git/commit-msg/conventional-commits.sh +33 -0
- package/.morph/framework/hooks/git/pre-commit/agents.sh +25 -0
- package/.morph/framework/hooks/git/pre-commit/orchestrator.sh +64 -0
- package/.morph/framework/hooks/git/pre-commit/specs.sh +50 -0
- package/.morph/framework/hooks/git/pre-push/run-tests.sh +44 -0
- package/.morph/framework/hooks/shared/hook-response.js +45 -0
- package/.morph/framework/hooks/shared/phase-utils.js +129 -0
- package/.morph/framework/hooks/shared/state-reader.js +138 -0
- package/.morph/framework/hooks/shared/stdin-reader.js +26 -0
- package/.morph/framework/standards/STANDARDS.json +933 -0
- package/.morph/framework/standards/ai-agents/blazor-ui.md +364 -0
- package/.morph/framework/standards/ai-agents/production.md +415 -0
- package/.morph/framework/standards/ai-agents/setup.md +418 -0
- package/.morph/framework/standards/ai-agents/team-orchestration.md +479 -0
- package/.morph/framework/standards/ai-agents/workflows.md +354 -0
- package/.morph/framework/standards/architecture/ddd/aggregates.md +120 -0
- package/.morph/framework/standards/architecture/ddd/bounded-contexts.md +105 -0
- package/.morph/framework/standards/architecture/ddd/complexity-levels.md +108 -0
- package/.morph/framework/standards/architecture/ddd/entities.md +99 -0
- package/.morph/framework/standards/architecture/ddd/ubiquitous-language.md +58 -0
- package/.morph/framework/standards/architecture/ddd/value-objects.md +124 -0
- package/.morph/framework/standards/backend/api/minimal-api.md +494 -0
- package/.morph/framework/standards/backend/api/rest.md +492 -0
- package/.morph/framework/standards/backend/api/validation.md +88 -0
- package/.morph/framework/standards/backend/authentication/passkeys.md +428 -0
- package/.morph/framework/standards/backend/database/ef-core.md +199 -0
- package/.morph/framework/standards/backend/database/migrations.md +393 -0
- package/.morph/framework/standards/backend/database/postgresql/database.md +352 -0
- package/.morph/framework/standards/backend/database/repository-patterns.md +528 -0
- package/.morph/framework/standards/backend/database/vector-search-rag.md +541 -0
- package/.morph/framework/standards/backend/dotnet/async.md +366 -0
- package/.morph/framework/standards/backend/dotnet/core.md +117 -0
- package/.morph/framework/standards/backend/dotnet/di.md +439 -0
- package/.morph/framework/standards/backend/dotnet/program-cs-checklist.md +92 -0
- package/.morph/framework/standards/backend/integrations/asaas/asaas-api.md +216 -0
- package/.morph/framework/standards/backend/integrations/clerk/clerk-auth.md +290 -0
- package/.morph/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +350 -0
- package/.morph/framework/standards/backend/integrations/resend/resend-email.md +385 -0
- package/.morph/framework/standards/context/analytics.md +96 -0
- package/.morph/framework/standards/context/bundles.md +110 -0
- package/.morph/framework/standards/context/priming.md +78 -0
- package/.morph/framework/standards/core/architecture.md +185 -0
- package/.morph/framework/standards/core/coding.md +214 -0
- package/.morph/framework/standards/core/git-branching-strategy.md +403 -0
- package/.morph/framework/standards/core/git.md +185 -0
- package/.morph/framework/standards/core/testing.md +295 -0
- package/.morph/framework/standards/data/nosql/blob-storage.md +102 -0
- package/.morph/framework/standards/data/nosql/cache/redis.md +97 -0
- package/.morph/framework/standards/data/nosql/cosmos-db.md +118 -0
- package/.morph/framework/standards/data/vector-search/azure-ai-search.md +121 -0
- package/.morph/framework/standards/data/vector-search/rag-chunking.md +104 -0
- package/.morph/framework/standards/frontend/blazor/design-checklist.md +222 -0
- package/.morph/framework/standards/frontend/blazor/fluent-ui-setup.md +595 -0
- package/.morph/framework/standards/frontend/blazor/fluent-ui.md +137 -0
- package/.morph/framework/standards/frontend/blazor/html-conversion.md +184 -0
- package/.morph/framework/standards/frontend/blazor/lifecycle.md +195 -0
- package/.morph/framework/standards/frontend/blazor/pitfalls.md +198 -0
- package/.morph/framework/standards/frontend/blazor/state.md +191 -0
- package/.morph/framework/standards/frontend/design-system/animations.md +151 -0
- package/.morph/framework/standards/frontend/design-system/naming.md +64 -0
- package/.morph/framework/standards/frontend/nextjs/app-router.md +123 -0
- package/.morph/framework/standards/frontend/nextjs/components.md +132 -0
- package/.morph/framework/standards/frontend/nextjs/data-fetching.md +126 -0
- package/.morph/framework/standards/frontend/nextjs/forms.md +128 -0
- package/.morph/framework/standards/frontend/nextjs/naming-conventions.md +67 -0
- package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +215 -0
- package/.morph/framework/standards/frontend/nextjs/project-structure.md +102 -0
- package/.morph/framework/standards/frontend/nextjs/state-management.md +72 -0
- package/.morph/framework/standards/frontend/nextjs/testing.md +111 -0
- package/.morph/framework/standards/infrastructure/azure/azure.md +624 -0
- package/.morph/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +422 -0
- package/.morph/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +516 -0
- package/.morph/framework/standards/infrastructure/azure/devops/local-development.md +520 -0
- package/.morph/framework/standards/infrastructure/azure/services/functions.md +486 -0
- package/.morph/framework/standards/infrastructure/azure/services/service-bus.md +459 -0
- package/.morph/framework/standards/infrastructure/azure/services/storage.md +407 -0
- package/.morph/framework/standards/infrastructure/docker/easypanel-deploy.md +196 -0
- package/.morph/framework/standards/infrastructure/supabase/mcp-setup.md +252 -0
- package/.morph/framework/standards/infrastructure/supabase/supabase-auth.md +176 -0
- package/.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md +169 -0
- package/.morph/framework/standards/infrastructure/supabase/supabase-rls.md +184 -0
- package/.morph/framework/standards/infrastructure/supabase/supabase-storage.md +153 -0
- package/.morph/framework/standards/integration/api/graphql.md +91 -0
- package/.morph/framework/standards/integration/api/grpc.md +114 -0
- package/.morph/framework/standards/integration/api/rest-design.md +95 -0
- package/.morph/framework/standards/integration/event-driven/cqrs.md +101 -0
- package/.morph/framework/standards/integration/event-driven/event-sourcing.md +124 -0
- package/.morph/framework/standards/integration/event-driven/service-bus.md +95 -0
- package/.morph/framework/standards/integration/mcp/mcp-tools.md +384 -0
- package/.morph/framework/standards/observability/logging.md +131 -0
- package/.morph/framework/standards/observability/metrics.md +121 -0
- package/.morph/framework/standards/observability/monitoring.md +114 -0
- package/.morph/framework/standards/observability/tracing.md +132 -0
- package/.morph/framework/standards/workflows/parallel-execution.md +112 -0
- package/.morph/framework/standards/workflows/thread-management.md +113 -0
- package/.morph/framework/templates/.idea/morph-templates.xml +92 -0
- package/.morph/framework/templates/.vscode/morph-templates.code-snippets +186 -0
- package/.morph/framework/templates/IDE-SNIPPETS.md +266 -0
- package/.morph/framework/templates/README.md +814 -0
- package/.morph/framework/templates/REGISTRY.json +1888 -0
- package/.morph/framework/templates/code/dotnet/backend/repository.cs +141 -0
- package/.morph/framework/templates/code/dotnet/backend/service.cs +139 -0
- package/.morph/framework/templates/code/dotnet/contracts/Commands.cs +74 -0
- package/.morph/framework/templates/code/dotnet/contracts/Entities.cs +25 -0
- package/.morph/framework/templates/code/dotnet/contracts/Queries.cs +74 -0
- package/.morph/framework/templates/code/dotnet/contracts/README.md +74 -0
- package/.morph/framework/templates/code/dotnet/contracts/api-contracts.cs +173 -0
- package/.morph/framework/templates/code/dotnet/contracts/contracts-level1.cs +69 -0
- package/.morph/framework/templates/code/dotnet/contracts/contracts-level2.cs +86 -0
- package/.morph/framework/templates/code/dotnet/contracts/contracts-level3.cs +41 -0
- package/.morph/framework/templates/code/dotnet/database/migration.cs +83 -0
- package/.morph/framework/templates/code/dotnet/frontend/component.razor +239 -0
- package/.morph/framework/templates/code/dotnet/jobs/agent.cs +163 -0
- package/.morph/framework/templates/code/dotnet/jobs/job.cs +171 -0
- package/.morph/framework/templates/code/dotnet/test.cs +239 -0
- package/.morph/framework/templates/code/sql/rls-policy.sql +57 -0
- package/.morph/framework/templates/code/sql/supabase-migration.sql +100 -0
- package/.morph/framework/templates/code/sql/supabase-migration.template.sql +113 -0
- package/.morph/framework/templates/code/typescript/contracts.ts +168 -0
- package/.morph/framework/templates/context/CONTEXT-FEATURE.md +276 -0
- package/.morph/framework/templates/context/CONTEXT.md +181 -0
- package/.morph/framework/templates/docs/clarifications.md +253 -0
- package/.morph/framework/templates/docs/onboarding.md +123 -0
- package/.morph/framework/templates/docs/proposal.md +182 -0
- package/.morph/framework/templates/docs/schema-analysis.md +119 -0
- package/.morph/framework/templates/docs/spec.md +198 -0
- package/.morph/framework/templates/docs/ui-components.md +124 -0
- package/.morph/framework/templates/docs/ui-design-system.md +76 -0
- package/.morph/framework/templates/docs/ui-flows.md +167 -0
- package/.morph/framework/templates/docs/ui-mockups.md +98 -0
- package/.morph/framework/templates/docs/user-stories.md +34 -0
- package/.morph/framework/templates/examples/design-system-examples.md +357 -0
- package/.morph/framework/templates/examples/spec-examples.md +90 -0
- package/.morph/framework/templates/feature/decisions.md +187 -0
- package/.morph/framework/templates/feature/recap.md +146 -0
- package/.morph/framework/templates/feature/tasks.md +199 -0
- package/.morph/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -0
- package/.morph/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -0
- package/.morph/framework/templates/frontend/nextjs/env.mjs.hbs +32 -0
- package/.morph/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -0
- package/.morph/framework/templates/frontend/nextjs/page.tsx.hbs +22 -0
- package/.morph/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -0
- package/.morph/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -0
- package/.morph/framework/templates/infrastructure/azure/Dockerfile.example +82 -0
- package/.morph/framework/templates/infrastructure/azure/README.md +286 -0
- package/.morph/framework/templates/infrastructure/azure/app-insights.bicep +63 -0
- package/.morph/framework/templates/infrastructure/azure/app-service.bicep +164 -0
- package/.morph/framework/templates/infrastructure/azure/container-app-env.bicep +49 -0
- package/.morph/framework/templates/infrastructure/azure/container-app.bicep +156 -0
- package/.morph/framework/templates/infrastructure/azure/deploy-checklist.md +426 -0
- package/.morph/framework/templates/infrastructure/azure/deploy.ps1 +229 -0
- package/.morph/framework/templates/infrastructure/azure/deploy.sh +208 -0
- package/.morph/framework/templates/infrastructure/azure/key-vault.bicep +91 -0
- package/.morph/framework/templates/infrastructure/azure/main.bicep +189 -0
- package/.morph/framework/templates/infrastructure/azure/parameters.dev.json +29 -0
- package/.morph/framework/templates/infrastructure/azure/parameters.prod.json +29 -0
- package/.morph/framework/templates/infrastructure/azure/parameters.staging.json +29 -0
- package/.morph/framework/templates/infrastructure/azure/sql-database.bicep +103 -0
- package/.morph/framework/templates/infrastructure/azure/storage.bicep +106 -0
- package/.morph/framework/templates/infrastructure/docker/Dockerfile.template +58 -0
- package/.morph/framework/templates/infrastructure/docker/docker-compose.template.yml +67 -0
- package/.morph/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -0
- package/.morph/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -0
- package/.morph/framework/templates/infrastructure/docker/easypanel.template.json +54 -0
- package/.morph/framework/templates/infrastructure/github/README.md +593 -0
- package/.morph/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +22 -0
- package/.morph/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -0
- package/.morph/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -0
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +61 -0
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +31 -0
- package/.morph/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -0
- package/.morph/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -0
- package/.morph/framework/templates/integrations/asaas-client.cs +387 -0
- package/.morph/framework/templates/integrations/asaas-webhook.cs +351 -0
- package/.morph/framework/templates/integrations/azure-identity-config.cs +288 -0
- package/.morph/framework/templates/integrations/clerk-config.cs +258 -0
- package/.morph/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -0
- package/.morph/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -0
- package/.morph/framework/templates/meta-prompts/hops/hop-retry.md +78 -0
- package/.morph/framework/templates/meta-prompts/hops/hop-validation.md +97 -0
- package/.morph/framework/templates/meta-prompts/hops/hop-wrapper.md +36 -0
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +113 -0
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +80 -0
- package/.morph/framework/templates/meta-prompts/squad-leaders/backend-squad.md +90 -0
- package/.morph/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +126 -0
- package/.morph/framework/templates/meta-prompts/squad-leaders/squad-leader.md +43 -0
- package/.morph/framework/templates/meta-prompts/validators/checkpoint-validator.md +107 -0
- package/.morph/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -0
- package/.morph/framework/templates/project-structure/dotnet-ddd.md +70 -0
- package/.morph/framework/templates/saas/subscription.cs +347 -0
- package/.morph/framework/templates/saas/tenant.cs +338 -0
- package/.morph/framework/templates/state.template.json +17 -0
- package/.morph/framework/templates/ui/FluentDesignTheme.cs +149 -0
- package/.morph/framework/templates/ui/MudTheme.cs +281 -0
- package/.morph/framework/templates/ui/design-system.css +226 -0
- package/.morph/logs/tool-failures.log +17 -0
- package/.morph/memory/pre-compact-2026-02-24T17-43-30-049Z.json +16 -0
- package/.morph/plans/eager-watching-bunny.md +105 -0
- package/.morph/plans/temporal-seeking-nebula.md +45 -0
- package/.morph/state.json +48 -0
- package/CLAUDE.md +1 -1
- package/README.md +2 -2
- package/bin/morph-spec.js +0 -9
- package/framework/CLAUDE.md +1 -1
- package/framework/hooks/README.md +10 -6
- package/framework/hooks/claude-code/notification/approval-reminder.js +2 -0
- package/framework/hooks/claude-code/post-tool-use/dispatch.js +1 -1
- package/framework/hooks/claude-code/stop/validate-completion.js +1 -1
- package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +1 -1
- package/package.json +1 -1
- package/src/commands/project/init.js +15 -42
- package/src/commands/project/update.js +22 -37
- package/src/lib/installers/mcp-installer.js +18 -3
- package/src/utils/hooks-installer.js +5 -15
- package/src/commands/project/detect.js +0 -114
|
@@ -0,0 +1,814 @@
|
|
|
1
|
+
# MORPH-SPEC Template System
|
|
2
|
+
|
|
3
|
+
> **Technology-Based Organization for Multi-Stack Reusability**
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The MORPH-SPEC template system provides **57 production-ready templates** organized by **technology** (not by stack) to enable maximum reusability across current and future stacks.
|
|
8
|
+
|
|
9
|
+
**Key Principle:** Templates are grouped by the **technology they use** (dotnet, typescript, sql, azure, docker), allowing new stacks like `vue-firebase` or `angular-mongodb` to reuse existing templates for .NET, TypeScript, SQL, etc.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 📁 Directory Structure
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
framework/templates/
|
|
17
|
+
├── docs/ # Universal documentation templates
|
|
18
|
+
│ ├── proposal.md # Feature proposal (required)
|
|
19
|
+
│ └── spec.md # Technical specification (required)
|
|
20
|
+
│
|
|
21
|
+
├── feature/ # Feature management
|
|
22
|
+
│ ├── tasks.md # Implementation tasks (required)
|
|
23
|
+
│ ├── decisions.md # Architecture Decision Records (required)
|
|
24
|
+
│ └── recap.md # Post-implementation summary (required)
|
|
25
|
+
│
|
|
26
|
+
├── context/ # Context generation
|
|
27
|
+
│ ├── CONTEXT.md # Project-level context
|
|
28
|
+
│ └── CONTEXT-FEATURE.md # Feature-level context
|
|
29
|
+
│
|
|
30
|
+
├── code/ # Code templates organized by technology
|
|
31
|
+
│ ├── dotnet/
|
|
32
|
+
│ │ ├── backend/
|
|
33
|
+
│ │ │ ├── service.cs # Service layer
|
|
34
|
+
│ │ │ ├── repository.cs # Data access layer
|
|
35
|
+
│ │ │ └── test.cs # Unit tests
|
|
36
|
+
│ │ ├── frontend/
|
|
37
|
+
│ │ │ └── component.razor # Blazor components
|
|
38
|
+
│ │ ├── database/
|
|
39
|
+
│ │ │ └── migration.cs # EF Core migrations
|
|
40
|
+
│ │ ├── jobs/
|
|
41
|
+
│ │ │ ├── job.cs # Hangfire background jobs
|
|
42
|
+
│ │ │ └── agent.cs # MS Agent Framework agents
|
|
43
|
+
│ │ └── contracts/
|
|
44
|
+
│ │ ├── contracts.cs # Base contracts
|
|
45
|
+
│ │ ├── Commands.cs # CQRS commands
|
|
46
|
+
│ │ ├── Queries.cs # CQRS queries
|
|
47
|
+
│ │ ├── Entities.cs # Domain entities
|
|
48
|
+
│ │ ├── api-contracts.cs # API contracts
|
|
49
|
+
│ │ └── README.md # Contracts documentation
|
|
50
|
+
│ │
|
|
51
|
+
│ ├── typescript/
|
|
52
|
+
│ │ └── contracts.ts # TypeScript type definitions
|
|
53
|
+
│ │
|
|
54
|
+
│ └── sql/
|
|
55
|
+
│ ├── supabase-migration.sql # Basic migration
|
|
56
|
+
│ ├── supabase-migration.template.sql # Enhanced migration
|
|
57
|
+
│ └── rls-policy.sql # Row-level security
|
|
58
|
+
│
|
|
59
|
+
├── infrastructure/
|
|
60
|
+
│ ├── azure/ # Azure Bicep templates
|
|
61
|
+
│ │ ├── main.bicep # Main orchestration (required)
|
|
62
|
+
│ │ ├── container-app.bicep # Container Apps
|
|
63
|
+
│ │ ├── container-app-env.bicep # Container environment
|
|
64
|
+
│ │ ├── app-service.bicep # App Service
|
|
65
|
+
│ │ ├── sql-database.bicep # Azure SQL
|
|
66
|
+
│ │ ├── storage.bicep # Storage Account
|
|
67
|
+
│ │ ├── key-vault.bicep # Key Vault
|
|
68
|
+
│ │ ├── app-insights.bicep # Application Insights
|
|
69
|
+
│ │ ├── parameters.dev.json # Dev parameters
|
|
70
|
+
│ │ ├── parameters.staging.json # Staging parameters
|
|
71
|
+
│ │ ├── parameters.prod.json # Prod parameters
|
|
72
|
+
│ │ ├── deploy.ps1 # PowerShell deploy
|
|
73
|
+
│ │ ├── deploy.sh # Bash deploy
|
|
74
|
+
│ │ ├── deploy-checklist.md # Pre-deploy checklist
|
|
75
|
+
│ │ ├── azure-pipelines-deploy.yml # Azure DevOps
|
|
76
|
+
│ │ ├── Dockerfile.example # Dockerfile example
|
|
77
|
+
│ │ └── README.md # Infrastructure docs
|
|
78
|
+
│ │
|
|
79
|
+
│ ├── docker/ # Docker & EasyPanel
|
|
80
|
+
│ │ ├── dockerfile-api.dockerfile # .NET API
|
|
81
|
+
│ │ ├── dockerfile-web.dockerfile # Next.js web
|
|
82
|
+
│ │ ├── Dockerfile.template # Generic
|
|
83
|
+
│ │ ├── docker-compose.template.yml # Compose
|
|
84
|
+
│ │ └── easypanel.template.json # EasyPanel config
|
|
85
|
+
│ │
|
|
86
|
+
│ └── github/ # GitHub Actions CI/CD
|
|
87
|
+
│ ├── workflows/ # Reusable workflow templates
|
|
88
|
+
│ │ ├── dotnet-build.yml.hbs # .NET restore, build, test
|
|
89
|
+
│ │ ├── docker-build-push.yml.hbs # Docker build & push
|
|
90
|
+
│ │ ├── deploy-azure-app-service.yml.hbs # Azure App Service deployment
|
|
91
|
+
│ │ └── deploy-easypanel.yml.hbs # EasyPanel deployment
|
|
92
|
+
│ │
|
|
93
|
+
│ ├── actions/ # Composite action templates
|
|
94
|
+
│ │ ├── docker-build-push/action.yml.hbs
|
|
95
|
+
│ │ ├── health-check/action.yml.hbs
|
|
96
|
+
│ │ └── azure-auth/action.yml.hbs
|
|
97
|
+
│ │
|
|
98
|
+
│ └── README.md # GitHub Actions docs
|
|
99
|
+
│
|
|
100
|
+
├── integrations/ # Platform-agnostic integrations
|
|
101
|
+
│ ├── asaas-client.cs # Asaas financial API
|
|
102
|
+
│ ├── asaas-webhook.cs # Asaas webhooks
|
|
103
|
+
│ ├── azure-identity-config.cs # Azure AD/Entra
|
|
104
|
+
│ └── clerk-config.cs # Clerk auth
|
|
105
|
+
│
|
|
106
|
+
├── ui/ # Design systems
|
|
107
|
+
│ ├── design-system.css # CSS tokens
|
|
108
|
+
│ ├── FluentDesignTheme.cs # Fluent UI theme
|
|
109
|
+
│ └── MudTheme.cs # MudBlazor theme
|
|
110
|
+
│
|
|
111
|
+
├── saas/ # Multi-tenant patterns
|
|
112
|
+
│ ├── subscription.cs # Subscription model
|
|
113
|
+
│ └── tenant.cs # Tenant model
|
|
114
|
+
│
|
|
115
|
+
├── examples/ # Reference implementations
|
|
116
|
+
│ ├── spec-examples.md # Example specs
|
|
117
|
+
│ └── design-system-examples.md # Design system examples
|
|
118
|
+
│
|
|
119
|
+
└── REGISTRY.json # Template metadata registry
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 🏗️ Technology-Based Architecture
|
|
125
|
+
|
|
126
|
+
**Why organize by technology instead of by stack?**
|
|
127
|
+
|
|
128
|
+
| Organization | Pros | Cons | Best For |
|
|
129
|
+
|--------------|------|------|----------|
|
|
130
|
+
| **By Stack** (old v1) | Stack-specific optimizations | Duplicate templates, hard to reuse | Single-stack projects |
|
|
131
|
+
| **By Technology** (new v2) | Reusable, DRY, future-proof | Requires stack override mechanism | Multi-stack frameworks |
|
|
132
|
+
|
|
133
|
+
**Example:** A `.NET service.cs` template works for both `blazor-azure` and `nextjs-supabase` stacks (both use .NET backend). No need to duplicate!
|
|
134
|
+
|
|
135
|
+
**Future-proof:** When we create `vue-firebase` stack, we can reuse:
|
|
136
|
+
- `code/typescript/` templates
|
|
137
|
+
- `infrastructure/docker/` templates
|
|
138
|
+
- `integrations/` templates (Clerk, etc.)
|
|
139
|
+
|
|
140
|
+
**Only create NEW templates for Vue-specific code.**
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## ⚙️ Template Engine: Handlebars
|
|
145
|
+
|
|
146
|
+
All templates use **Handlebars** with **20+ custom helpers**.
|
|
147
|
+
|
|
148
|
+
### Basic Syntax
|
|
149
|
+
|
|
150
|
+
```handlebars
|
|
151
|
+
# Feature: {{titleCase FEATURE_NAME}}
|
|
152
|
+
|
|
153
|
+
Namespace: {{pascalCase FEATURE_NAME}}
|
|
154
|
+
|
|
155
|
+
Created: {{DATE}}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Available Helpers
|
|
159
|
+
|
|
160
|
+
| Helper | Input | Output | Usage |
|
|
161
|
+
|--------|-------|--------|-------|
|
|
162
|
+
| `{{pascalCase str}}` | `user-profile` | `UserProfile` | Class names |
|
|
163
|
+
| `{{camelCase str}}` | `user-profile` | `userProfile` | Variable names |
|
|
164
|
+
| `{{snakeCase str}}` | `user-profile` | `user_profile` | SQL tables |
|
|
165
|
+
| `{{upperSnakeCase str}}` | `user-profile` | `USER_PROFILE` | Constants |
|
|
166
|
+
| `{{titleCase str}}` | `user-profile` | `User Profile` | Titles |
|
|
167
|
+
| `{{kebabCase str}}` | `User Profile` | `user-profile` | URLs |
|
|
168
|
+
| `{{pluralize str}}` | `user` | `users` | Collections |
|
|
169
|
+
| `{{singularize str}}` | `users` | `user` | Entities |
|
|
170
|
+
| `{{eq a b}}` | `"blazor" "blazor"` | `true` | Conditionals |
|
|
171
|
+
| `{{or a b}}` | `false true` | `true` | Logical OR |
|
|
172
|
+
| `{{and a b}}` | `true false` | `false` | Logical AND |
|
|
173
|
+
| `{{default val fallback}}` | `null "default"` | `"default"` | Defaults |
|
|
174
|
+
|
|
175
|
+
### Conditional Logic
|
|
176
|
+
|
|
177
|
+
```handlebars
|
|
178
|
+
{{#if (eq STACK "blazor-azure")}}
|
|
179
|
+
// Azure-specific code
|
|
180
|
+
{{else if (eq STACK "nextjs-supabase")}}
|
|
181
|
+
// Supabase-specific code
|
|
182
|
+
{{else}}
|
|
183
|
+
// Generic code
|
|
184
|
+
{{/if}}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Deprecated: Pre-computed Variables
|
|
188
|
+
|
|
189
|
+
**❌ Old (v1):**
|
|
190
|
+
```handlebars
|
|
191
|
+
{{pascalCase FEATURE_NAME}} <!-- Pre-computed in bin/render-template.js -->
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**✅ New (v2):**
|
|
195
|
+
```handlebars
|
|
196
|
+
{{pascalCase FEATURE_NAME}} <!-- Computed via Handlebars helper -->
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 🛠️ CLI Commands
|
|
202
|
+
|
|
203
|
+
### List All Templates
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# List all templates
|
|
207
|
+
morph-spec template list
|
|
208
|
+
|
|
209
|
+
# Filter by category
|
|
210
|
+
morph-spec template list --category code
|
|
211
|
+
morph-spec template list --category infrastructure
|
|
212
|
+
|
|
213
|
+
# Filter by phase
|
|
214
|
+
morph-spec template list --phase implement
|
|
215
|
+
|
|
216
|
+
# Filter by stack applicability
|
|
217
|
+
morph-spec template list --stack blazor-azure
|
|
218
|
+
|
|
219
|
+
# Show only required templates
|
|
220
|
+
morph-spec template list --required
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Output:**
|
|
224
|
+
```
|
|
225
|
+
📦 Universal Templates (9)
|
|
226
|
+
proposal Feature Proposal [REQUIRED] [UNIVERSAL] [HBS]
|
|
227
|
+
spec Technical Specification [REQUIRED] [UNIVERSAL] [HBS]
|
|
228
|
+
tasks Implementation Tasks [REQUIRED] [UNIVERSAL] [HBS]
|
|
229
|
+
...
|
|
230
|
+
|
|
231
|
+
📦 Technology-Based Templates (48)
|
|
232
|
+
dotnet-backend-service .NET Service Class [UNIVERSAL] [HBS] (dotnet)
|
|
233
|
+
typescript-contracts TypeScript Contracts [UNIVERSAL] [HBS] (typescript)
|
|
234
|
+
azure-bicep-main Main Bicep Orchestration [REQUIRED] [UNIVERSAL] [HBS] (bicep)
|
|
235
|
+
...
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Show Template Details
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Show metadata
|
|
242
|
+
morph-spec template show dotnet-backend-service
|
|
243
|
+
|
|
244
|
+
# Show with file preview
|
|
245
|
+
morph-spec template show dotnet-backend-service --preview
|
|
246
|
+
|
|
247
|
+
# Show with resolved path
|
|
248
|
+
morph-spec template show dotnet-backend-service --show-path
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Output:**
|
|
252
|
+
```
|
|
253
|
+
Template: dotnet-backend-service
|
|
254
|
+
|
|
255
|
+
📋 Metadata
|
|
256
|
+
ID: dotnet-backend-service
|
|
257
|
+
Name: .NET Service Class
|
|
258
|
+
Path: code/dotnet/backend/service.cs
|
|
259
|
+
Location: framework
|
|
260
|
+
Category: code
|
|
261
|
+
Phase: implement
|
|
262
|
+
Required: No
|
|
263
|
+
Technology: dotnet
|
|
264
|
+
Applicable Stacks: blazor-azure, nextjs-supabase
|
|
265
|
+
|
|
266
|
+
📝 Description
|
|
267
|
+
C# service class template with dependency injection and interface pattern
|
|
268
|
+
|
|
269
|
+
🔑 Variables
|
|
270
|
+
{{FEATURE_NAME}}
|
|
271
|
+
{{NAMESPACE}}
|
|
272
|
+
|
|
273
|
+
📄 Output Name
|
|
274
|
+
{FeatureName}Service.cs
|
|
275
|
+
|
|
276
|
+
💡 Usage Hint
|
|
277
|
+
morph-spec template render dotnet-backend-service output.cs '{"FEATURE_NAME":"user-auth","NAMESPACE":"MyApp"}'
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Render Template
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
# Render to file
|
|
284
|
+
morph-spec template render dotnet-backend-service UserAuthService.cs '{
|
|
285
|
+
"FEATURE_NAME": "user-auth",
|
|
286
|
+
"NAMESPACE": "MyApp.Services"
|
|
287
|
+
}'
|
|
288
|
+
|
|
289
|
+
# Dry run (preview only)
|
|
290
|
+
morph-spec template render dotnet-backend-service output.cs '{"FEATURE_NAME":"test"}' --dry-run
|
|
291
|
+
|
|
292
|
+
# Auto-resolve path (searches framework → stack override)
|
|
293
|
+
morph-spec template render proposal proposal.md '{"FEATURE_NAME":"auth"}' --resolve-path
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Default Variables (auto-injected):**
|
|
297
|
+
- `DATE`: `2026-02-17`
|
|
298
|
+
- `YEAR`: `2026`
|
|
299
|
+
- `TIMESTAMP`: `2026-02-17T19:38:00.000Z`
|
|
300
|
+
|
|
301
|
+
### Customize Template (Stack Override)
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# Copy to stack-specific directory (override framework version)
|
|
305
|
+
morph-spec template customize dotnet-backend-service --stack blazor-azure
|
|
306
|
+
|
|
307
|
+
# Copy to project-local (cross-stack override)
|
|
308
|
+
morph-spec template customize dotnet-backend-service --local
|
|
309
|
+
|
|
310
|
+
# Force overwrite if exists
|
|
311
|
+
morph-spec template customize dotnet-backend-service --stack blazor-azure --force
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Output:**
|
|
315
|
+
```
|
|
316
|
+
Source: framework/templates/code/dotnet/backend/service.cs
|
|
317
|
+
Destination: stacks/blazor-azure/.morph/framework/templates/code/dotnet/backend/service.cs
|
|
318
|
+
|
|
319
|
+
✅ Template copied for customization
|
|
320
|
+
|
|
321
|
+
📝 Next Steps
|
|
322
|
+
1. Edit the template file:
|
|
323
|
+
stacks/blazor-azure/.morph/framework/templates/code/dotnet/backend/service.cs
|
|
324
|
+
|
|
325
|
+
2. Template will now be used instead of framework version
|
|
326
|
+
(Stack-specific templates take precedence)
|
|
327
|
+
|
|
328
|
+
3. Test rendering:
|
|
329
|
+
morph-spec template render dotnet-backend-service output.cs '{"FEATURE_NAME":"test"}'
|
|
330
|
+
|
|
331
|
+
⚠️ Customized templates won't receive framework updates
|
|
332
|
+
To get updates: delete customized version and re-run this command
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 🔄 GitHub Actions Templates
|
|
338
|
+
|
|
339
|
+
The framework provides reusable GitHub Actions workflows and composite actions for CI/CD automation.
|
|
340
|
+
|
|
341
|
+
### Structure
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
infrastructure/github/
|
|
345
|
+
├── workflows/ # Reusable workflow templates
|
|
346
|
+
│ ├── dotnet-build.yml.hbs # .NET restore, build, test
|
|
347
|
+
│ ├── docker-build-push.yml.hbs # Docker build & push
|
|
348
|
+
│ ├── deploy-azure-app-service.yml.hbs # Azure App Service deployment
|
|
349
|
+
│ └── deploy-easypanel.yml.hbs # EasyPanel deployment
|
|
350
|
+
│
|
|
351
|
+
└── actions/ # Composite action templates
|
|
352
|
+
├── docker-build-push/action.yml.hbs
|
|
353
|
+
├── health-check/action.yml.hbs
|
|
354
|
+
└── azure-auth/action.yml.hbs
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Reusable Workflows vs Composite Actions
|
|
358
|
+
|
|
359
|
+
| Type | Purpose | Location | Usage |
|
|
360
|
+
|------|---------|----------|-------|
|
|
361
|
+
| **Reusable Workflows** | Complete CI/CD pipelines (multi-job) | `workflows/*.yml.hbs` | Called via `uses:` from stack workflows |
|
|
362
|
+
| **Composite Actions** | Reusable step logic (single responsibility) | `actions/*/action.yml.hbs` | Called via `uses:` in workflow steps |
|
|
363
|
+
|
|
364
|
+
### Deployment Strategy Difference
|
|
365
|
+
|
|
366
|
+
**Blazor-Azure:** Direct .NET publish to Azure App Service (no Docker)
|
|
367
|
+
- `dotnet publish` → `azure/webapps-deploy@v2`
|
|
368
|
+
- Bicep deploys App Service Plan + App Service
|
|
369
|
+
- Authentication: OIDC (Federated Identity)
|
|
370
|
+
|
|
371
|
+
**NextJS-Supabase:** Docker containers to EasyPanel
|
|
372
|
+
- `docker build` → `docker push` → EasyPanel webhook
|
|
373
|
+
- Multi-service deployment (API + Web)
|
|
374
|
+
- Registry: GitHub Container Registry (ghcr.io)
|
|
375
|
+
|
|
376
|
+
### Template Rendering
|
|
377
|
+
|
|
378
|
+
**GitHub Actions Constraint:**
|
|
379
|
+
- ❌ GitHub Actions CANNOT reference parent directories (`../../../../framework/`)
|
|
380
|
+
- ✅ Solution: Framework templates are **rendered** into each stack's `.github/` directory
|
|
381
|
+
- Rendered `.yml` files are **committed** to repos (not `.yml.hbs` templates)
|
|
382
|
+
|
|
383
|
+
**Rendering Process:**
|
|
384
|
+
```bash
|
|
385
|
+
# Render all GitHub Actions templates for a stack (manual for now)
|
|
386
|
+
# Future: morph-spec template render github-workflows --stack blazor-azure
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Handlebars Variables
|
|
390
|
+
|
|
391
|
+
- `{{APP_NAME}}` - Application name from config.json
|
|
392
|
+
- `{{DOTNET_VERSION}}` - .NET SDK version
|
|
393
|
+
- `{{GITHUB_OWNER}}` - GitHub organization/user
|
|
394
|
+
- `{{kebabCase APP_NAME}}` - Docker image name format
|
|
395
|
+
- `${{{{ inputs.* }}}}` - GitHub Actions runtime syntax (escaped with `{{{{raw}}}}`)
|
|
396
|
+
|
|
397
|
+
### Authentication & Secrets
|
|
398
|
+
|
|
399
|
+
**Azure (Blazor-Azure):**
|
|
400
|
+
```yaml
|
|
401
|
+
# OIDC (Federated Identity) - Recommended
|
|
402
|
+
- uses: azure/login@v1
|
|
403
|
+
with:
|
|
404
|
+
client-id: ${{{{ secrets.AZURE_CLIENT_ID }}}}
|
|
405
|
+
tenant-id: ${{{{ secrets.AZURE_TENANT_ID }}}}
|
|
406
|
+
subscription-id: ${{{{ secrets.AZURE_SUBSCRIPTION_ID }}}}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
**Docker Registry (NextJS-Supabase):**
|
|
410
|
+
```yaml
|
|
411
|
+
# GitHub Container Registry (ghcr.io)
|
|
412
|
+
- uses: docker/login-action@v3
|
|
413
|
+
with:
|
|
414
|
+
registry: ghcr.io
|
|
415
|
+
username: ${{{{ github.actor }}}}
|
|
416
|
+
password: ${{{{ secrets.GITHUB_TOKEN }}}}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**GitHub Secrets to Configure:**
|
|
420
|
+
- Blazor-Azure: `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`
|
|
421
|
+
- NextJS-Supabase: `GITHUB_TOKEN` (auto), `EASYPANEL_API_TOKEN`
|
|
422
|
+
|
|
423
|
+
### Example: Blazor-Azure CI/CD
|
|
424
|
+
|
|
425
|
+
**CI Build Workflow** (`stacks/blazor-azure/.morph/framework/templates/infrastructure/github/workflows/ci-build.yml.hbs`):
|
|
426
|
+
```yaml
|
|
427
|
+
name: CI Build
|
|
428
|
+
|
|
429
|
+
on:
|
|
430
|
+
pull_request:
|
|
431
|
+
branches: [main, staging]
|
|
432
|
+
|
|
433
|
+
jobs:
|
|
434
|
+
build:
|
|
435
|
+
uses: ./.github/workflows/dotnet-build.yml # Framework template (rendered)
|
|
436
|
+
with:
|
|
437
|
+
dotnet-version: '{{DOTNET_VERSION}}'
|
|
438
|
+
run-tests: true
|
|
439
|
+
|
|
440
|
+
security:
|
|
441
|
+
runs-on: ubuntu-latest
|
|
442
|
+
steps:
|
|
443
|
+
- uses: actions/checkout@v4
|
|
444
|
+
- name: Check vulnerable packages
|
|
445
|
+
run: dotnet list package --vulnerable --include-transitive
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**Production Deployment** (`cd-prod.yml.hbs`):
|
|
449
|
+
```yaml
|
|
450
|
+
name: Deploy to Production
|
|
451
|
+
|
|
452
|
+
on:
|
|
453
|
+
push:
|
|
454
|
+
branches: [main]
|
|
455
|
+
|
|
456
|
+
jobs:
|
|
457
|
+
build:
|
|
458
|
+
uses: ./.github/workflows/dotnet-build.yml
|
|
459
|
+
with:
|
|
460
|
+
dotnet-version: '{{DOTNET_VERSION}}'
|
|
461
|
+
secrets: inherit
|
|
462
|
+
|
|
463
|
+
deploy:
|
|
464
|
+
needs: build
|
|
465
|
+
uses: ./.github/workflows/deploy-azure-app-service.yml
|
|
466
|
+
with:
|
|
467
|
+
environment: 'production'
|
|
468
|
+
resource-group: 'rg-{{kebabCase APP_NAME}}-prod'
|
|
469
|
+
app-service-name: 'app-{{kebabCase APP_NAME}}-prod'
|
|
470
|
+
secrets: inherit
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Stack-Specific Overrides
|
|
474
|
+
|
|
475
|
+
Stack-specific workflow templates in:
|
|
476
|
+
- `stacks/blazor-azure/.morph/framework/templates/infrastructure/github/workflows/`
|
|
477
|
+
- `stacks/nextjs-supabase/.morph/framework/templates/infrastructure/github/workflows/`
|
|
478
|
+
|
|
479
|
+
**Resolution Order:**
|
|
480
|
+
1. Project-local: `.morph/framework/templates/infrastructure/github/workflows/ci-build.yml.hbs`
|
|
481
|
+
2. Stack default: `stacks/{stack}/.morph/framework/templates/infrastructure/github/workflows/ci-build.yml.hbs`
|
|
482
|
+
3. Framework fallback: `framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs`
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## 🔀 Stack Override Mechanism
|
|
487
|
+
|
|
488
|
+
**Resolution Order:**
|
|
489
|
+
|
|
490
|
+
1. **Stack-specific override** (highest priority)
|
|
491
|
+
- `stacks/{stack}/.morph/framework/templates/code/dotnet/backend/service.cs`
|
|
492
|
+
|
|
493
|
+
2. **Project-local override** (medium priority)
|
|
494
|
+
- `.morph/framework/templates/code/dotnet/backend/service.cs`
|
|
495
|
+
|
|
496
|
+
3. **Framework template** (fallback)
|
|
497
|
+
- `framework/templates/code/dotnet/backend/service.cs`
|
|
498
|
+
|
|
499
|
+
**Use Cases for Overrides:**
|
|
500
|
+
|
|
501
|
+
| Scenario | Override Location | Example |
|
|
502
|
+
|----------|-------------------|---------|
|
|
503
|
+
| Stack-specific tweak | `stacks/{stack}/.morph/framework/templates/` | Blazor uses different DI pattern |
|
|
504
|
+
| Project-wide customization | `.morph/framework/templates/` | Company-specific code style |
|
|
505
|
+
| Use framework default | None (no override) | Standard templates work fine |
|
|
506
|
+
|
|
507
|
+
**Example:**
|
|
508
|
+
|
|
509
|
+
```bash
|
|
510
|
+
# Create stack override for Blazor
|
|
511
|
+
morph-spec template customize dotnet-backend-service --stack blazor-azure
|
|
512
|
+
|
|
513
|
+
# Edit the override
|
|
514
|
+
code stacks/blazor-azure/.morph/framework/templates/code/dotnet/backend/service.cs
|
|
515
|
+
|
|
516
|
+
# Now all renders for blazor-azure will use the override
|
|
517
|
+
morph-spec template render dotnet-backend-service UserService.cs '...' --stack blazor-azure
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
## 📊 Template Registry (REGISTRY.json)
|
|
523
|
+
|
|
524
|
+
The `REGISTRY.json` file is the **single source of truth** for all template metadata.
|
|
525
|
+
|
|
526
|
+
### Schema
|
|
527
|
+
|
|
528
|
+
```json
|
|
529
|
+
{
|
|
530
|
+
"version": "2.0.0",
|
|
531
|
+
"templates": [
|
|
532
|
+
{
|
|
533
|
+
"id": "dotnet-backend-service",
|
|
534
|
+
"name": ".NET Service Class",
|
|
535
|
+
"path": "code/dotnet/backend/service.cs",
|
|
536
|
+
"location": "framework",
|
|
537
|
+
"category": "code",
|
|
538
|
+
"phase": "implement",
|
|
539
|
+
"required": false,
|
|
540
|
+
"technology": "dotnet",
|
|
541
|
+
"applicableStacks": ["blazor-azure", "nextjs-supabase"],
|
|
542
|
+
"engine": "handlebars",
|
|
543
|
+
"placeholders": ["FEATURE_NAME", "NAMESPACE"],
|
|
544
|
+
"outputName": "{FeatureName}Service.cs",
|
|
545
|
+
"deprecated": false
|
|
546
|
+
}
|
|
547
|
+
]
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Discovery API
|
|
552
|
+
|
|
553
|
+
```javascript
|
|
554
|
+
import {
|
|
555
|
+
getAllTemplates,
|
|
556
|
+
getTemplateById,
|
|
557
|
+
getTemplatesByCategory,
|
|
558
|
+
getTemplatesByTechnology,
|
|
559
|
+
resolveTemplatePathById
|
|
560
|
+
} from '../src/lib/template-registry.js';
|
|
561
|
+
|
|
562
|
+
// Get all templates
|
|
563
|
+
const all = getAllTemplates();
|
|
564
|
+
|
|
565
|
+
// Get specific template
|
|
566
|
+
const service = getTemplateById('dotnet-backend-service');
|
|
567
|
+
|
|
568
|
+
// Filter by category
|
|
569
|
+
const codeTemplates = getTemplatesByCategory('code');
|
|
570
|
+
|
|
571
|
+
// Filter by technology
|
|
572
|
+
const dotnetTemplates = getTemplatesByTechnology('dotnet');
|
|
573
|
+
|
|
574
|
+
// Resolve path with fallback
|
|
575
|
+
const path = resolveTemplatePathById('dotnet-backend-service', '/project', 'blazor-azure');
|
|
576
|
+
// Returns: framework/templates/code/dotnet/backend/service.cs
|
|
577
|
+
// Or: stacks/blazor-azure/.morph/framework/templates/code/dotnet/backend/service.cs (if override exists)
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## 🚀 Creating New Templates
|
|
583
|
+
|
|
584
|
+
### 1. Create Template File
|
|
585
|
+
|
|
586
|
+
```bash
|
|
587
|
+
# For .NET templates
|
|
588
|
+
touch framework/templates/code/dotnet/backend/my-template.cs
|
|
589
|
+
|
|
590
|
+
# For infrastructure templates
|
|
591
|
+
touch framework/templates/infrastructure/azure/my-resource.bicep
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### 2. Add Handlebars Placeholders
|
|
595
|
+
|
|
596
|
+
```handlebars
|
|
597
|
+
namespace {{pascalCase NAMESPACE}};
|
|
598
|
+
|
|
599
|
+
public class {{pascalCase FEATURE_NAME}}Service
|
|
600
|
+
{
|
|
601
|
+
// TODO: Implement {{titleCase FEATURE_NAME}} logic
|
|
602
|
+
}
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### 3. Register in REGISTRY.json
|
|
606
|
+
|
|
607
|
+
```json
|
|
608
|
+
{
|
|
609
|
+
"id": "dotnet-backend-my-template",
|
|
610
|
+
"name": "My Custom Template",
|
|
611
|
+
"path": "code/dotnet/backend/my-template.cs",
|
|
612
|
+
"location": "framework",
|
|
613
|
+
"category": "code",
|
|
614
|
+
"phase": "implement",
|
|
615
|
+
"required": false,
|
|
616
|
+
"technology": "dotnet",
|
|
617
|
+
"applicableStacks": ["blazor-azure"],
|
|
618
|
+
"engine": "handlebars",
|
|
619
|
+
"placeholders": ["FEATURE_NAME", "NAMESPACE"],
|
|
620
|
+
"outputName": "{FeatureName}MyTemplate.cs",
|
|
621
|
+
"deprecated": false
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### 4. Test Rendering
|
|
626
|
+
|
|
627
|
+
```bash
|
|
628
|
+
morph-spec template render dotnet-backend-my-template output.cs '{
|
|
629
|
+
"FEATURE_NAME": "user-auth",
|
|
630
|
+
"NAMESPACE": "MyApp.Services"
|
|
631
|
+
}'
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
## 📦 Migration Guide: v1 → v2
|
|
637
|
+
|
|
638
|
+
### What Changed
|
|
639
|
+
|
|
640
|
+
| Aspect | v1 (Stack-Based) | v2 (Technology-Based) |
|
|
641
|
+
|--------|------------------|----------------------|
|
|
642
|
+
| **Location** | `stacks/{stack}/.morph/framework/templates/` | `framework/templates/{technology}/` |
|
|
643
|
+
| **Organization** | By stack (blazor-azure, nextjs-supabase) | By technology (dotnet, azure, docker) |
|
|
644
|
+
| **Duplication** | High (proposal.md × 2, decisions.md × 2) | Low (shared templates in framework) |
|
|
645
|
+
| **Template Engine** | 3 engines (custom, Handlebars, mixed) | 1 engine (Handlebars with helpers) |
|
|
646
|
+
| **Pre-computed Variables** | `{{pascalCase FEATURE_NAME}}` | `{{pascalCase FEATURE_NAME}}` (helpers) |
|
|
647
|
+
| **Registry** | None (hardcoded paths) | `REGISTRY.json` (centralized metadata) |
|
|
648
|
+
| **CLI** | None | `morph-spec template list/show/render/customize` |
|
|
649
|
+
| **Future Stacks** | Must copy templates | Reuse existing technology templates |
|
|
650
|
+
|
|
651
|
+
### Breaking Changes
|
|
652
|
+
|
|
653
|
+
**1. Template Paths**
|
|
654
|
+
|
|
655
|
+
```diff
|
|
656
|
+
- stacks/blazor-azure/.morph/framework/templates/service.cs
|
|
657
|
+
+ framework/templates/code/dotnet/backend/service.cs
|
|
658
|
+
|
|
659
|
+
- stacks/blazor-azure/.morph/framework/templates/infra/main.bicep
|
|
660
|
+
+ framework/templates/infrastructure/azure/main.bicep
|
|
661
|
+
|
|
662
|
+
- stacks/nextjs-supabase/.morph/framework/templates/dockerfile-web.dockerfile
|
|
663
|
+
+ framework/templates/infrastructure/docker/dockerfile-web.dockerfile
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
**2. Pre-computed Variables**
|
|
667
|
+
|
|
668
|
+
```diff
|
|
669
|
+
- {{pascalCase FEATURE_NAME}}
|
|
670
|
+
+ {{pascalCase FEATURE_NAME}}
|
|
671
|
+
|
|
672
|
+
- {{camelCase FEATURE_NAME}}
|
|
673
|
+
+ {{camelCase FEATURE_NAME}}
|
|
674
|
+
|
|
675
|
+
- {{snakeCase FEATURE_NAME}}
|
|
676
|
+
+ {{snakeCase FEATURE_NAME}}
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
**3. Template Resolution**
|
|
680
|
+
|
|
681
|
+
```javascript
|
|
682
|
+
// Old (v1)
|
|
683
|
+
const templatePath = join(resolveTemplatesDir(projectPath), 'service.cs');
|
|
684
|
+
|
|
685
|
+
// New (v2)
|
|
686
|
+
const templatePath = resolveTemplatePath(projectPath, 'code/dotnet/backend/service.cs', stackId);
|
|
687
|
+
// Automatically falls back: stack override → framework
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
### Migration Steps
|
|
691
|
+
|
|
692
|
+
**Step 1:** Update code to use `resolveTemplatePath()`
|
|
693
|
+
|
|
694
|
+
```javascript
|
|
695
|
+
import { resolveTemplatePath } from '../lib/stack-resolver.js';
|
|
696
|
+
|
|
697
|
+
// Before
|
|
698
|
+
const path = join(resolveTemplatesDir(process.cwd()), 'service.cs');
|
|
699
|
+
|
|
700
|
+
// After
|
|
701
|
+
const path = resolveTemplatePath(process.cwd(), 'code/dotnet/backend/service.cs', 'blazor-azure');
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
**Step 2:** Update template syntax to Handlebars
|
|
705
|
+
|
|
706
|
+
```handlebars
|
|
707
|
+
<!-- Before -->
|
|
708
|
+
namespace {{NAMESPACE}};
|
|
709
|
+
public class {{pascalCase FEATURE_NAME}}Service { }
|
|
710
|
+
|
|
711
|
+
<!-- After -->
|
|
712
|
+
namespace {{pascalCase NAMESPACE}};
|
|
713
|
+
public class {{pascalCase FEATURE_NAME}}Service { }
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
**Step 3:** Use CLI commands instead of hardcoded paths
|
|
717
|
+
|
|
718
|
+
```bash
|
|
719
|
+
# Before (hardcoded)
|
|
720
|
+
cp framework/templates/proposal.md .morph/features/user-auth/proposal.md
|
|
721
|
+
|
|
722
|
+
# After (CLI)
|
|
723
|
+
morph-spec template render proposal .morph/features/user-auth/proposal.md '{
|
|
724
|
+
"FEATURE_NAME": "user-auth"
|
|
725
|
+
}'
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
730
|
+
## 🎯 Best Practices
|
|
731
|
+
|
|
732
|
+
### 1. **Use Helpers, Not Pre-computed Variables**
|
|
733
|
+
|
|
734
|
+
```handlebars
|
|
735
|
+
✅ GOOD:
|
|
736
|
+
{{pascalCase FEATURE_NAME}}Service
|
|
737
|
+
|
|
738
|
+
❌ BAD:
|
|
739
|
+
{{pascalCase FEATURE_NAME}}Service // Deprecated, won't work
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
### 2. **Keep Templates Technology-Agnostic**
|
|
743
|
+
|
|
744
|
+
```handlebars
|
|
745
|
+
✅ GOOD: code/dotnet/backend/service.cs
|
|
746
|
+
Works for: blazor-azure, nextjs-supabase, future-dotnet-stack
|
|
747
|
+
|
|
748
|
+
❌ BAD: code/blazor/service.cs
|
|
749
|
+
Locked to Blazor only
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
### 3. **Use Stack Conditionals for Differences**
|
|
753
|
+
|
|
754
|
+
```handlebars
|
|
755
|
+
{{#if (eq STACK "blazor-azure")}}
|
|
756
|
+
// Azure-specific implementation
|
|
757
|
+
{{else if (eq STACK "nextjs-supabase")}}
|
|
758
|
+
// Supabase-specific implementation
|
|
759
|
+
{{else}}
|
|
760
|
+
// Generic implementation
|
|
761
|
+
{{/if}}
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
### 4. **Document Applicability in Registry**
|
|
765
|
+
|
|
766
|
+
```json
|
|
767
|
+
{
|
|
768
|
+
"technology": "dotnet",
|
|
769
|
+
"applicableStacks": ["blazor-azure", "nextjs-supabase"],
|
|
770
|
+
"description": "Works with any .NET backend stack"
|
|
771
|
+
}
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
### 5. **Override Only When Necessary**
|
|
775
|
+
|
|
776
|
+
```bash
|
|
777
|
+
# Only customize if framework template doesn't meet needs
|
|
778
|
+
morph-spec template customize dotnet-backend-service --stack blazor-azure
|
|
779
|
+
|
|
780
|
+
# Otherwise, use framework version (gets updates automatically)
|
|
781
|
+
morph-spec template render dotnet-backend-service output.cs '...'
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
---
|
|
785
|
+
|
|
786
|
+
## 📚 References
|
|
787
|
+
|
|
788
|
+
- **Template Registry API:** [`src/lib/template-registry.js`](../../src/lib/template-registry.js)
|
|
789
|
+
- **Template Renderer:** [`src/lib/template-renderer.js`](../../src/lib/template-renderer.js)
|
|
790
|
+
- **Stack Resolver:** [`src/lib/stack-resolver.js`](../../src/lib/stack-resolver.js)
|
|
791
|
+
- **CLI Commands:** [`src/commands/template-*.js`](../../src/commands/)
|
|
792
|
+
- **Handlebars Docs:** https://handlebarsjs.com/
|
|
793
|
+
|
|
794
|
+
---
|
|
795
|
+
|
|
796
|
+
## 🤝 Contributing
|
|
797
|
+
|
|
798
|
+
### Adding New Technology
|
|
799
|
+
|
|
800
|
+
1. Create directory: `framework/templates/code/{technology}/`
|
|
801
|
+
2. Add templates with Handlebars syntax
|
|
802
|
+
3. Register in `REGISTRY.json` with `"technology": "{technology}"`
|
|
803
|
+
4. Test with `morph-spec template render`
|
|
804
|
+
5. Document in this README
|
|
805
|
+
|
|
806
|
+
### Deprecating Templates
|
|
807
|
+
|
|
808
|
+
1. Add `"deprecated": true` to `REGISTRY.json`
|
|
809
|
+
2. Add `"deprecationReason": "Reason here"`
|
|
810
|
+
3. Keep file for backward compatibility or remove after major version bump
|
|
811
|
+
|
|
812
|
+
---
|
|
813
|
+
|
|
814
|
+
**MORPH-SPEC Template System v2.0** - Technology-Based, Future-Proof, DRY ✨
|