From 635e173217d3ab507dddb4f2eb1287bd0cb5f628 Mon Sep 17 00:00:00 2001 From: Stephen Walsh <868017+stphnwlsh@users.noreply.github.com> Date: Fri, 6 Nov 2026 02:06:27 +0000 Subject: [PATCH] Help people find the templates in search Short name aliases, brand short names, search words in the name, a Lean Mean Clean Apps classification and more package tags, so dotnet new search, --tag and nuget.org all find the family. --- .agents/skills/template-authoring/SKILL.md | 13 ++++++++++++- .github/workflows/build-pipeline.yml | 2 +- .template.config/template.json | 12 ++++++++++-- NUGET.md | 2 ++ README.md | 2 ++ template/template.csproj | 4 ++-- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/.agents/skills/template-authoring/SKILL.md b/.agents/skills/template-authoring/SKILL.md index 94a0535..4236e7b 100644 --- a/.agents/skills/template-authoring/SKILL.md +++ b/.agents/skills/template-authoring/SKILL.md @@ -45,6 +45,17 @@ A toggle's inputs, such as `authority` and `audience`, are separate symbols, ena The package includes `src/`, `tests/`, `docs/RUN.md`, the root build files, `AGENTS.md`, `CLAUDE.md`, the persona and the engineering skills. It also packs `template/ci.yml` as the generated solution's `.github/workflows/ci.yml`, a small pipeline with no template name in it. It leaves out the rest of `.github/`, the community files and the repository and maintainer skills, which only make sense in the template repository. Those skills are listed in `RepositorySkills` in `template/template.csproj`; a new one is added there. The pipeline fails a package over 1 MB. +## Getting found + +`dotnet new search` and `dotnet new list` match any part of the template `name` or of any short name, and nothing else. `--tag` matches a whole classification, and nuget.org and `dotnet package search` read the package's `PackageTags`. So every template puts its search words in all three: + +- `shortName` is a list. The first entry is the template's own name in lower case, such as `cleanminimalapi`, and never changes. After it come one or two shorter aliases, such as `cleanminimal` or `cleanmcp`, then `lmca-` and `leanmeancleanapps-`, where the key is the docs site's (`minimalapi`, `mcp`, `graphql`, `webapi`, `lambda`). Those two make searches for clean, lmc, lmca, lean, mean and leanmeanclean find every template. Never a bare short name such as `mcp`, which clashes with other people's templates. +- The `name` and the package `Title` match, and carry the words people search for that the name lacks, such as "(MCP)", "(Hot Chocolate)", "(Controllers)" or "AWS". +- Every template has the `Lean Mean Clean Apps` classification, so `dotnet new list --tag "Lean Mean Clean Apps"` shows the family. +- `PackageTags` carry the tags all five share, brand words included (`clean`, `cleanarchitecture`, `lmc`, `lmca`, `leanmeanclean`, `leanmeancleanapps`), then the template's own. + +The README and `NUGET.md` name the aliases under the install commands, and the docs site's template options page lists them. The pipeline's Verify Template step uses the first short name. + ## Steps 1. Change `template.json` or `template.csproj`. `template.csproj` references `Microsoft.TemplateEngine.Authoring.Tasks`, Microsoft's template validator, which checks `.template.config` on every build and pack; keep its output free of messages, not just errors. A new option also goes in `dotnetcli.host.json` with a short flag that doesn't clash with `dotnet new`'s own (`-n`, `-o`, `-lang`, `-h`), and in `ide.host.json` with `isVisible` set, or Visual Studio hides it. @@ -74,7 +85,7 @@ The package includes `src/`, `tests/`, `docs/RUN.md`, the root build files, `AGE ## Don't -- Change `identity` or the first `shortName`; existing installs and docs depend on them. Adding a shorter alias after it is fine. +- Change `identity` or the first `shortName`; existing installs and docs depend on them. Adding aliases after it is fine (see Getting found). - Make a primary output that isn't a project visible to the CLI. The restore post action restores every primary output it can see, so `docs/RUN.md` carries the same `HostIdentifier` condition as the action that opens it. - Add a `.sln`. The solution is `.slnx` only, and `primaryOutputs`, the Dockerfile and the package all point at it. - Reuse a short flag across options, or give one to `--no-restore`; the `dotnet new` templates from Microsoft leave it long, and so do we. diff --git a/.github/workflows/build-pipeline.yml b/.github/workflows/build-pipeline.yml index 38813f5..07214a3 100644 --- a/.github/workflows/build-pipeline.yml +++ b/.github/workflows/build-pipeline.yml @@ -219,7 +219,7 @@ jobs: # would fail the generated solution's format check. run: | dotnet new install packages/*.nupkg - SHORT_NAME=$(jq -r .shortName .template.config/template.json) + SHORT_NAME=$(jq -r '[.shortName] | flatten | first' .template.config/template.json) SOURCE_NAME=$(jq -r .sourceName .template.config/template.json) # Nothing of the template itself leaks into a generated solution: no toggle markers, and no trace of the diff --git a/.template.config/template.json b/.template.config/template.json index 1625474..1cdaf78 100644 --- a/.template.config/template.json +++ b/.template.config/template.json @@ -7,15 +7,23 @@ "API", "Service", "GraphQL", + "Hot Chocolate", + "Lean Mean Clean Apps", "Clean Architecture" ], "identity": "CleanGraphQLApi.Template", "groupIdentity": "CleanGraphQLApi", "generatorVersions": "[1.0.0.0-*)", "precedence": "100", - "name": "Clean GraphQL API Template", + "name": "Clean GraphQL API (Hot Chocolate) Template", "description": "A GraphQL API on Hot Chocolate and .NET 10, built with Clean Architecture minus the ceremony.", - "shortName": "cleangraphqlapi", + "shortName": [ + "cleangraphqlapi", + "cleangraphql", + "cleanhotchocolate", + "lmca-graphql", + "leanmeancleanapps-graphql" + ], "tags": { "language": "C#", "type": "solution" diff --git a/NUGET.md b/NUGET.md index 8922971..6216a19 100644 --- a/NUGET.md +++ b/NUGET.md @@ -25,6 +25,8 @@ dotnet new cleangraphqlapi --name WorksOnMyMachine.Movies --authorName "Your Nam cd WorksOnMyMachine.Movies ``` +`cleangraphql` and `cleanhotchocolate` work too, for anyone who'd rather not type `cleangraphqlapi` every time, and so do `lmca-graphql` and `leanmeancleanapps-graphql`. `dotnet new search leanmeanclean` lists the whole family. + | Option | Default | What it does | | --- | --- | --- | | `--name`, `-n` | The folder's name | Names the solution and its root namespace | diff --git a/README.md b/README.md index 6796a76..da69b0d 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ dotnet new cleangraphqlapi --name WorksOnMyMachine.Movies --authorName "Your Nam cd WorksOnMyMachine.Movies ``` +`cleangraphql` and `cleanhotchocolate` work too, for anyone who'd rather not type `cleangraphqlapi` every time, and so do `lmca-graphql` and `leanmeancleanapps-graphql`. `dotnet new search leanmeanclean` lists the whole family. + | Option | Default | What it does | | --- | --- | --- | | `--name`, `-n` | The folder's name | Names the solution and its root namespace | diff --git a/template/template.csproj b/template/template.csproj index 593a5af..7aa9c51 100644 --- a/template/template.csproj +++ b/template/template.csproj @@ -4,10 +4,10 @@ net10.0 Template CleanGraphQLApi.Template - Clean GraphQL API Template + Clean GraphQL API (Hot Chocolate) Template Stephen Walsh A dotnet new template for a GraphQL API using Hot Chocolate, built with a streamlined Clean Architecture on .NET 10. - dotnet;csharp;dotnet-template;template;clean-architecture;cqrs;mediator;fluentvalidation;mapperly;entity-framework-core;docker;aspnetcore;graphql;hotchocolate + dotnet;csharp;dotnet-template;template;clean-architecture;cqrs;mediator;fluentvalidation;mapperly;entity-framework-core;docker;aspnetcore;graphql;hotchocolate;clean;cleanarchitecture;lmc;lmca;leanmeanclean;leanmeancleanapps;project-template;solution-template;net10;dotnet10;sqlite;efcore;serilog;opentelemetry;graph;graphql-api;graphql-server;hot-chocolate;chillicream;relay;dataloader;nitro;api https://leanmeancleanapps.github.io/graphql/ https://github.com/LeanMeanCleanApps/CleanGraphQLApi git