@polymorphism-tech/morph-spec 7.2.0 β†’ 7.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.
Files changed (61) hide show
  1. package/README.md +2 -2
  2. package/claude-plugin.json +1 -1
  3. package/docs/CHEATSHEET.md +1 -1
  4. package/docs/QUICKSTART.md +1 -1
  5. package/framework/CLAUDE.md +1 -1
  6. package/framework/commands/morph-apply.md +1 -1
  7. package/framework/commands/morph-proposal.md +1 -1
  8. package/framework/hooks/README.md +1 -1
  9. package/framework/hooks/claude-code/core/validate-completion.js +136 -136
  10. package/framework/phases.json +1 -1
  11. package/framework/skills/README.md +1 -1
  12. package/framework/skills/core/morph-apply/SKILL.md +1 -1
  13. package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
  14. package/framework/skills/core/morph-eval/SKILL.md +1 -1
  15. package/framework/skills/core/morph-implement/SKILL.md +1 -1
  16. package/framework/skills/core/morph-plan/SKILL.md +1 -1
  17. package/framework/skills/core/morph-proposal/SKILL.md +1 -1
  18. package/framework/skills/core/morph-review/SKILL.md +1 -1
  19. package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
  20. package/framework/skills/core/morph-standards/SKILL.md +1 -1
  21. package/framework/templates/README.md +708 -709
  22. package/framework/templates/REGISTRY.json +1 -20
  23. package/framework/templates/context/CONTEXT-FEATURE.md +276 -276
  24. package/framework/templates/docs/proposal.md +171 -171
  25. package/framework/templates/feature/recap.md +145 -145
  26. package/package.json +1 -1
  27. package/src/commands/project/doctor.js +941 -946
  28. package/src/commands/project/status.js +373 -376
  29. package/src/commands/validation/validate-feature.js +315 -287
  30. package/src/core/state/state-manager.js +900 -934
  31. package/src/dashboard/app/App.jsx +29 -31
  32. package/src/dashboard/app/components/Sidebar.jsx +44 -45
  33. package/src/dashboard/scanner/index.js +20 -21
  34. package/src/lib/context/context-builder.js +3 -3
  35. package/src/lib/generators/context-generator.js +2 -3
  36. package/src/lib/generators/mandate-generator.js +48 -92
  37. package/src/lib/generators/metadata-extractor.js +385 -386
  38. package/src/lib/generators/recap-generator.js +285 -285
  39. package/src/lib/validators/content/content-validator.js +89 -286
  40. package/src/lib/validators/content/index.js +0 -1
  41. package/framework/templates/feature/tasks.md +0 -199
  42. package/framework/workflows/README.md +0 -1041
  43. package/framework/workflows/configs/fast-track.json +0 -46
  44. package/framework/workflows/configs/full.json +0 -64
  45. package/framework/workflows/configs/quick.json +0 -32
  46. package/framework/workflows/configs/standard.json +0 -57
  47. package/framework/workflows/docs/STORY-DRIVEN-DEVELOPMENT.md +0 -392
  48. package/framework/workflows/docs/design-impl.md +0 -37
  49. package/framework/workflows/docs/enforcement-pipeline.md +0 -668
  50. package/framework/workflows/docs/fast-track.md +0 -29
  51. package/framework/workflows/docs/full-morph.md +0 -69
  52. package/framework/workflows/docs/standard.md +0 -49
  53. package/framework/workflows/docs/ui-refresh.md +0 -39
  54. package/src/commands/state/index.js +0 -7
  55. package/src/core/workflows/workflow-detector.js +0 -586
  56. package/src/core/workflows/workflow-router.js +0 -204
  57. package/src/dashboard/app/pages/Workflows.jsx +0 -346
  58. package/src/dashboard/scanner/workflows-scanner.js +0 -18
  59. package/src/lib/phase-chain/phase-validator.js +0 -359
  60. package/src/lib/validators/content/cross-phase-validator.js +0 -281
  61. package/src/lib/validators/spec-validator.js +0 -312
@@ -1,709 +1,708 @@
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, 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
- β”‚ β”‚ β”œβ”€β”€ database/
37
- β”‚ β”‚ β”‚ └── migration.cs # EF Core migrations
38
- β”‚ β”‚ β”œβ”€β”€ jobs/
39
- β”‚ β”‚ β”‚ β”œβ”€β”€ job.cs # Hangfire background jobs
40
- β”‚ β”‚ β”‚ └── agent.cs # MS Agent Framework agents
41
- β”‚ β”‚ └── contracts/
42
- β”‚ β”‚ β”œβ”€β”€ contracts.cs # Base contracts
43
- β”‚ β”‚ β”œβ”€β”€ Commands.cs # CQRS commands
44
- β”‚ β”‚ β”œβ”€β”€ Queries.cs # CQRS queries
45
- β”‚ β”‚ β”œβ”€β”€ Entities.cs # Domain entities
46
- β”‚ β”‚ β”œβ”€β”€ api-contracts.cs # API contracts
47
- β”‚ β”‚ └── README.md # Contracts documentation
48
- β”‚ β”‚
49
- β”‚ β”œβ”€β”€ typescript/
50
- β”‚ β”‚ └── contracts.ts # TypeScript type definitions
51
- β”‚ β”‚
52
- β”‚ └── sql/
53
- β”‚ β”œβ”€β”€ postgresql-migration.sql # Basic migration
54
- β”‚ β”œβ”€β”€ postgresql-migration.template.sql # Enhanced migration
55
- β”‚ └── postgresql-rls-policy.sql # Row-level security
56
- β”‚
57
- β”œβ”€β”€ infrastructure/
58
- β”‚ β”œβ”€β”€ docker/ # Docker & EasyPanel
59
- β”‚ β”‚ β”œβ”€β”€ dockerfile-api.dockerfile # .NET API
60
- β”‚ β”‚ β”œβ”€β”€ dockerfile-web.dockerfile # Next.js web
61
- β”‚ β”‚ β”œβ”€β”€ Dockerfile.template # Generic
62
- β”‚ β”‚ β”œβ”€β”€ docker-compose.template.yml # Compose
63
- β”‚ β”‚ └── easypanel.template.json # EasyPanel config
64
- β”‚ β”‚
65
- β”‚ └── github/ # GitHub Actions CI/CD
66
- β”‚ β”œβ”€β”€ workflows/ # Reusable workflow templates
67
- β”‚ β”‚ β”œβ”€β”€ dotnet-build.yml.hbs # .NET restore, build, test
68
- β”‚ β”‚ β”œβ”€β”€ docker-build-push.yml.hbs # Docker build & push
69
- β”‚ β”‚ └── deploy-easypanel.yml.hbs # EasyPanel deployment
70
- β”‚ β”‚
71
- β”‚ β”œβ”€β”€ actions/ # Composite action templates
72
- β”‚ β”‚ β”œβ”€β”€ docker-build-push/action.yml.hbs
73
- β”‚ β”‚ └── health-check/action.yml.hbs
74
- β”‚ β”‚
75
- β”‚ └── README.md # GitHub Actions docs
76
- β”‚
77
- β”œβ”€β”€ integrations/ # Platform-agnostic integrations
78
- β”‚ β”œβ”€β”€ asaas-client.cs # Asaas financial API
79
- β”‚ β”œβ”€β”€ asaas-webhook.cs # Asaas webhooks
80
- β”‚ └── neon-auth-config.cs # Neon Auth (Better Auth)
81
- β”‚
82
- β”œβ”€β”€ ui/ # Design systems
83
- β”‚ └── design-system.css # CSS tokens
84
- β”‚
85
- β”œβ”€β”€ saas/ # Multi-tenant patterns
86
- β”‚
87
- β”œβ”€β”€ examples/ # Reference implementations
88
- β”‚ β”œβ”€β”€ spec-examples.md # Example specs
89
- β”‚ └── design-system-examples.md # Design system examples
90
- β”‚
91
- └── REGISTRY.json # Template metadata registry
92
- ```
93
-
94
- ---
95
-
96
- ## πŸ—οΈ Technology-Based Architecture
97
-
98
- **Why organize by technology instead of by stack?**
99
-
100
- | Organization | Pros | Cons | Best For |
101
- |--------------|------|------|----------|
102
- | **By Stack** (old v1) | Stack-specific optimizations | Duplicate templates, hard to reuse | Single-stack projects |
103
- | **By Technology** (new v2) | Reusable, DRY, future-proof | Requires stack override mechanism | Multi-stack frameworks |
104
-
105
- **Example:** A `.NET service.cs` template works for both `dotnet-nextjs` and `nextjs-neon` stacks (both use .NET backend). No need to duplicate!
106
-
107
- **Future-proof:** When we create `vue-firebase` stack, we can reuse:
108
- - `code/typescript/` templates
109
- - `infrastructure/docker/` templates
110
- - `integrations/` templates (Neon Auth, etc.)
111
-
112
- **Only create NEW templates for Vue-specific code.**
113
-
114
- ---
115
-
116
- ## βš™οΈ Template Engine: Handlebars
117
-
118
- All templates use **Handlebars** with **20+ custom helpers**.
119
-
120
- ### Basic Syntax
121
-
122
- ```handlebars
123
- # Feature: {{titleCase FEATURE_NAME}}
124
-
125
- Namespace: {{pascalCase FEATURE_NAME}}
126
-
127
- Created: {{DATE}}
128
- ```
129
-
130
- ### Available Helpers
131
-
132
- | Helper | Input | Output | Usage |
133
- |--------|-------|--------|-------|
134
- | `{{pascalCase str}}` | `user-profile` | `UserProfile` | Class names |
135
- | `{{camelCase str}}` | `user-profile` | `userProfile` | Variable names |
136
- | `{{snakeCase str}}` | `user-profile` | `user_profile` | SQL tables |
137
- | `{{upperSnakeCase str}}` | `user-profile` | `USER_PROFILE` | Constants |
138
- | `{{titleCase str}}` | `user-profile` | `User Profile` | Titles |
139
- | `{{kebabCase str}}` | `User Profile` | `user-profile` | URLs |
140
- | `{{pluralize str}}` | `user` | `users` | Collections |
141
- | `{{singularize str}}` | `users` | `user` | Entities |
142
- | `{{eq a b}}` | `"nextjs" "nextjs"` | `true` | Conditionals |
143
- | `{{or a b}}` | `false true` | `true` | Logical OR |
144
- | `{{and a b}}` | `true false` | `false` | Logical AND |
145
- | `{{default val fallback}}` | `null "default"` | `"default"` | Defaults |
146
-
147
- ### Conditional Logic
148
-
149
- ```handlebars
150
- {{#if (eq STACK "nextjs-neon")}}
151
- // Neon-specific code
152
- {{else}}
153
- // Generic code
154
- {{/if}}
155
- ```
156
-
157
- ### Deprecated: Pre-computed Variables
158
-
159
- **❌ Old (v1):**
160
- ```handlebars
161
- {{pascalCase FEATURE_NAME}} <!-- Pre-computed in bin/render-template.js -->
162
- ```
163
-
164
- **βœ… New (v2):**
165
- ```handlebars
166
- {{pascalCase FEATURE_NAME}} <!-- Computed via Handlebars helper -->
167
- ```
168
-
169
- ---
170
-
171
- ## πŸ› οΈ CLI Commands
172
-
173
- ### List All Templates
174
-
175
- ```bash
176
- # List all templates
177
- morph-spec template list
178
-
179
- # Filter by category
180
- morph-spec template list --category code
181
- morph-spec template list --category infrastructure
182
-
183
- # Filter by phase
184
- morph-spec template list --phase implement
185
-
186
- # Filter by stack applicability
187
- morph-spec template list --stack dotnet-nextjs
188
-
189
- # Show only required templates
190
- morph-spec template list --required
191
- ```
192
-
193
- **Output:**
194
- ```
195
- πŸ“¦ Universal Templates (9)
196
- proposal Feature Proposal [REQUIRED] [UNIVERSAL] [HBS]
197
- spec Technical Specification [REQUIRED] [UNIVERSAL] [HBS]
198
- tasks Implementation Tasks [REQUIRED] [UNIVERSAL] [HBS]
199
- ...
200
-
201
- πŸ“¦ Technology-Based Templates (48)
202
- dotnet-backend-service .NET Service Class [UNIVERSAL] [HBS] (dotnet)
203
- typescript-contracts TypeScript Contracts [UNIVERSAL] [HBS] (typescript)
204
- ...
205
- ```
206
-
207
- ### Show Template Details
208
-
209
- ```bash
210
- # Show metadata
211
- morph-spec template show dotnet-backend-service
212
-
213
- # Show with file preview
214
- morph-spec template show dotnet-backend-service --preview
215
-
216
- # Show with resolved path
217
- morph-spec template show dotnet-backend-service --show-path
218
- ```
219
-
220
- **Output:**
221
- ```
222
- Template: dotnet-backend-service
223
-
224
- πŸ“‹ Metadata
225
- ID: dotnet-backend-service
226
- Name: .NET Service Class
227
- Path: code/dotnet/backend/service.cs
228
- Location: framework
229
- Category: code
230
- Phase: implement
231
- Required: No
232
- Technology: dotnet
233
- Applicable Stacks: dotnet-nextjs, nextjs-neon
234
-
235
- πŸ“ Description
236
- C# service class template with dependency injection and interface pattern
237
-
238
- πŸ”‘ Variables
239
- {{FEATURE_NAME}}
240
- {{NAMESPACE}}
241
-
242
- πŸ“„ Output Name
243
- {FeatureName}Service.cs
244
-
245
- πŸ’‘ Usage Hint
246
- morph-spec template render dotnet-backend-service output.cs '{"FEATURE_NAME":"user-auth","NAMESPACE":"MyApp"}'
247
- ```
248
-
249
- ### Render Template
250
-
251
- ```bash
252
- # Render to file
253
- morph-spec template render dotnet-backend-service UserAuthService.cs '{
254
- "FEATURE_NAME": "user-auth",
255
- "NAMESPACE": "MyApp.Services"
256
- }'
257
-
258
- # Dry run (preview only)
259
- morph-spec template render dotnet-backend-service output.cs '{"FEATURE_NAME":"test"}' --dry-run
260
-
261
- # Auto-resolve path (searches framework β†’ stack override)
262
- morph-spec template render proposal proposal.md '{"FEATURE_NAME":"auth"}' --resolve-path
263
- ```
264
-
265
- **Default Variables (auto-injected):**
266
- - `DATE`: `2026-02-17`
267
- - `YEAR`: `2026`
268
- - `TIMESTAMP`: `2026-02-17T19:38:00.000Z`
269
-
270
- ### Customize Template (Stack Override)
271
-
272
- ```bash
273
- # Copy to stack-specific directory (override framework version)
274
- morph-spec template customize dotnet-backend-service --stack dotnet-nextjs
275
-
276
- # Copy to project-local (cross-stack override)
277
- morph-spec template customize dotnet-backend-service --local
278
-
279
- # Force overwrite if exists
280
- morph-spec template customize dotnet-backend-service --stack dotnet-nextjs --force
281
- ```
282
-
283
- **Output:**
284
- ```
285
- Source: framework/templates/code/dotnet/backend/service.cs
286
- Destination: stacks/dotnet-nextjs/.morph/framework/templates/code/dotnet/backend/service.cs
287
-
288
- βœ… Template copied for customization
289
-
290
- πŸ“ Next Steps
291
- 1. Edit the template file:
292
- stacks/dotnet-nextjs/.morph/framework/templates/code/dotnet/backend/service.cs
293
-
294
- 2. Template will now be used instead of framework version
295
- (Stack-specific templates take precedence)
296
-
297
- 3. Test rendering:
298
- morph-spec template render dotnet-backend-service output.cs '{"FEATURE_NAME":"test"}'
299
-
300
- ⚠️ Customized templates won't receive framework updates
301
- To get updates: delete customized version and re-run this command
302
- ```
303
-
304
- ---
305
-
306
- ## πŸ”„ GitHub Actions Templates
307
-
308
- The framework provides reusable GitHub Actions workflows and composite actions for CI/CD automation.
309
-
310
- ### Structure
311
-
312
- ```
313
- infrastructure/github/
314
- β”œβ”€β”€ workflows/ # Reusable workflow templates
315
- β”‚ β”œβ”€β”€ dotnet-build.yml.hbs # .NET restore, build, test
316
- β”‚ β”œβ”€β”€ docker-build-push.yml.hbs # Docker build & push
317
- β”‚ └── deploy-easypanel.yml.hbs # EasyPanel deployment
318
- β”‚
319
- └── actions/ # Composite action templates
320
- β”œβ”€β”€ docker-build-push/action.yml.hbs
321
- └── health-check/action.yml.hbs
322
- ```
323
-
324
- ### Reusable Workflows vs Composite Actions
325
-
326
- | Type | Purpose | Location | Usage |
327
- |------|---------|----------|-------|
328
- | **Reusable Workflows** | Complete CI/CD pipelines (multi-job) | `workflows/*.yml.hbs` | Called via `uses:` from stack workflows |
329
- | **Composite Actions** | Reusable step logic (single responsibility) | `actions/*/action.yml.hbs` | Called via `uses:` in workflow steps |
330
-
331
- ### Deployment Strategy Difference
332
-
333
- **NextJS-Neon:** Docker containers to EasyPanel
334
- - `docker build` β†’ `docker push` β†’ EasyPanel webhook
335
- - Multi-service deployment (API + Web)
336
- - Registry: GitHub Container Registry (ghcr.io)
337
-
338
- ### Template Rendering
339
-
340
- **GitHub Actions Constraint:**
341
- - ❌ GitHub Actions CANNOT reference parent directories (`../../../../framework/`)
342
- - βœ… Solution: Framework templates are **rendered** into each stack's `.github/` directory
343
- - Rendered `.yml` files are **committed** to repos (not `.yml.hbs` templates)
344
-
345
- **Rendering Process:**
346
- ```bash
347
- # Render all GitHub Actions templates for a stack (manual for now)
348
- # Future: morph-spec template render github-workflows --stack dotnet-nextjs
349
- ```
350
-
351
- ### Handlebars Variables
352
-
353
- - `{{APP_NAME}}` - Application name from config.json
354
- - `{{DOTNET_VERSION}}` - .NET SDK version
355
- - `{{GITHUB_OWNER}}` - GitHub organization/user
356
- - `{{kebabCase APP_NAME}}` - Docker image name format
357
- - `${{{{ inputs.* }}}}` - GitHub Actions runtime syntax (escaped with `{{{{raw}}}}`)
358
-
359
- ### Authentication & Secrets
360
-
361
- **Docker Registry (NextJS-Neon):**
362
- ```yaml
363
- # GitHub Container Registry (ghcr.io)
364
- - uses: docker/login-action@v3
365
- with:
366
- registry: ghcr.io
367
- username: ${{{{ github.actor }}}}
368
- password: ${{{{ secrets.GITHUB_TOKEN }}}}
369
- ```
370
-
371
- **GitHub Secrets to Configure:**
372
- - NextJS-Neon: `GITHUB_TOKEN` (auto), `EASYPANEL_API_TOKEN`
373
-
374
- ### Stack-Specific Overrides
375
-
376
- Stack-specific workflow templates in:
377
- - `stacks/nextjs-neon/.morph/framework/templates/infrastructure/github/workflows/`
378
-
379
- **Resolution Order:**
380
- 1. Project-local: `.morph/framework/templates/infrastructure/github/workflows/ci-build.yml.hbs`
381
- 2. Stack default: `stacks/{stack}/.morph/framework/templates/infrastructure/github/workflows/ci-build.yml.hbs`
382
- 3. Framework fallback: `framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs`
383
-
384
- ---
385
-
386
- ## πŸ”€ Stack Override Mechanism
387
-
388
- **Resolution Order:**
389
-
390
- 1. **Stack-specific override** (highest priority)
391
- - `stacks/{stack}/.morph/framework/templates/code/dotnet/backend/service.cs`
392
-
393
- 2. **Project-local override** (medium priority)
394
- - `.morph/framework/templates/code/dotnet/backend/service.cs`
395
-
396
- 3. **Framework template** (fallback)
397
- - `framework/templates/code/dotnet/backend/service.cs`
398
-
399
- **Use Cases for Overrides:**
400
-
401
- | Scenario | Override Location | Example |
402
- |----------|-------------------|---------|
403
- | Stack-specific tweak | `stacks/{stack}/.morph/framework/templates/` | Stack uses different DI pattern |
404
- | Project-wide customization | `.morph/framework/templates/` | Company-specific code style |
405
- | Use framework default | None (no override) | Standard templates work fine |
406
-
407
- **Example:**
408
-
409
- ```bash
410
- # Create stack override
411
- morph-spec template customize dotnet-backend-service --stack dotnet-nextjs
412
-
413
- # Edit the override
414
- code stacks/dotnet-nextjs/.morph/framework/templates/code/dotnet/backend/service.cs
415
-
416
- # Now all renders for dotnet-nextjs will use the override
417
- morph-spec template render dotnet-backend-service UserService.cs '...' --stack dotnet-nextjs
418
- ```
419
-
420
- ---
421
-
422
- ## πŸ“Š Template Registry (REGISTRY.json)
423
-
424
- The `REGISTRY.json` file is the **single source of truth** for all template metadata.
425
-
426
- ### Schema
427
-
428
- ```json
429
- {
430
- "version": "2.0.0",
431
- "templates": [
432
- {
433
- "id": "dotnet-backend-service",
434
- "name": ".NET Service Class",
435
- "path": "code/dotnet/backend/service.cs",
436
- "location": "framework",
437
- "category": "code",
438
- "phase": "implement",
439
- "required": false,
440
- "technology": "dotnet",
441
- "applicableStacks": ["dotnet-nextjs", "nextjs-neon"],
442
- "engine": "handlebars",
443
- "placeholders": ["FEATURE_NAME", "NAMESPACE"],
444
- "outputName": "{FeatureName}Service.cs",
445
- "deprecated": false
446
- }
447
- ]
448
- }
449
- ```
450
-
451
- ### Discovery API
452
-
453
- ```javascript
454
- import {
455
- getAllTemplates,
456
- getTemplateById,
457
- getTemplatesByCategory,
458
- getTemplatesByTechnology,
459
- resolveTemplatePathById
460
- } from '../src/lib/template-registry.js';
461
-
462
- // Get all templates
463
- const all = getAllTemplates();
464
-
465
- // Get specific template
466
- const service = getTemplateById('dotnet-backend-service');
467
-
468
- // Filter by category
469
- const codeTemplates = getTemplatesByCategory('code');
470
-
471
- // Filter by technology
472
- const dotnetTemplates = getTemplatesByTechnology('dotnet');
473
-
474
- // Resolve path with fallback
475
- const path = resolveTemplatePathById('dotnet-backend-service', '/project', 'dotnet-nextjs');
476
- // Returns: framework/templates/code/dotnet/backend/service.cs
477
- // Or: stacks/dotnet-nextjs/.morph/framework/templates/code/dotnet/backend/service.cs (if override exists)
478
- ```
479
-
480
- ---
481
-
482
- ## πŸš€ Creating New Templates
483
-
484
- ### 1. Create Template File
485
-
486
- ```bash
487
- # For .NET templates
488
- touch framework/templates/code/dotnet/backend/my-template.cs
489
-
490
- # For infrastructure templates
491
- touch framework/templates/infrastructure/docker/my-resource.dockerfile
492
- ```
493
-
494
- ### 2. Add Handlebars Placeholders
495
-
496
- ```handlebars
497
- namespace {{pascalCase NAMESPACE}};
498
-
499
- public class {{pascalCase FEATURE_NAME}}Service
500
- {
501
- // TODO: Implement {{titleCase FEATURE_NAME}} logic
502
- }
503
- ```
504
-
505
- ### 3. Register in REGISTRY.json
506
-
507
- ```json
508
- {
509
- "id": "dotnet-backend-my-template",
510
- "name": "My Custom Template",
511
- "path": "code/dotnet/backend/my-template.cs",
512
- "location": "framework",
513
- "category": "code",
514
- "phase": "implement",
515
- "required": false,
516
- "technology": "dotnet",
517
- "applicableStacks": ["dotnet-nextjs"],
518
- "engine": "handlebars",
519
- "placeholders": ["FEATURE_NAME", "NAMESPACE"],
520
- "outputName": "{FeatureName}MyTemplate.cs",
521
- "deprecated": false
522
- }
523
- ```
524
-
525
- ### 4. Test Rendering
526
-
527
- ```bash
528
- morph-spec template render dotnet-backend-my-template output.cs '{
529
- "FEATURE_NAME": "user-auth",
530
- "NAMESPACE": "MyApp.Services"
531
- }'
532
- ```
533
-
534
- ---
535
-
536
- ## πŸ“¦ Migration Guide: v1 β†’ v2
537
-
538
- ### What Changed
539
-
540
- | Aspect | v1 (Stack-Based) | v2 (Technology-Based) |
541
- |--------|------------------|----------------------|
542
- | **Location** | `stacks/{stack}/.morph/framework/templates/` | `framework/templates/{technology}/` |
543
- | **Organization** | By stack (dotnet-nextjs, nextjs-neon) | By technology (dotnet, docker) |
544
- | **Duplication** | High (proposal.md Γ— 2, decisions.md Γ— 2) | Low (shared templates in framework) |
545
- | **Template Engine** | 3 engines (custom, Handlebars, mixed) | 1 engine (Handlebars with helpers) |
546
- | **Pre-computed Variables** | `{{pascalCase FEATURE_NAME}}` | `{{pascalCase FEATURE_NAME}}` (helpers) |
547
- | **Registry** | None (hardcoded paths) | `REGISTRY.json` (centralized metadata) |
548
- | **CLI** | None | `morph-spec template list/show/render/customize` |
549
- | **Future Stacks** | Must copy templates | Reuse existing technology templates |
550
-
551
- ### Breaking Changes
552
-
553
- **1. Template Paths**
554
-
555
- ```diff
556
- - stacks/dotnet-nextjs/.morph/framework/templates/service.cs
557
- + framework/templates/code/dotnet/backend/service.cs
558
-
559
- - stacks/nextjs-neon/.morph/framework/templates/dockerfile-web.dockerfile
560
- + framework/templates/infrastructure/docker/dockerfile-web.dockerfile
561
- ```
562
-
563
- **2. Pre-computed Variables**
564
-
565
- ```diff
566
- - {{pascalCase FEATURE_NAME}}
567
- + {{pascalCase FEATURE_NAME}}
568
-
569
- - {{camelCase FEATURE_NAME}}
570
- + {{camelCase FEATURE_NAME}}
571
-
572
- - {{snakeCase FEATURE_NAME}}
573
- + {{snakeCase FEATURE_NAME}}
574
- ```
575
-
576
- **3. Template Resolution**
577
-
578
- ```javascript
579
- // Old (v1)
580
- const templatePath = join(resolveTemplatesDir(projectPath), 'service.cs');
581
-
582
- // New (v2)
583
- const templatePath = resolveTemplatePath(projectPath, 'code/dotnet/backend/service.cs', stackId);
584
- // Automatically falls back: stack override β†’ framework
585
- ```
586
-
587
- ### Migration Steps
588
-
589
- **Step 1:** Update code to use `resolveTemplatePath()`
590
-
591
- ```javascript
592
- import { resolveTemplatePath } from '../lib/stack-resolver.js';
593
-
594
- // Before
595
- const path = join(resolveTemplatesDir(process.cwd()), 'service.cs');
596
-
597
- // After
598
- const path = resolveTemplatePath(process.cwd(), 'code/dotnet/backend/service.cs', 'dotnet-nextjs');
599
- ```
600
-
601
- **Step 2:** Update template syntax to Handlebars
602
-
603
- ```handlebars
604
- <!-- Before -->
605
- namespace {{NAMESPACE}};
606
- public class {{pascalCase FEATURE_NAME}}Service { }
607
-
608
- <!-- After -->
609
- namespace {{pascalCase NAMESPACE}};
610
- public class {{pascalCase FEATURE_NAME}}Service { }
611
- ```
612
-
613
- **Step 3:** Use CLI commands instead of hardcoded paths
614
-
615
- ```bash
616
- # Before (hardcoded)
617
- cp framework/templates/proposal.md .morph/features/user-auth/proposal.md
618
-
619
- # After (CLI)
620
- morph-spec template render proposal .morph/features/user-auth/proposal.md '{
621
- "FEATURE_NAME": "user-auth"
622
- }'
623
- ```
624
-
625
- ---
626
-
627
- ## 🎯 Best Practices
628
-
629
- ### 1. **Use Helpers, Not Pre-computed Variables**
630
-
631
- ```handlebars
632
- βœ… GOOD:
633
- {{pascalCase FEATURE_NAME}}Service
634
-
635
- ❌ BAD:
636
- {{pascalCase FEATURE_NAME}}Service // Deprecated, won't work
637
- ```
638
-
639
- ### 2. **Keep Templates Technology-Agnostic**
640
-
641
- ```handlebars
642
- βœ… GOOD: code/dotnet/backend/service.cs
643
- Works for: dotnet-nextjs, nextjs-neon, future-dotnet-stack
644
-
645
- ❌ BAD: code/stack-specific/service.cs
646
- Locked to one stack only
647
- ```
648
-
649
- ### 3. **Use Stack Conditionals for Differences**
650
-
651
- ```handlebars
652
- {{#if (eq STACK "nextjs-neon")}}
653
- // Neon-specific implementation
654
- {{else}}
655
- // Generic implementation
656
- {{/if}}
657
- ```
658
-
659
- ### 4. **Document Applicability in Registry**
660
-
661
- ```json
662
- {
663
- "technology": "dotnet",
664
- "applicableStacks": ["dotnet-nextjs", "nextjs-neon"],
665
- "description": "Works with any .NET backend stack"
666
- }
667
- ```
668
-
669
- ### 5. **Override Only When Necessary**
670
-
671
- ```bash
672
- # Only customize if framework template doesn't meet needs
673
- morph-spec template customize dotnet-backend-service --stack dotnet-nextjs
674
-
675
- # Otherwise, use framework version (gets updates automatically)
676
- morph-spec template render dotnet-backend-service output.cs '...'
677
- ```
678
-
679
- ---
680
-
681
- ## πŸ“š References
682
-
683
- - **Template Registry API:** [`src/lib/template-registry.js`](../../src/lib/template-registry.js)
684
- - **Template Renderer:** [`src/lib/template-renderer.js`](../../src/lib/template-renderer.js)
685
- - **Stack Resolver:** [`src/lib/stack-resolver.js`](../../src/lib/stack-resolver.js)
686
- - **CLI Commands:** [`src/commands/template-*.js`](../../src/commands/)
687
- - **Handlebars Docs:** https://handlebarsjs.com/
688
-
689
- ---
690
-
691
- ## 🀝 Contributing
692
-
693
- ### Adding New Technology
694
-
695
- 1. Create directory: `framework/templates/code/{technology}/`
696
- 2. Add templates with Handlebars syntax
697
- 3. Register in `REGISTRY.json` with `"technology": "{technology}"`
698
- 4. Test with `morph-spec template render`
699
- 5. Document in this README
700
-
701
- ### Deprecating Templates
702
-
703
- 1. Add `"deprecated": true` to `REGISTRY.json`
704
- 2. Add `"deprecationReason": "Reason here"`
705
- 3. Keep file for backward compatibility or remove after major version bump
706
-
707
- ---
708
-
709
- **MORPH-SPEC Template System v2.0** - Technology-Based, Future-Proof, DRY ✨
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, 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
+ β”‚ β”œβ”€β”€ decisions.md # Architecture Decision Records (required)
23
+ β”‚ └── recap.md # Post-implementation summary (required)
24
+ β”‚
25
+ β”œβ”€β”€ context/ # Context generation
26
+ β”‚ β”œβ”€β”€ CONTEXT.md # Project-level context
27
+ β”‚ └── CONTEXT-FEATURE.md # Feature-level context
28
+ β”‚
29
+ β”œβ”€β”€ code/ # Code templates organized by technology
30
+ β”‚ β”œβ”€β”€ dotnet/
31
+ β”‚ β”‚ β”œβ”€β”€ backend/
32
+ β”‚ β”‚ β”‚ β”œβ”€β”€ service.cs # Service layer
33
+ β”‚ β”‚ β”‚ β”œβ”€β”€ repository.cs # Data access layer
34
+ β”‚ β”‚ β”‚ └── test.cs # Unit tests
35
+ β”‚ β”‚ β”œβ”€β”€ database/
36
+ β”‚ β”‚ β”‚ └── migration.cs # EF Core migrations
37
+ β”‚ β”‚ β”œβ”€β”€ jobs/
38
+ β”‚ β”‚ β”‚ β”œβ”€β”€ job.cs # Hangfire background jobs
39
+ β”‚ β”‚ β”‚ └── agent.cs # MS Agent Framework agents
40
+ β”‚ β”‚ └── contracts/
41
+ β”‚ β”‚ β”œβ”€β”€ contracts.cs # Base contracts
42
+ β”‚ β”‚ β”œβ”€β”€ Commands.cs # CQRS commands
43
+ β”‚ β”‚ β”œβ”€β”€ Queries.cs # CQRS queries
44
+ β”‚ β”‚ β”œβ”€β”€ Entities.cs # Domain entities
45
+ β”‚ β”‚ β”œβ”€β”€ api-contracts.cs # API contracts
46
+ β”‚ β”‚ └── README.md # Contracts documentation
47
+ β”‚ β”‚
48
+ β”‚ β”œβ”€β”€ typescript/
49
+ β”‚ β”‚ └── contracts.ts # TypeScript type definitions
50
+ β”‚ β”‚
51
+ β”‚ └── sql/
52
+ β”‚ β”œβ”€β”€ postgresql-migration.sql # Basic migration
53
+ β”‚ β”œβ”€β”€ postgresql-migration.template.sql # Enhanced migration
54
+ β”‚ └── postgresql-rls-policy.sql # Row-level security
55
+ β”‚
56
+ β”œβ”€β”€ infrastructure/
57
+ β”‚ β”œβ”€β”€ docker/ # Docker & EasyPanel
58
+ β”‚ β”‚ β”œβ”€β”€ dockerfile-api.dockerfile # .NET API
59
+ β”‚ β”‚ β”œβ”€β”€ dockerfile-web.dockerfile # Next.js web
60
+ β”‚ β”‚ β”œβ”€β”€ Dockerfile.template # Generic
61
+ β”‚ β”‚ β”œβ”€β”€ docker-compose.template.yml # Compose
62
+ β”‚ β”‚ └── easypanel.template.json # EasyPanel config
63
+ β”‚ β”‚
64
+ β”‚ └── github/ # GitHub Actions CI/CD
65
+ β”‚ β”œβ”€β”€ workflows/ # Reusable workflow templates
66
+ β”‚ β”‚ β”œβ”€β”€ dotnet-build.yml.hbs # .NET restore, build, test
67
+ β”‚ β”‚ β”œβ”€β”€ docker-build-push.yml.hbs # Docker build & push
68
+ β”‚ β”‚ └── deploy-easypanel.yml.hbs # EasyPanel deployment
69
+ β”‚ β”‚
70
+ β”‚ β”œβ”€β”€ actions/ # Composite action templates
71
+ β”‚ β”‚ β”œβ”€β”€ docker-build-push/action.yml.hbs
72
+ β”‚ β”‚ └── health-check/action.yml.hbs
73
+ β”‚ β”‚
74
+ β”‚ └── README.md # GitHub Actions docs
75
+ β”‚
76
+ β”œβ”€β”€ integrations/ # Platform-agnostic integrations
77
+ β”‚ β”œβ”€β”€ asaas-client.cs # Asaas financial API
78
+ β”‚ β”œβ”€β”€ asaas-webhook.cs # Asaas webhooks
79
+ β”‚ └── neon-auth-config.cs # Neon Auth (Better Auth)
80
+ β”‚
81
+ β”œβ”€β”€ ui/ # Design systems
82
+ β”‚ └── design-system.css # CSS tokens
83
+ β”‚
84
+ β”œβ”€β”€ saas/ # Multi-tenant patterns
85
+ β”‚
86
+ β”œβ”€β”€ examples/ # Reference implementations
87
+ β”‚ β”œβ”€β”€ spec-examples.md # Example specs
88
+ β”‚ └── design-system-examples.md # Design system examples
89
+ β”‚
90
+ └── REGISTRY.json # Template metadata registry
91
+ ```
92
+
93
+ ---
94
+
95
+ ## πŸ—οΈ Technology-Based Architecture
96
+
97
+ **Why organize by technology instead of by stack?**
98
+
99
+ | Organization | Pros | Cons | Best For |
100
+ |--------------|------|------|----------|
101
+ | **By Stack** (old v1) | Stack-specific optimizations | Duplicate templates, hard to reuse | Single-stack projects |
102
+ | **By Technology** (new v2) | Reusable, DRY, future-proof | Requires stack override mechanism | Multi-stack frameworks |
103
+
104
+ **Example:** A `.NET service.cs` template works for both `dotnet-nextjs` and `nextjs-neon` stacks (both use .NET backend). No need to duplicate!
105
+
106
+ **Future-proof:** When we create `vue-firebase` stack, we can reuse:
107
+ - `code/typescript/` templates
108
+ - `infrastructure/docker/` templates
109
+ - `integrations/` templates (Neon Auth, etc.)
110
+
111
+ **Only create NEW templates for Vue-specific code.**
112
+
113
+ ---
114
+
115
+ ## βš™οΈ Template Engine: Handlebars
116
+
117
+ All templates use **Handlebars** with **20+ custom helpers**.
118
+
119
+ ### Basic Syntax
120
+
121
+ ```handlebars
122
+ # Feature: {{titleCase FEATURE_NAME}}
123
+
124
+ Namespace: {{pascalCase FEATURE_NAME}}
125
+
126
+ Created: {{DATE}}
127
+ ```
128
+
129
+ ### Available Helpers
130
+
131
+ | Helper | Input | Output | Usage |
132
+ |--------|-------|--------|-------|
133
+ | `{{pascalCase str}}` | `user-profile` | `UserProfile` | Class names |
134
+ | `{{camelCase str}}` | `user-profile` | `userProfile` | Variable names |
135
+ | `{{snakeCase str}}` | `user-profile` | `user_profile` | SQL tables |
136
+ | `{{upperSnakeCase str}}` | `user-profile` | `USER_PROFILE` | Constants |
137
+ | `{{titleCase str}}` | `user-profile` | `User Profile` | Titles |
138
+ | `{{kebabCase str}}` | `User Profile` | `user-profile` | URLs |
139
+ | `{{pluralize str}}` | `user` | `users` | Collections |
140
+ | `{{singularize str}}` | `users` | `user` | Entities |
141
+ | `{{eq a b}}` | `"nextjs" "nextjs"` | `true` | Conditionals |
142
+ | `{{or a b}}` | `false true` | `true` | Logical OR |
143
+ | `{{and a b}}` | `true false` | `false` | Logical AND |
144
+ | `{{default val fallback}}` | `null "default"` | `"default"` | Defaults |
145
+
146
+ ### Conditional Logic
147
+
148
+ ```handlebars
149
+ {{#if (eq STACK "nextjs-neon")}}
150
+ // Neon-specific code
151
+ {{else}}
152
+ // Generic code
153
+ {{/if}}
154
+ ```
155
+
156
+ ### Deprecated: Pre-computed Variables
157
+
158
+ **❌ Old (v1):**
159
+ ```handlebars
160
+ {{pascalCase FEATURE_NAME}} <!-- Pre-computed in bin/render-template.js -->
161
+ ```
162
+
163
+ **βœ… New (v2):**
164
+ ```handlebars
165
+ {{pascalCase FEATURE_NAME}} <!-- Computed via Handlebars helper -->
166
+ ```
167
+
168
+ ---
169
+
170
+ ## πŸ› οΈ CLI Commands
171
+
172
+ ### List All Templates
173
+
174
+ ```bash
175
+ # List all templates
176
+ morph-spec template list
177
+
178
+ # Filter by category
179
+ morph-spec template list --category code
180
+ morph-spec template list --category infrastructure
181
+
182
+ # Filter by phase
183
+ morph-spec template list --phase implement
184
+
185
+ # Filter by stack applicability
186
+ morph-spec template list --stack dotnet-nextjs
187
+
188
+ # Show only required templates
189
+ morph-spec template list --required
190
+ ```
191
+
192
+ **Output:**
193
+ ```
194
+ πŸ“¦ Universal Templates (9)
195
+ proposal Feature Proposal [REQUIRED] [UNIVERSAL] [HBS]
196
+ spec Technical Specification [REQUIRED] [UNIVERSAL] [HBS]
197
+ tasks Implementation Tasks [REQUIRED] [UNIVERSAL] [HBS]
198
+ ...
199
+
200
+ πŸ“¦ Technology-Based Templates (48)
201
+ dotnet-backend-service .NET Service Class [UNIVERSAL] [HBS] (dotnet)
202
+ typescript-contracts TypeScript Contracts [UNIVERSAL] [HBS] (typescript)
203
+ ...
204
+ ```
205
+
206
+ ### Show Template Details
207
+
208
+ ```bash
209
+ # Show metadata
210
+ morph-spec template show dotnet-backend-service
211
+
212
+ # Show with file preview
213
+ morph-spec template show dotnet-backend-service --preview
214
+
215
+ # Show with resolved path
216
+ morph-spec template show dotnet-backend-service --show-path
217
+ ```
218
+
219
+ **Output:**
220
+ ```
221
+ Template: dotnet-backend-service
222
+
223
+ πŸ“‹ Metadata
224
+ ID: dotnet-backend-service
225
+ Name: .NET Service Class
226
+ Path: code/dotnet/backend/service.cs
227
+ Location: framework
228
+ Category: code
229
+ Phase: implement
230
+ Required: No
231
+ Technology: dotnet
232
+ Applicable Stacks: dotnet-nextjs, nextjs-neon
233
+
234
+ πŸ“ Description
235
+ C# service class template with dependency injection and interface pattern
236
+
237
+ πŸ”‘ Variables
238
+ {{FEATURE_NAME}}
239
+ {{NAMESPACE}}
240
+
241
+ πŸ“„ Output Name
242
+ {FeatureName}Service.cs
243
+
244
+ πŸ’‘ Usage Hint
245
+ morph-spec template render dotnet-backend-service output.cs '{"FEATURE_NAME":"user-auth","NAMESPACE":"MyApp"}'
246
+ ```
247
+
248
+ ### Render Template
249
+
250
+ ```bash
251
+ # Render to file
252
+ morph-spec template render dotnet-backend-service UserAuthService.cs '{
253
+ "FEATURE_NAME": "user-auth",
254
+ "NAMESPACE": "MyApp.Services"
255
+ }'
256
+
257
+ # Dry run (preview only)
258
+ morph-spec template render dotnet-backend-service output.cs '{"FEATURE_NAME":"test"}' --dry-run
259
+
260
+ # Auto-resolve path (searches framework β†’ stack override)
261
+ morph-spec template render proposal proposal.md '{"FEATURE_NAME":"auth"}' --resolve-path
262
+ ```
263
+
264
+ **Default Variables (auto-injected):**
265
+ - `DATE`: `2026-02-17`
266
+ - `YEAR`: `2026`
267
+ - `TIMESTAMP`: `2026-02-17T19:38:00.000Z`
268
+
269
+ ### Customize Template (Stack Override)
270
+
271
+ ```bash
272
+ # Copy to stack-specific directory (override framework version)
273
+ morph-spec template customize dotnet-backend-service --stack dotnet-nextjs
274
+
275
+ # Copy to project-local (cross-stack override)
276
+ morph-spec template customize dotnet-backend-service --local
277
+
278
+ # Force overwrite if exists
279
+ morph-spec template customize dotnet-backend-service --stack dotnet-nextjs --force
280
+ ```
281
+
282
+ **Output:**
283
+ ```
284
+ Source: framework/templates/code/dotnet/backend/service.cs
285
+ Destination: stacks/dotnet-nextjs/.morph/framework/templates/code/dotnet/backend/service.cs
286
+
287
+ βœ… Template copied for customization
288
+
289
+ πŸ“ Next Steps
290
+ 1. Edit the template file:
291
+ stacks/dotnet-nextjs/.morph/framework/templates/code/dotnet/backend/service.cs
292
+
293
+ 2. Template will now be used instead of framework version
294
+ (Stack-specific templates take precedence)
295
+
296
+ 3. Test rendering:
297
+ morph-spec template render dotnet-backend-service output.cs '{"FEATURE_NAME":"test"}'
298
+
299
+ ⚠️ Customized templates won't receive framework updates
300
+ To get updates: delete customized version and re-run this command
301
+ ```
302
+
303
+ ---
304
+
305
+ ## πŸ”„ GitHub Actions Templates
306
+
307
+ The framework provides reusable GitHub Actions workflows and composite actions for CI/CD automation.
308
+
309
+ ### Structure
310
+
311
+ ```
312
+ infrastructure/github/
313
+ β”œβ”€β”€ workflows/ # Reusable workflow templates
314
+ β”‚ β”œβ”€β”€ dotnet-build.yml.hbs # .NET restore, build, test
315
+ β”‚ β”œβ”€β”€ docker-build-push.yml.hbs # Docker build & push
316
+ β”‚ └── deploy-easypanel.yml.hbs # EasyPanel deployment
317
+ β”‚
318
+ └── actions/ # Composite action templates
319
+ β”œβ”€β”€ docker-build-push/action.yml.hbs
320
+ └── health-check/action.yml.hbs
321
+ ```
322
+
323
+ ### Reusable Workflows vs Composite Actions
324
+
325
+ | Type | Purpose | Location | Usage |
326
+ |------|---------|----------|-------|
327
+ | **Reusable Workflows** | Complete CI/CD pipelines (multi-job) | `workflows/*.yml.hbs` | Called via `uses:` from stack workflows |
328
+ | **Composite Actions** | Reusable step logic (single responsibility) | `actions/*/action.yml.hbs` | Called via `uses:` in workflow steps |
329
+
330
+ ### Deployment Strategy Difference
331
+
332
+ **NextJS-Neon:** Docker containers to EasyPanel
333
+ - `docker build` β†’ `docker push` β†’ EasyPanel webhook
334
+ - Multi-service deployment (API + Web)
335
+ - Registry: GitHub Container Registry (ghcr.io)
336
+
337
+ ### Template Rendering
338
+
339
+ **GitHub Actions Constraint:**
340
+ - ❌ GitHub Actions CANNOT reference parent directories (`../../../../framework/`)
341
+ - βœ… Solution: Framework templates are **rendered** into each stack's `.github/` directory
342
+ - Rendered `.yml` files are **committed** to repos (not `.yml.hbs` templates)
343
+
344
+ **Rendering Process:**
345
+ ```bash
346
+ # Render all GitHub Actions templates for a stack (manual for now)
347
+ # Future: morph-spec template render github-workflows --stack dotnet-nextjs
348
+ ```
349
+
350
+ ### Handlebars Variables
351
+
352
+ - `{{APP_NAME}}` - Application name from config.json
353
+ - `{{DOTNET_VERSION}}` - .NET SDK version
354
+ - `{{GITHUB_OWNER}}` - GitHub organization/user
355
+ - `{{kebabCase APP_NAME}}` - Docker image name format
356
+ - `${{{{ inputs.* }}}}` - GitHub Actions runtime syntax (escaped with `{{{{raw}}}}`)
357
+
358
+ ### Authentication & Secrets
359
+
360
+ **Docker Registry (NextJS-Neon):**
361
+ ```yaml
362
+ # GitHub Container Registry (ghcr.io)
363
+ - uses: docker/login-action@v3
364
+ with:
365
+ registry: ghcr.io
366
+ username: ${{{{ github.actor }}}}
367
+ password: ${{{{ secrets.GITHUB_TOKEN }}}}
368
+ ```
369
+
370
+ **GitHub Secrets to Configure:**
371
+ - NextJS-Neon: `GITHUB_TOKEN` (auto), `EASYPANEL_API_TOKEN`
372
+
373
+ ### Stack-Specific Overrides
374
+
375
+ Stack-specific workflow templates in:
376
+ - `stacks/nextjs-neon/.morph/framework/templates/infrastructure/github/workflows/`
377
+
378
+ **Resolution Order:**
379
+ 1. Project-local: `.morph/framework/templates/infrastructure/github/workflows/ci-build.yml.hbs`
380
+ 2. Stack default: `stacks/{stack}/.morph/framework/templates/infrastructure/github/workflows/ci-build.yml.hbs`
381
+ 3. Framework fallback: `framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs`
382
+
383
+ ---
384
+
385
+ ## πŸ”€ Stack Override Mechanism
386
+
387
+ **Resolution Order:**
388
+
389
+ 1. **Stack-specific override** (highest priority)
390
+ - `stacks/{stack}/.morph/framework/templates/code/dotnet/backend/service.cs`
391
+
392
+ 2. **Project-local override** (medium priority)
393
+ - `.morph/framework/templates/code/dotnet/backend/service.cs`
394
+
395
+ 3. **Framework template** (fallback)
396
+ - `framework/templates/code/dotnet/backend/service.cs`
397
+
398
+ **Use Cases for Overrides:**
399
+
400
+ | Scenario | Override Location | Example |
401
+ |----------|-------------------|---------|
402
+ | Stack-specific tweak | `stacks/{stack}/.morph/framework/templates/` | Stack uses different DI pattern |
403
+ | Project-wide customization | `.morph/framework/templates/` | Company-specific code style |
404
+ | Use framework default | None (no override) | Standard templates work fine |
405
+
406
+ **Example:**
407
+
408
+ ```bash
409
+ # Create stack override
410
+ morph-spec template customize dotnet-backend-service --stack dotnet-nextjs
411
+
412
+ # Edit the override
413
+ code stacks/dotnet-nextjs/.morph/framework/templates/code/dotnet/backend/service.cs
414
+
415
+ # Now all renders for dotnet-nextjs will use the override
416
+ morph-spec template render dotnet-backend-service UserService.cs '...' --stack dotnet-nextjs
417
+ ```
418
+
419
+ ---
420
+
421
+ ## πŸ“Š Template Registry (REGISTRY.json)
422
+
423
+ The `REGISTRY.json` file is the **single source of truth** for all template metadata.
424
+
425
+ ### Schema
426
+
427
+ ```json
428
+ {
429
+ "version": "2.0.0",
430
+ "templates": [
431
+ {
432
+ "id": "dotnet-backend-service",
433
+ "name": ".NET Service Class",
434
+ "path": "code/dotnet/backend/service.cs",
435
+ "location": "framework",
436
+ "category": "code",
437
+ "phase": "implement",
438
+ "required": false,
439
+ "technology": "dotnet",
440
+ "applicableStacks": ["dotnet-nextjs", "nextjs-neon"],
441
+ "engine": "handlebars",
442
+ "placeholders": ["FEATURE_NAME", "NAMESPACE"],
443
+ "outputName": "{FeatureName}Service.cs",
444
+ "deprecated": false
445
+ }
446
+ ]
447
+ }
448
+ ```
449
+
450
+ ### Discovery API
451
+
452
+ ```javascript
453
+ import {
454
+ getAllTemplates,
455
+ getTemplateById,
456
+ getTemplatesByCategory,
457
+ getTemplatesByTechnology,
458
+ resolveTemplatePathById
459
+ } from '../src/lib/template-registry.js';
460
+
461
+ // Get all templates
462
+ const all = getAllTemplates();
463
+
464
+ // Get specific template
465
+ const service = getTemplateById('dotnet-backend-service');
466
+
467
+ // Filter by category
468
+ const codeTemplates = getTemplatesByCategory('code');
469
+
470
+ // Filter by technology
471
+ const dotnetTemplates = getTemplatesByTechnology('dotnet');
472
+
473
+ // Resolve path with fallback
474
+ const path = resolveTemplatePathById('dotnet-backend-service', '/project', 'dotnet-nextjs');
475
+ // Returns: framework/templates/code/dotnet/backend/service.cs
476
+ // Or: stacks/dotnet-nextjs/.morph/framework/templates/code/dotnet/backend/service.cs (if override exists)
477
+ ```
478
+
479
+ ---
480
+
481
+ ## πŸš€ Creating New Templates
482
+
483
+ ### 1. Create Template File
484
+
485
+ ```bash
486
+ # For .NET templates
487
+ touch framework/templates/code/dotnet/backend/my-template.cs
488
+
489
+ # For infrastructure templates
490
+ touch framework/templates/infrastructure/docker/my-resource.dockerfile
491
+ ```
492
+
493
+ ### 2. Add Handlebars Placeholders
494
+
495
+ ```handlebars
496
+ namespace {{pascalCase NAMESPACE}};
497
+
498
+ public class {{pascalCase FEATURE_NAME}}Service
499
+ {
500
+ // TODO: Implement {{titleCase FEATURE_NAME}} logic
501
+ }
502
+ ```
503
+
504
+ ### 3. Register in REGISTRY.json
505
+
506
+ ```json
507
+ {
508
+ "id": "dotnet-backend-my-template",
509
+ "name": "My Custom Template",
510
+ "path": "code/dotnet/backend/my-template.cs",
511
+ "location": "framework",
512
+ "category": "code",
513
+ "phase": "implement",
514
+ "required": false,
515
+ "technology": "dotnet",
516
+ "applicableStacks": ["dotnet-nextjs"],
517
+ "engine": "handlebars",
518
+ "placeholders": ["FEATURE_NAME", "NAMESPACE"],
519
+ "outputName": "{FeatureName}MyTemplate.cs",
520
+ "deprecated": false
521
+ }
522
+ ```
523
+
524
+ ### 4. Test Rendering
525
+
526
+ ```bash
527
+ morph-spec template render dotnet-backend-my-template output.cs '{
528
+ "FEATURE_NAME": "user-auth",
529
+ "NAMESPACE": "MyApp.Services"
530
+ }'
531
+ ```
532
+
533
+ ---
534
+
535
+ ## πŸ“¦ Migration Guide: v1 β†’ v2
536
+
537
+ ### What Changed
538
+
539
+ | Aspect | v1 (Stack-Based) | v2 (Technology-Based) |
540
+ |--------|------------------|----------------------|
541
+ | **Location** | `stacks/{stack}/.morph/framework/templates/` | `framework/templates/{technology}/` |
542
+ | **Organization** | By stack (dotnet-nextjs, nextjs-neon) | By technology (dotnet, docker) |
543
+ | **Duplication** | High (proposal.md Γ— 2, decisions.md Γ— 2) | Low (shared templates in framework) |
544
+ | **Template Engine** | 3 engines (custom, Handlebars, mixed) | 1 engine (Handlebars with helpers) |
545
+ | **Pre-computed Variables** | `{{pascalCase FEATURE_NAME}}` | `{{pascalCase FEATURE_NAME}}` (helpers) |
546
+ | **Registry** | None (hardcoded paths) | `REGISTRY.json` (centralized metadata) |
547
+ | **CLI** | None | `morph-spec template list/show/render/customize` |
548
+ | **Future Stacks** | Must copy templates | Reuse existing technology templates |
549
+
550
+ ### Breaking Changes
551
+
552
+ **1. Template Paths**
553
+
554
+ ```diff
555
+ - stacks/dotnet-nextjs/.morph/framework/templates/service.cs
556
+ + framework/templates/code/dotnet/backend/service.cs
557
+
558
+ - stacks/nextjs-neon/.morph/framework/templates/dockerfile-web.dockerfile
559
+ + framework/templates/infrastructure/docker/dockerfile-web.dockerfile
560
+ ```
561
+
562
+ **2. Pre-computed Variables**
563
+
564
+ ```diff
565
+ - {{pascalCase FEATURE_NAME}}
566
+ + {{pascalCase FEATURE_NAME}}
567
+
568
+ - {{camelCase FEATURE_NAME}}
569
+ + {{camelCase FEATURE_NAME}}
570
+
571
+ - {{snakeCase FEATURE_NAME}}
572
+ + {{snakeCase FEATURE_NAME}}
573
+ ```
574
+
575
+ **3. Template Resolution**
576
+
577
+ ```javascript
578
+ // Old (v1)
579
+ const templatePath = join(resolveTemplatesDir(projectPath), 'service.cs');
580
+
581
+ // New (v2)
582
+ const templatePath = resolveTemplatePath(projectPath, 'code/dotnet/backend/service.cs', stackId);
583
+ // Automatically falls back: stack override β†’ framework
584
+ ```
585
+
586
+ ### Migration Steps
587
+
588
+ **Step 1:** Update code to use `resolveTemplatePath()`
589
+
590
+ ```javascript
591
+ import { resolveTemplatePath } from '../lib/stack-resolver.js';
592
+
593
+ // Before
594
+ const path = join(resolveTemplatesDir(process.cwd()), 'service.cs');
595
+
596
+ // After
597
+ const path = resolveTemplatePath(process.cwd(), 'code/dotnet/backend/service.cs', 'dotnet-nextjs');
598
+ ```
599
+
600
+ **Step 2:** Update template syntax to Handlebars
601
+
602
+ ```handlebars
603
+ <!-- Before -->
604
+ namespace {{NAMESPACE}};
605
+ public class {{pascalCase FEATURE_NAME}}Service { }
606
+
607
+ <!-- After -->
608
+ namespace {{pascalCase NAMESPACE}};
609
+ public class {{pascalCase FEATURE_NAME}}Service { }
610
+ ```
611
+
612
+ **Step 3:** Use CLI commands instead of hardcoded paths
613
+
614
+ ```bash
615
+ # Before (hardcoded)
616
+ cp framework/templates/proposal.md .morph/features/user-auth/proposal.md
617
+
618
+ # After (CLI)
619
+ morph-spec template render proposal .morph/features/user-auth/proposal.md '{
620
+ "FEATURE_NAME": "user-auth"
621
+ }'
622
+ ```
623
+
624
+ ---
625
+
626
+ ## 🎯 Best Practices
627
+
628
+ ### 1. **Use Helpers, Not Pre-computed Variables**
629
+
630
+ ```handlebars
631
+ βœ… GOOD:
632
+ {{pascalCase FEATURE_NAME}}Service
633
+
634
+ ❌ BAD:
635
+ {{pascalCase FEATURE_NAME}}Service // Deprecated, won't work
636
+ ```
637
+
638
+ ### 2. **Keep Templates Technology-Agnostic**
639
+
640
+ ```handlebars
641
+ βœ… GOOD: code/dotnet/backend/service.cs
642
+ Works for: dotnet-nextjs, nextjs-neon, future-dotnet-stack
643
+
644
+ ❌ BAD: code/stack-specific/service.cs
645
+ Locked to one stack only
646
+ ```
647
+
648
+ ### 3. **Use Stack Conditionals for Differences**
649
+
650
+ ```handlebars
651
+ {{#if (eq STACK "nextjs-neon")}}
652
+ // Neon-specific implementation
653
+ {{else}}
654
+ // Generic implementation
655
+ {{/if}}
656
+ ```
657
+
658
+ ### 4. **Document Applicability in Registry**
659
+
660
+ ```json
661
+ {
662
+ "technology": "dotnet",
663
+ "applicableStacks": ["dotnet-nextjs", "nextjs-neon"],
664
+ "description": "Works with any .NET backend stack"
665
+ }
666
+ ```
667
+
668
+ ### 5. **Override Only When Necessary**
669
+
670
+ ```bash
671
+ # Only customize if framework template doesn't meet needs
672
+ morph-spec template customize dotnet-backend-service --stack dotnet-nextjs
673
+
674
+ # Otherwise, use framework version (gets updates automatically)
675
+ morph-spec template render dotnet-backend-service output.cs '...'
676
+ ```
677
+
678
+ ---
679
+
680
+ ## πŸ“š References
681
+
682
+ - **Template Registry API:** [`src/lib/template-registry.js`](../../src/lib/template-registry.js)
683
+ - **Template Renderer:** [`src/lib/template-renderer.js`](../../src/lib/template-renderer.js)
684
+ - **Stack Resolver:** [`src/lib/stack-resolver.js`](../../src/lib/stack-resolver.js)
685
+ - **CLI Commands:** [`src/commands/template-*.js`](../../src/commands/)
686
+ - **Handlebars Docs:** https://handlebarsjs.com/
687
+
688
+ ---
689
+
690
+ ## 🀝 Contributing
691
+
692
+ ### Adding New Technology
693
+
694
+ 1. Create directory: `framework/templates/code/{technology}/`
695
+ 2. Add templates with Handlebars syntax
696
+ 3. Register in `REGISTRY.json` with `"technology": "{technology}"`
697
+ 4. Test with `morph-spec template render`
698
+ 5. Document in this README
699
+
700
+ ### Deprecating Templates
701
+
702
+ 1. Add `"deprecated": true` to `REGISTRY.json`
703
+ 2. Add `"deprecationReason": "Reason here"`
704
+ 3. Keep file for backward compatibility or remove after major version bump
705
+
706
+ ---
707
+
708
+ **MORPH-SPEC Template System v2.0** - Technology-Based, Future-Proof, DRY ✨