Skip to content

Template Architecture Specification

This document is the authoritative technical specification for ConnectSoft's template and overlay system. It serves as the contract for both humans and agents working with templates, defining the rules, mechanisms, and patterns that govern template hierarchy, inheritance, composition, and extension.

Important

This specification defines the technical contract for template architecture. All template implementations, Factory agents, and human developers must adhere to these rules and patterns.

Document Purpose

This specification provides:

  • Complete technical contract for template hierarchy and inheritance
  • Rules and mechanisms for template JSON/CLI inheritance
  • Build-time vs generation-time extension patterns
  • Reference wiring mechanisms for tests, docs, and infrastructure
  • Authoritative source for agents and developers

For business-oriented overviews, see Template Architecture Overview. For practical guides, see Template Layering Guide and Extensibility Guide.

Template Hierarchy & Inheritance

Base Microservice Template

The Base Microservice Template (MicroserviceTemplate.Base) is the canonical foundation for all specialized templates. It provides:

Structure:

  • Solution layout (Host, Domain, Application, Infrastructure, Tests)
  • Common bootstrapping code (Program.cs, Host configuration)
  • Base health checks and resilience patterns
  • Base testing infrastructure
  • Base documentation structure
  • Base template metadata (template/template.json)

Responsibilities:

  • Define canonical microservice structure
  • Provide extension points (interfaces, abstract classes)
  • Establish common patterns (Clean Architecture, DDD, event-driven)
  • Maintain domain-agnostic infrastructure
  • Define base template parameters and symbols

Constraints:

  • MUST NOT contain domain-specific logic (no Identity, Auth, Audit, etc.)
  • MUST be fully buildable as a normal .NET solution
  • MUST provide extension points for specialized templates
  • MUST define all base template.json parameters

Identity Backend Template (Overlay)

The Identity Backend Template is a specialized template that extends the base template with Identity domain logic.

Structure:

  • Includes base template as git submodule (base-template/)
  • Adds Identity-specific projects (Identity.Api, Identity.Domain, Identity.Infrastructure)
  • Adds Identity-specific tests (Identity.UnitTests, Identity.AcceptanceTests)
  • Adds Identity-specific documentation
  • Defines Identity overlay metadata (template/identity.template.extend.json)

Responsibilities:

  • Implement Identity domain logic (users, roles, permissions)
  • Extend base infrastructure via extension points
  • Provide Identity-specific template parameters
  • Define Identity overlay composition rules

Inheritance:

  • Inherits all base template structure and code
  • Inherits all base template.json parameters
  • Extends base with Identity-specific functionality
  • Overrides base parameters where appropriate (name, description, defaults)

Auth Server Template (Overlay)

The Auth Server Template is a specialized template that extends the base template with authentication server functionality.

Structure:

  • Includes base template as git submodule (base-template/)
  • Adds Auth-specific projects (Auth.Api, Auth.Domain, Auth.Infrastructure)
  • Adds Auth-specific tests
  • Adds Auth-specific documentation
  • Defines Auth overlay metadata (template/auth.template.extend.json)

Responsibilities:

  • Implement OAuth2/OIDC server functionality
  • Handle token generation and validation
  • Extend base infrastructure via extension points
  • Provide Auth-specific template parameters

Inheritance:

  • Inherits all base template structure and code
  • Inherits all base template.json parameters
  • Extends base with Auth-specific functionality
  • Overrides base parameters where appropriate

Multi-Overlay Composition

Multiple overlays can be composed to create complex templates. For example, an Identity Backend template might combine:

  • Base Template (foundation)
  • Identity Overlay (domain logic)
  • Worker Overlay (background job processing)

Composition Rules:

  1. Base is always first - All compositions start with base template
  2. Overlays applied in order - Order matters for file patching and token replacement
  3. Later overlays override earlier - Conflicts resolved by last overlay wins
  4. Metadata merged sequentially - template.json extended in order

Example Composition:

flowchart TB
    BASE[Base Template<br/>MicroserviceTemplate.Base]
    IDENTITY[Identity Overlay<br/>Domain Logic]
    WORKER[Worker Overlay<br/>Background Jobs]

    BASE --> IDENTITY
    IDENTITY --> WORKER
    WORKER --> FINAL[Final Template:<br/>Base + Identity + Worker]

    style BASE fill:#BBDEFB
    style IDENTITY fill:#C8E6C9
    style WORKER fill:#FFF9C4
    style FINAL fill:#A5D6A7
Hold "Alt" / "Option" to enable pan & zoom

Composition Process:

  1. Start with base template (code, docs, metadata)
  2. Apply Identity overlay (add files, patch base files, extend metadata)
  3. Apply Worker overlay (add files, patch base files, extend metadata)
  4. Resolve all tokens (ServiceName, Namespace, etc.)
  5. Output final flattened template

Template Folder Structure & Organization

Base Template Structure

MicroserviceTemplate.Base/
├── .template.config/
│   └── template.json              # Base template metadata
├── src/
│   ├── Host/                      # Host project (Program.cs, Startup)
│   ├── Domain/                    # Base domain abstractions
│   ├── Application/               # Base application layer
│   └── Infrastructure/            # Base infrastructure
├── tests/
│   └── Base.Testing.Infrastructure/  # Base test infrastructure
├── docs/
│   ├── overview.md                # Base documentation
│   ├── architecture.md            # Base architecture docs
│   └── getting-started.md         # Base getting started
└── template/
    ├── template.json              # Base template.json
    ├── ide.host.json              # IDE configuration
    └── dotnetcli.host.json        # CLI configuration

Specialized Template Structure

IdentityBackendTemplate/
├── .gitmodules                    # Git submodule configuration
├── base-template/                 # Git submodule -> MicroserviceTemplate.Base
│   └── [base template structure]
├── src/
│   ├── Identity.Api/              # Identity-specific API
│   ├── Identity.Domain/           # Identity domain logic
│   ├── Identity.Infrastructure/   # Identity infrastructure
│   └── Identity.Worker/           # Optional: Identity worker
├── tests/
│   ├── Identity.UnitTests/        # Identity unit tests
│   └── Identity.AcceptanceTests/  # Identity acceptance tests
├── docs/
│   ├── identity-overview.md       # Identity-specific docs
│   ├── identity-auth-flows.md
│   └── identity-metrics.md
├── template/
│   ├── identity.template.extend.json  # Identity overlay metadata
│   └── worker.template.extend.json    # Optional: Worker overlay metadata
├── IdentityBackend.sln            # Solution file (includes base + identity)
└── pack-template.ps1              # Script to build final template artifacts

Git Submodule Integration

Purpose: Enable build-time composition without code duplication.

Configuration:

# In Identity template repo
git submodule add <base-repo-url> base-template

Result:

  • Base template code available at base-template/
  • Base template can be updated independently
  • Specialized template references specific base commit
  • Solution file includes projects from both base and specialized template

Submodule Update Process:

# Update to latest base template
cd base-template
git pull origin main
cd ..
git add base-template
git commit -m "Update base template to latest version"

Template JSON Inheritance System

Base template.json Structure

The base template.json defines canonical parameters that all specialized templates inherit:

Top-Level Fields:

  • name - Template display name
  • shortName - Template short name for dotnet new
  • description - Template description
  • tags - Template tags and classifications
  • author - Template author
  • classifications - Template classifications

Symbols (Parameters):

  • ServiceName - Name of the generated service (MUST inherit)
  • RootNamespace - Root namespace for generated code (MUST inherit)
  • PersistenceType - Type of persistence (MUST inherit)
  • MessagingType - Type of messaging (MUST inherit)
  • UseMassTransit - Whether to use MassTransit (MUST inherit)
  • UseNHibernate - Whether to use NHibernate (MUST inherit)
  • Common infrastructure flags (MUST inherit)

Post-Actions:

  • Restore NuGet packages
  • Run build
  • Run tests (optional)
  • Setup git repository

Extend File Format

Specialized templates define extend files (*.template.extend.json) that specify deltas to the base template.json:

Extend File Structure:

{
  "identityOverrides": {
    "name": "ConnectSoft Identity Backend Service",
    "shortName": "cs-identity-backend",
    "description": "Identity backend service with user management",
    "tags": {
      "connectsoft-template": "identity-backend"
    }
  },
  "symbolOverrides": {
    "ServiceName": {
      "defaultValue": "IdentityService",
      "description": "Name of the Identity service"
    }
  },
  "symbolAdds": {
    "UseExternalIdp": {
      "type": "parameter",
      "datatype": "bool",
      "defaultValue": "false",
      "description": "Enable external identity provider integration"
    },
    "RequireEmailConfirmation": {
      "type": "parameter",
      "datatype": "bool",
      "defaultValue": "true",
      "description": "Require email confirmation for new users"
    }
  },
  "postActionsAdds": [
    {
      "id": "identity-migrations",
      "description": "Run Identity database migrations",
      "actionId": "custom-action-guid"
    }
  ]
}

Inheritance Rules

MUST Inherit (Cannot Override):

  • Core infrastructure parameters: ServiceName, RootNamespace, PersistenceType, MessagingType
  • Base post-actions: restore, build
  • Base primary outputs

CAN Override:

  • Display name, description, tags
  • Default values for some parameters (e.g., ServiceName default)
  • Parameter descriptions (for clarity)

CAN Add:

  • Domain-specific parameters (e.g., UseExternalIdp, RequireEmailConfirmation)
  • Domain-specific post-actions
  • Domain-specific primary outputs

CANNOT Remove:

  • Base parameters (must be present in final template.json)
  • Base post-actions (must be present in final template.json)

Merge Process

The pack script merges base template.json with extend files:

  1. Load base template.json - Start with canonical base
  2. Apply identityOverrides - Override top-level fields
  3. Apply symbolOverrides - Override existing symbol properties
  4. Apply symbolAdds - Add new symbols
  5. Apply postActionsAdds - Add additional post-actions
  6. Apply primaryOutputsAdds - Add additional primary outputs
  7. Validate - Ensure all required fields present
  8. Output - Write final merged template.json

IDE & CLI Configuration Inheritance

ide.host.json Inheritance

The base template defines IDE configuration in template/ide.host.json:

Base Structure:

{
  "symbolInfo": {
    "ServiceName": {
      "shortName": "sn"
    },
    "RootNamespace": {
      "shortName": "rn"
    }
  },
  "forms": {
    "ServiceName": "sn",
    "RootNamespace": "rn"
  }
}

Specialized Template Extension:

  • Specialized templates can add additional symbol shortcuts
  • Specialized templates can add domain-specific forms
  • Base shortcuts MUST be preserved

Merge Rules:

  • Base symbolInfo merged with overlay symbolInfo
  • Base forms merged with overlay forms
  • Conflicts resolved by overlay wins

dotnetcli.host.json Inheritance

The base template defines CLI configuration in template/dotnetcli.host.json:

Base Structure:

{
  "symbolInfo": {
    "ServiceName": {
      "shortName": "sn"
    }
  },
  "forms": {
    "ServiceName": "sn"
  }
}

Specialized Template Extension:

  • Same merge rules as ide.host.json
  • CLI-specific configurations can be added
  • Base configurations MUST be preserved

Build-Time vs Generation-Time Extension

Build-Time Extension

Goal: Enable developers to work on templates as normal .NET solutions.

Mechanisms:

  1. Git Submodules

    • Base template included as submodule
    • Solution file includes projects from both base and specialized template
    • Developer works on concrete application
  2. Project References

    • Specialized projects reference base projects
    • Base test infrastructure referenced by specialized tests
    • Base documentation referenced via submodule paths
  3. Solution File Composition

    <!-- IdentityBackend.sln -->
    <Project Include="base-template\src\Host\Host.csproj" />
    <Project Include="base-template\src\Domain\Domain.csproj" />
    <Project Include="src\Identity.Api\Identity.Api.csproj" />
    <Project Include="src\Identity.Domain\Identity.Domain.csproj" />
    <Project Include="tests\Identity.AcceptanceTests\Identity.AcceptanceTests.csproj" />
    

  4. Documentation References

    • Base docs referenced via relative paths: ../base-template/docs/overview.md
    • Specialized docs extend base structure
    • MkDocs configuration can include both base and specialized docs

Generation-Time Extension

Goal: Produce final flattened template artifact for Factory or dotnet new.

Mechanisms:

  1. Overlay Application

    • Start with base template (code, docs, metadata)
    • Apply overlays in recipe order
    • Resolve all tokens (ServiceName, Namespace, etc.)
    • Output flattened structure
  2. File Operations

    • Add: New files from overlay added to final template
    • Patch: Base files modified via markers or patches
    • Replace: Token replacement (ServiceName, Namespace, etc.)
    • Merge: Documentation and metadata merged
  3. Token Replacement

    • All occurrences of ServiceName replaced with actual service name
    • All occurrences of RootNamespace replaced with actual namespace
    • Domain-specific tokens replaced (e.g., IdentityService)
  4. Documentation Merging

    • Base docs + overlay docs merged into final structure
    • Cross-references updated
    • Table of contents merged

Base Test Projects Extension

Build-Time:

  • Base provides Base.Testing.Infrastructure project
  • Specialized tests reference base test infrastructure
  • Specialized tests implement ITestAppFactory interface
  • Specialized tests extend AcceptanceTestBase class

Example:

// Identity.AcceptanceTests references Base.Testing.Infrastructure
// Identity.AcceptanceTests implements ITestAppFactory
public class IdentityTestAppFactory : ITestAppFactory { }

// Identity tests extend base test class
public class IdentityHealthChecksTests : AcceptanceTestBase
{
    protected override ITestAppFactory AppFactory => new IdentityTestAppFactory();
}

Generation-Time:

  • Base test infrastructure included in final template
  • Specialized test projects included in final template
  • Project references resolved
  • Namespaces updated

Base Documentation Extension

Build-Time:

  • Base docs in base-template/docs/
  • Specialized docs in docs/
  • MkDocs can reference both via relative paths
  • Cross-references use relative paths

Generation-Time:

  • Base docs copied to final template docs/
  • Specialized docs copied to final template docs/
  • Cross-references updated
  • Table of contents merged

Metrics/Options Libraries Extension

Build-Time:

  • Base provides IMetricsFeature interface in ConnectSoft.Extensions.Metrics
  • Base provides IConfigureOptions<T> scanning in ConnectSoft.Extensions.Options
  • Specialized templates implement interfaces
  • Base auto-discovers implementations via DI scanning

Generation-Time:

  • Base infrastructure included in final template
  • Specialized implementations included in final template
  • DI registration code merged
  • All references resolved

Reference Wiring Mechanisms

Base Test Infrastructure → Specialized Services

Mechanism: Interface-based extension points

Base Provides:

// Base.Testing.Infrastructure/ITestAppFactory.cs
public interface ITestAppFactory
{
    HttpClient CreateClient();
    IServiceProvider Services { get; }
    void ConfigureWebHost(Action<IWebHostBuilder> configure);
}

// Base.Testing.Infrastructure/AcceptanceTestBase.cs
public abstract class AcceptanceTestBase
{
    protected abstract ITestAppFactory AppFactory { get; }

    [TestMethod]
    public async Task Health_endpoint_returns_ok()
    {
        var client = AppFactory.CreateClient();
        // ...
    }
}

Specialized Template Implements:

// Identity.AcceptanceTests/IdentityTestAppFactory.cs
public sealed class IdentityTestAppFactory : ITestAppFactory
{
    private WebApplicationFactory<Program> _appFactory;

    public HttpClient CreateClient() => _appFactory.CreateClient();
    public IServiceProvider Services => _appFactory.Services;
    // ...
}

// Identity.AcceptanceTests/IdentityHealthChecksTests.cs
public class IdentityHealthChecksTests : AcceptanceTestBase
{
    protected override ITestAppFactory AppFactory => new IdentityTestAppFactory();
}

Wiring:

  • Base test infrastructure has no knowledge of Identity
  • Identity implements base interface
  • Base test methods work with any implementation
  • Polymorphism enables reuse

Base Documentation → Specialized Documentation

Mechanism: Relative path references and documentation merging

Build-Time:

<!-- In base-template/docs/overview.md -->
See [Identity Overview](../../docs/identity-overview.md) for Identity-specific details.

<!-- In docs/identity-overview.md -->
This extends the [Base Overview](../base-template/docs/overview.md).

Generation-Time:

  • Base docs copied to docs/
  • Specialized docs copied to docs/
  • Relative paths updated
  • Cross-references resolved

Base Metrics/Options Infrastructure → Specialized Implementations

Mechanism: Auto-discovery via dependency injection scanning

Base Provides:

// ConnectSoft.Extensions.Metrics
public interface IMetricsFeature
{
    void Register(IMeterFactory meterFactory);
}

// Base registration
services.Scan(scan => scan
    .FromApplicationDependencies()
    .AddClasses(c => c.AssignableTo<IMetricsFeature>())
    .AsImplementedInterfaces()
    .WithSingletonLifetime());

Specialized Template Implements:

// Identity.Infrastructure/Metrics/IdentityMetricsFeature.cs
public sealed class IdentityMetricsFeature : IMetricsFeature
{
    public void Register(IMeterFactory meterFactory)
    {
        // Register Identity-specific metrics
    }
}

Wiring:

  • Base infrastructure scans for implementations
  • Specialized implementations discovered automatically
  • No explicit registration required
  • Base has no knowledge of Identity

Extension Point Discovery Patterns

Pattern 1: Interface Scanning

  • Base defines interface
  • Base scans for implementations
  • Specialized templates implement interface
  • Auto-discovery at runtime

Pattern 2: Abstract Class Extension

  • Base provides abstract class
  • Specialized templates extend abstract class
  • Base calls abstract methods
  • Polymorphism enables reuse

Pattern 3: Options Pattern

  • Base provides IConfigureOptions<T> scanning
  • Specialized templates implement IConfigureOptions<TOptions>
  • Base auto-discovers and registers
  • Configuration bound automatically

Reference Wiring Diagram

flowchart TB
    subgraph Base["Base Template"]
        BaseTestInfra[Base.Testing.Infrastructure<br/>ITestAppFactory<br/>AcceptanceTestBase]
        BaseMetrics[ConnectSoft.Extensions.Metrics<br/>IMetricsFeature Interface]
        BaseOptions[ConnectSoft.Extensions.Options<br/>IConfigureOptions Scanning]
        BaseDocs[Base Documentation]
    end

    subgraph Identity["Identity Template"]
        IdentityTestFactory[IdentityTestAppFactory<br/>implements ITestAppFactory]
        IdentityTests[IdentityHealthChecksTests<br/>extends AcceptanceTestBase]
        IdentityMetrics[IdentityMetricsFeature<br/>implements IMetricsFeature]
        IdentityOptions[ConfigureIdentityOptions<br/>implements IConfigureOptions]
        IdentityDocs[Identity Documentation]
    end

    BaseTestInfra -.->|Interface Contract| IdentityTestFactory
    BaseTestInfra -.->|Abstract Class| IdentityTests
    BaseMetrics -.->|Interface Contract| IdentityMetrics
    BaseOptions -.->|Interface Scanning| IdentityOptions
    BaseDocs -.->|Relative Paths| IdentityDocs

    style Base fill:#BBDEFB
    style Identity fill:#C8E6C9
    style BaseTestInfra fill:#FFE0B2
    style BaseMetrics fill:#FFE0B2
    style BaseOptions fill:#FFE0B2
Hold "Alt" / "Option" to enable pan & zoom

Build-Time Structure Diagram

flowchart TB
    subgraph IdentityRepo["IdentityBackendTemplate Repository"]
        BaseSubmodule[base-template/<br/>Git Submodule]
        IdentitySrc[src/<br/>Identity Projects]
        IdentityTests[tests/<br/>Identity Tests]
        IdentityDocs[docs/<br/>Identity Docs]
        SolutionFile[IdentityBackend.sln<br/>Includes All Projects]
    end

    subgraph BaseTemplate["MicroserviceTemplate.Base"]
        BaseSrc[src/<br/>Base Projects]
        BaseTests[tests/<br/>Base.Testing.Infrastructure]
        BaseDocs[docs/<br/>Base Docs]
    end

    BaseSubmodule -->|References| BaseTemplate
    IdentitySrc -->|References| BaseSubmodule
    IdentityTests -->|References| BaseSubmodule
    IdentityDocs -->|References| BaseSubmodule
    SolutionFile -->|Includes| BaseSubmodule
    SolutionFile -->|Includes| IdentitySrc
    SolutionFile -->|Includes| IdentityTests

    style IdentityRepo fill:#C8E6C9
    style BaseTemplate fill:#BBDEFB
    style BaseSubmodule fill:#FFF9C4
Hold "Alt" / "Option" to enable pan & zoom