Maintain the catalog
The site only lists public, non-archived repositories under nathanmcnulty that start
with azd- and contain an azure.yaml file at the root of the default branch.
Add a newly published template
- Publish the repository on GitHub with an
azd-prefix and a rootazure.yamlfile. - Give the repository a useful GitHub description and topics so the automatic fallback metadata is meaningful.
- Add
.azd/catalog.jsonto the template repository when it needs curated catalog metadata. - Validate the metadata, then run a local website build or request an immediate refresh.
The build regenerates src/generated/solutions.ts from GitHub metadata and rewrites the generated
solution guide pages under docs/solutions/. The catalog sync workflow performs the same full
discovery after an immediate dispatch and once per day as a fallback.
Repository-owned metadata
Curated metadata normally belongs in the template repository at .azd/catalog.json. This keeps the
catalog description and deployment guidance next to the solution they describe. The stable schema is
catalog/catalog.schema.json.
Every field is optional, but supplied values are strict: unknown properties, empty strings, duplicate
array values, invalid booleans, and non-positive solutionCount values fail generation.
{
"title": "Example workload",
"summary": "One-sentence explanation of what the template deploys.",
"tags": ["Tag One", "Tag Two"],
"highlights": [
"Important selling point",
"Another useful detail"
],
"featured": false,
"solutionCount": 1,
"quickstartCommands": [
"azd init -t nathanmcnulty/azd-example",
"azd up"
]
}
Validate a metadata file from this repository without running discovery:
npm run validate:catalog -- path\to\.azd\catalog.json
Then validate the generated site locally:
npm run build
Editorial overrides
Use catalog/overrides.json only when the website needs to editorially replace repository-owned
metadata. Overrides use the same fields plus repoName. Precedence is field-level: a field supplied
by the local override replaces that field from .azd/catalog.json; repository-owned fields that are
not overridden remain in effect. GitHub descriptions, topics, and generator defaults fill any fields
missing from both sources.
{
"repoName": "azd-example",
"featured": true,
"summary": "Website-specific editorial summary."
}
Request an immediate refresh
Template repositories can send a repository_dispatch event to nathanmcnulty/azd-website with
event type azd-catalog-updated. The optional payload is validated for logging only; it is never
trusted as a local path and does not restrict discovery to one repository.
{
"event_type": "azd-catalog-updated",
"client_payload": {
"repository": "nathanmcnulty/azd-example",
"ref": "main",
"catalogPath": ".azd/catalog.json"
}
}
The source repository needs a fine-grained token or GitHub App token that can call the website
repository's dispatch endpoint. Store it as a source-repository secret such as
AZD_CATALOG_DISPATCH_TOKEN and grant Contents: read and write access to
nathanmcnulty/azd-website. If the dispatch is unavailable or fails, the daily scheduled sync remains
the fallback.
The website repository also requires CATALOG_SYNC_TOKEN with Contents: read and write and
Pull requests: read and write access so the sync workflow can update automation/sync-catalog
and create its pull request under read-only default workflow permissions.
GitHub API notes
The generator uses the public GitHub API. For a small personal catalog, anonymous access is
usually fine. If you want a higher rate limit during local builds or CI, set GITHUB_TOKEN
before running the build.