Template Layering Guide¶
This document provides a technical guide to ConnectSoft's template layering architecture. It is written for architects and engineers who need to understand how templates are structured, how they reuse code and documentation, and how the build-time and generation-time processes differ.
ConnectSoft avoids copy-pasting and "template inheritance" by splitting responsibilities across three layers: shared libraries, base template (ConnectSoft.BaseTemplate via base-template submodule), and specialized templates. This architecture enables maximum reuse while maintaining flexibility and avoiding duplication.
DI orchestration reuse in this model is governed by hook-based registration in BaseTemplate. See BaseTemplate DI Extensibility.
NuGet catalog: ConnectSoft.Extensions catalog (public docs). MSBuild layering for extended repos (for example ConnectSoft.IdentityTemplate) is documented there under Template layering and reuse. For the full multi-layer alignment playbook (submodule, MSBuild, Docker, application and template-installer CI, dockerRegistryServiceConnection / ACR alignment, composition), see Extended templates: full multi-layer alignment playbook.
Important
The three-layer model is fundamental to ConnectSoft's template architecture. Understanding this model is essential for working with templates, extending them, or creating new specialized templates.
The Three-Layer Model¶
ConnectSoft templates are organized into three distinct layers:
flowchart TB
subgraph Layer1["Layer 1: Shared Libraries"]
LIB[ConnectSoft.Extensions NuGet packages]
end
subgraph Layer2["Layer 2: Base Template"]
BASE[ConnectSoft.BaseTemplate model projects and host]
end
subgraph Layer3["Layer 3: Specialized Templates"]
IDENTITY[ConnectSoft.IdentityTemplate and others]
WORKER[Worker and domain templates]
BOT[Microsoft Bot Framework Template]
end
Layer1 -->|Central Package Management| Layer2
Layer1 -->|Central Package Management| Layer3
Layer2 -->|Git submodule base-template| Layer3
Layer 1: Shared Libraries (ConnectSoft.Extensions.*)¶
Purpose: All generic, cross-cutting infrastructure delivered as NuGet packages. Authoritative list: ConnectSoft.Extensions catalog.
Characteristics:
- Delivered as NuGet packages
- Used by all templates and services
- Versioned in ConnectSoft.BaseTemplate Directory.Packages.props
- No domain-specific logic
Layer 2: Base Template (ConnectSoft.BaseTemplate)¶
Purpose: One canonical repository (ConnectSoft.BaseTemplate), included as the base-template git submodule, containing the microservice "kernel" - all common structure and bootstrapping without domain-specific logic.
Responsibilities:
- Solution layout: ConnectSoft.BaseTemplate.* projects (DomainModel, ApplicationModel, PersistenceModel, ServiceModel, FlowModel, MessagingModel, host, tests, optional stacks)—see ConnectSoft.BaseTemplate.slnx
- Program/Host bootstrapping
- Common health checks, resilience patterns
- Base CI/CD pipelines
- Base testing infrastructure
- Base documentation structure
- Base template metadata (/template/template.json)
Characteristics: - Single canonical repository - No domain-specific logic (no Identity/Audit/etc.) - Fully buildable as a normal .NET solution - Used as git submodule by specialized templates
Layer 3: Specialized Templates (Identity, Auth, Audit, Worker, Microsoft Bot Framework, etc.)¶
Purpose: Each specialized template adds domain-specific functionality on top of the base template.
Responsibilities:
- Domain-specific projects (Identity, Auth, Worker, ConnectSoft.MicrosoftBotFrameworkTemplate with BotModel and forked Application / ApplicationModel, etc.)
- Domain-specific tests
- Domain-specific documentation
- Overlay metadata for template.json and docs
Characteristics:
- Each template is its own repository
- Includes base as git submodule (base-template/)
- Adds domain-specific projects
- Fully buildable as normal .NET solution without Factory
- Defines overlay metadata for generation-time composition
Build Time vs Generation Time¶
ConnectSoft distinguishes between two modes of operation:
Build Time (Developer Experience)¶
Goal: Open solution, hit dotnet build / dotnet test, everything just works.
Characteristics: - Specialized template repo includes base as git submodule - Solution file includes projects from both base and specialized template - Developer works on a real, concrete application - No Factory required to build or test - Documentation references both base docs (via submodule) and specialized docs
Example structure (ConnectSoft.IdentityTemplate):
ConnectSoft.IdentityTemplate/
├── base-template/ # Submodule: ConnectSoft.BaseTemplate
├── ConnectSoft.IdentityTemplate.slnx
├── Directory.Build.props
├── Directory.Packages.props
├── build/DisableMicrosoftExtensionsStackForMinimalHost.props
├── ConnectSoft.IdentityTemplate.*/ # Host, DomainModel, Application, ServiceModel, …
└── ConnectSoft.IdentityTemplate.*Tests/
Generation Time (Factory / Template Packaging)¶
Goal: Produce a final, flattened project template that the AI Factory or dotnet new uses.
Characteristics: - Start from base template (code + docs + metadata) - Apply one or more overlays (Identity, Worker, etc.) in a recipe - Resolve tokens (ServiceName, Namespace, etc.) - Output flattened template artifact - Push to Azure DevOps / Git / etc. with pipelines/work items
Generation Pipeline:
flowchart TD
BASE[Base Template<br/>Code + Docs + Metadata]
OVERLAY1[Identity Overlay<br/>Domain Code + Docs + Metadata]
OVERLAY2[Worker Overlay<br/>Worker Code + Docs + Metadata]
RECIPE[Recipe:<br/>base + identity + worker]
GENERATOR[Template Generator]
OUTPUT[Final Template Artifact<br/>Flattened Structure]
BASE --> GENERATOR
OVERLAY1 --> GENERATOR
OVERLAY2 --> GENERATOR
RECIPE --> GENERATOR
GENERATOR --> OUTPUT
Submodules at Build Time vs Overlays at Generation Time¶
Build Time: Git Submodules¶
What: Base template is included as a git submodule in specialized template repos.
Why: - Enables building specialized templates as normal .NET solutions - Base changes propagate automatically - No duplication of base code
How:
Result: Specialized template repo contains both base and specialized code, fully buildable.
Generation Time: Overlays¶
What: Overlays are applied on top of base template to create final template artifact.
Why:
- Enables composition of multiple overlays (Identity + Worker)
- Produces flattened template for dotnet new or Factory
- Allows recipe-based template generation
How:
# Recipe example
templateId: identity-worker-service
displayName: "Identity Backend with Worker"
layers:
- base: microservice/base
- overlay: microservice/overlays/identity-backend
- overlay: microservice/overlays/worker
Result: Final template artifact with all overlays applied, ready for generation.
Multi-Overlay Scenarios (Identity + Worker)¶
Specialized templates can combine multiple overlays. For example, an Identity Backend template might support both Identity domain logic and Worker functionality.
Overlay Stacking¶
flowchart TB
BASE[Base Template]
IDENTITY[Identity Overlay]
WORKER[Worker Overlay]
BASE --> IDENTITY
IDENTITY --> WORKER
WORKER --> FINAL[Final Template:<br/>Base + Identity + Worker]
Practical example: ConnectSoft.IdentityTemplate¶
Repository structure¶
Use repo ConnectSoft.IdentityTemplate: submodule base-template/ → ConnectSoft.BaseTemplate; solution ConnectSoft.IdentityTemplate.slnx includes a subset of base ConnectSoft.BaseTemplate.* projects and all ConnectSoft.IdentityTemplate.* projects. ConnectSoft.IdentityTemplate.Application replaces ConnectSoft.BaseTemplate.Application in that solution.
Build process¶
-
Clone repository:
-
Open the solution:
ConnectSoft.IdentityTemplate.slnx -
Build:
dotnet build ConnectSoft.IdentityTemplate.slnx -
Test:
dotnet test ConnectSoft.IdentityTemplate.slnx
Everything works as a normal .NET solution. No Factory required.
Rules and Best Practices¶
Do's¶
✅ Use git submodules for base template in specialized templates
✅ Keep base template domain-agnostic - no Identity/Audit/etc. logic
✅ Build specialized templates as normal solutions - they should compile without Factory
✅ Use overlays for generation-time composition - enables recipe-based templates
✅ Reference base docs via submodule at build time
✅ Merge docs physically at generation time
Don'ts¶
❌ Don't duplicate base code - use submodules instead
❌ Don't put domain logic in base - base is infrastructure only
❌ Don't modify base template.json directly - use extend files
❌ Don't copy base docs - reference via submodule
❌ Don't require Factory to build - templates must build as normal solutions
Related Documents¶
- Template Architecture Specification - First-class technical specification for template hierarchy, inheritance, and composition (authoritative contract)
- Template Overlays Specification - Detailed specification for overlay system, versioning, and compatibility
- Template Architecture Overview - Business-oriented overview
- Extensibility Guide - How to extend base infrastructure
- ADR-0002 - Template Layering - Architecture decision record
- Microservice Template - ConnectSoft.MicroserviceTemplate (extended template) specification