Step-by-Step Guide to Building Custom .NET Templates

Introduction
The .NET SDK provides a powerful templating engine that allows developers to create reusable templates for projects, files, and solution structures. This guide covers how to create, package, and distribute custom templates using the dotnet new
command-line interface.
Understanding .NET Templates
Templates in .NET are packages that contain source files and a configuration that determines how those files should be transformed when instantiated. They provide a way to standardize project structures, apply consistent patterns, and save time when creating new applications or components.
Key Concepts
Template: A set of files and folders that can be transformed into a working project or component
Template Package: A NuGet package containing one or more templates
Template Engine: The system that processes templates and generates output
Template Structure
A basic template consists of:
Source Files and Folders: The content that will be used to generate new projects
Configuration Files: JSON files that control how the template behaves
The .template.config Directory
Every template must have a .template.config
directory at its root containing at least a template.json
file. This file provides metadata and configuration for the template.
template.json
The template.json
file defines how the template works. Here's a breakdown of the essential fields:
{
"$schema": "http://json.schemastore.org/template",
"author": "Your Name",
"classifications": ["Category1", "Category2"],
"identity": "Your.Template.Identity",
"name": "User-friendly Template Name",
"shortName": "template-shortname",
"sourceName": "TemplateSourceName",
"preferNameDirectory": true,
"tags": {
"language": "C#",
"type": "project"
}
}
$schema: Reference to the JSON schema
author: Creator of the template
classifications: Categories for organizing templates
identity: Unique identifier for the template
name: Display name for the template
shortName: Command-line alias for the template
sourceName: The name in source files to be replaced with the user's specified name
preferNameDirectory: Whether to create a directory for the output
tags: Metadata for filtering templates
Advanced Template Configuration
Parameters and Symbols
Templates can define parameters that users can specify when creating a new instance:
"symbols": {
"ParameterName": {
"type": "parameter",
"datatype": "bool",
"defaultValue": "false",
"description": "Parameter description"
}
}
Conditional Content
You can include or exclude files based on parameter values:
"sources": [
{
"modifiers": [
{
"condition": "(!ParameterName)",
"exclude": ["ExcludedFolder/**/*"]
}
]
}
]
Post-Creation Actions
You can define actions to be executed after the template is instantiated:
"postActions": [
{
"description": "Additional setup steps",
"manualInstructions": [
{
"text": "Instructions for the user after template creation"
}
],
"actionId": "CB9A6CF3-4F5C-4860-B9D2-03A574959774",
"continueOnError": true
}
]
Packaging and Distribution
Creating a NuGet Package
To distribute your template, you need to create a NuGet package:
- Create a
.csproj
file to define the package:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageType>Template</PackageType>
<PackageVersion>1.0.0</PackageVersion>
<PackageId>Your.Template.Package</PackageId>
<Title>Your Template Package</Title>
<Authors>Your Name</Authors>
<Description>Your template description</Description>
<PackageTags>dotnet-new;templates;yourKeywords</PackageTags>
<TargetFramework>netstandard2.0</TargetFramework>
<IncludeContentInPack>true</IncludeContentInPack>
<IncludeBuildOutput>false</IncludeBuildOutput>
<ContentTargetFolders>content</ContentTargetFolders>
<NoWarn>$(NoWarn);NU5128</NoWarn>
<NoDefaultExcludes>true</NoDefaultExcludes>
</PropertyGroup>
<ItemGroup>
<Content Include="content/**/*" Exclude="content/**/bin/**;content/**/obj/**" />
<Compile Remove="**/*" />
</ItemGroup>
</Project>
- Organize your files:
YourTemplatePackage/
├── YourTemplatePackage.csproj
└── content/
├── .template.config/
│ └── template.json
└── YourTemplateFiles/
- Build the package:
dotnet pack -c Release
Installing Templates
Templates can be installed from various sources:
- From a NuGet package:
dotnet new install Your.Template.Package
- From a local .nupkg file:
dotnet new install path/to/Your.Template.Package.1.0.0.nupkg
- From a file system directory:
dotnet new install path/to/template/directory
Using Templates
Once installed, you can use your template with:
dotnet new template-shortname -n ProjectName [--parameter1 value1]
Template Localization
Templates can be localized to display in different languages. Create a localize
folder in the .template.config
directory with JSON files named according to the language code:
.template.config/
├── template.json
└── localize/
├── templatestrings.en-US.json
└── templatestrings.es-ES.json
Each localization file contains key-value pairs matching the fields in template.json
that should be translated.
Visual Studio Integration
To make your template appear in Visual Studio's "New Project" dialog:
- Add Visual Studio metadata to the
template.json
:
"tags": {
"language": "C#",
"type": "project",
"vs-workload": "dotnetcore"
}
- For complete integration, consider creating a Visual Studio Extension (VSIX) package.
Best Practices
Clear naming: Choose descriptive, specific names for your templates
Good documentation: Include clear descriptions and examples
Minimal dependencies: Avoid unnecessary dependencies
Thoughtful defaults: Provide sensible default values for parameters
Testing: Test your templates in various environments before distribution
Versioning: Follow semantic versioning for your template packages
Organization: Keep templates focused and organized by functionality
Troubleshooting
Common Issues
Template Not Found: Ensure the template is installed correctly
File Not Included: Check your include/exclude patterns
Parameter Not Working: Verify parameter configuration in
template.json
Template Not Visible in VS: Check Visual Studio integration settings
Debugging
For detailed logs when using templates:
dotnet new template-shortname -n ProjectName --verbosity diagnostic
Conclusion
Custom .NET templates are a powerful way to standardize code structures, enforce architectural patterns, and improve productivity. By following this guide, you can create, package, and distribute templates that will help your team or the wider .NET community build better software more efficiently.
Resources
Subscribe to my newsletter
Read articles from Rick directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Rick
Rick
15+ years of experience having fun building apps with .NET I began my professional career in 2006, using Microsoft technologies where C# and Windows Forms and WPF were the first technologies I started working with during that time. I had the opportunity to actively participate in the Windows ecosystem as an MVP and Windows 8/Windows Phone application developer from 2013-2018. Throughout my career, I have used Azure as my default cloud platform and have primarily worked with technologies like ASP.NET Core for multiple companies globally across the US, UK, Korea, Japan, and Latin America. I have extensive experience with frameworks such as: ASP.NET Core Microsoft Orleans WPF UWP React with TypeScript Reactive Extensions Blazor I am an entrepreneur, speaker, and love traveling the world. I created this blog to share my experience with new generations and to publish all the technical resources that I had been writing privately, now made public as a contribution to enrich the ecosystem in which I have developed my career.