# MORPH-SPEC Template System

> Handlebars templates organized by **technology**, indexed by `REGISTRY.json`.

## Overview

**89 templates**, grouped by the technology they target (dotnet, typescript, sql, docker,
nextjs) rather than by stack. A template for a .NET slice serves every stack with a .NET
backend, so a new stack reuses what exists instead of copying it.

`REGISTRY.json` is the source of truth: it maps each template `id` to its `path`, category,
technology and applicable stacks. Nothing resolves a template by hardcoded path — code goes
through the registry, and this README never repeats a path the registry already owns.

---

## 📁 Directory Structure

```
framework/templates/
├── docs/              # Phase documents (proposal, spec, user-stories, ui-*, onboarding…)
├── feature/           # decisions.md, recap.md
├── context/           # ARCHITECTURE.md, design-system.md
│
├── code/              # Code templates, by technology
│   ├── dotnet/        # abstractions, ai-agents, constants, contracts, database,
│   │                  #   exceptions, extensions, feature, jobs, pipelines
│   ├── typescript/    # contracts.ts
│   └── sql/           # postgresql migrations, RLS policy, ai-agents
│
├── frontend/
│   └── nextjs/        # page, client-component, feature-form, use-feature, env, tsconfig…
│
├── infrastructure/
│   ├── docker/        # Dockerfiles, compose, Coolify config
│   └── github/        # Actions workflows + composite actions (.hbs)
│
├── integrations/      # asaas-client, asaas-webhook, neon-auth-config
├── ui/                # design-system.css
├── meta-prompts/      # fusion, squad-leaders, validators
├── examples/          # spec-examples.md, design-system-examples.md
└── REGISTRY.json      # template metadata — the index every consumer reads
```

---

## ⚙️ Template Engine: Handlebars

All templates render through Handlebars with custom helpers registered in
`src/core/templates/template-renderer.js`.

```handlebars
# Feature: {{titleCase FEATURE_NAME}}

namespace {{pascalCase FEATURE_NAME}};

Created: {{now}}
```

### Available helpers

| Group | Helpers |
|-------|---------|
| **Case** | `pascalCase` `camelCase` `snakeCase` `upperSnakeCase` `kebabCase` `titleCase` `uppercase` `lowercase` `capitalize` |
| **Words** | `pluralize` `singularize` |
| **Comparison** | `eq` `ne` `lt` `gt` `lte` `gte` |
| **Logic** | `and` `or` `not` `default` |
| **String** | `trim` `replace` `concat` `substr` `startsWith` `endsWith` `contains` `length` |
| **Math** | `add` `subtract` `multiply` `divide` `mod` `round` |
| **Array** | `join` `first` `last` `slice` |
| **Misc** | `json` `now` `year` `formatDate` |

```handlebars
{{#if (eq STACK "nextjs-neon")}}
// Neon-specific code
{{else}}
// Generic code
{{/if}}
```

---

## 🔗 How templates are consumed

Templates are **resolved from the installed npm package**, not copied into projects.
`morph-spec setup-infra` deliberately skips copying `framework/templates/` — a target project
gets the package's templates for free and stays current on every upgrade.

**The consumer is the scaffolder**, which pairs a REGISTRY `id` with an output shape:

```bash
morph-spec scaffold dotnet <feature> <slice-name>   # VSA slice (endpoint, handler, request,
                                                    #   response, validator, errors, entity)
morph-spec scaffold nextjs <feature>                # page, client component, form, hook
```

There is **no `morph-spec template` command** — the v4 CLI surface (`list`/`show`/`render`/
`customize`) was removed in the v4→v5 migration. To use a template by hand, read the file and
follow its pattern, or call `renderTemplate()` from the renderer module.

### Local override

A project may shadow any packaged template by placing a file at the same relative path under
`.morph/framework/templates/{path}`. The local copy wins, and **stops receiving framework
updates** — only override when the packaged template genuinely does not fit.

---

## ➕ Adding a template

1. Create the file under the right technology directory:
   `framework/templates/code/{technology}/...` (Handlebars syntax, `.hbs` when the extension
   would otherwise confuse tooling).
2. Register it in `REGISTRY.json` with a unique `id`, its `path`, `category`, `technology`
   and applicable stacks.
3. If a generator should emit it, add the `id` to the relevant list in
   `src/lib/generators/scaffold-generator.js`.

### Deprecating a template

Add `"deprecated": true` plus `"deprecationReason"` to its `REGISTRY.json` entry. Keep the
file until a major version bump.

---

## 📚 References

- **Registry API:** [`src/core/templates/template-registry.js`](../../src/core/templates/template-registry.js)
- **Renderer + helpers:** [`src/core/templates/template-renderer.js`](../../src/core/templates/template-renderer.js)
- **Scaffold generator:** [`src/lib/generators/scaffold-generator.js`](../../src/lib/generators/scaffold-generator.js)
- **Stack filtering:** [`src/lib/stack-filter.js`](../../src/lib/stack-filter.js)
- **Handlebars docs:** https://handlebarsjs.com/

---

**MORPH-SPEC Template System** — technology-based, registry-indexed, resolved from the package.
