Skip to content

The default changelog renderer for nx release generates a changelog entry for each released project similar to the following:

## 7.9.0 (2024-05-13)
### 🚀 Features
- **rule-tester:** check for missing placeholder data in the message ([#9039](https://github.com/typescript-eslint/typescript-eslint/pull/9039))
### ❤️ Thank You
- Kirk Waiblinger
- Sheetal Nandi
- Vinccool96

There are a few options available to modify the default changelog renderer output. They can be applied to both workspaceChangelog and projectChangelogs in exactly the same way. All four options are true by default:

nx.json
{
"release": {
"changelog": {
"projectChangelogs": {
"renderOptions": {
"authors": true,
"applyUsernameToAuthors": true,
"commitReferences": true,
"versionTitleDate": true
}
}
}
}
}

Whether the commit authors should be added to the bottom of the changelog in a "Thank You" section. Defaults to true.

If authors is enabled, controls whether or not to try to map the authors to their GitHub usernames using https://ungh.cc (from https://github.com/unjs/ungh) and the email addresses found in the commits. Defaults to true.

You should disable this option if you don't want to make any external requests to https://ungh.cc

NOTE: Prior to Nx v21, this option was named mapAuthorsToGitHubUsernames.

Whether the commit references (such as commit and/or PR links) should be included in the changelog. Defaults to true.

Whether to include the date in the version title. It can be set to false to disable it, or true to enable with the default of (YYYY-MM-DD). Defaults to true.

If you prefer a more minimalist changelog, you can set all the options to false, like this:

nx.json
{
"release": {
"changelog": {
"projectChangelogs": {
"renderOptions": {
"authors": false,
"applyUsernameToAuthors": false,
"commitReferences": false,
"versionTitleDate": false
}
}
}
}
}

Which will generate a changelog that looks similar to the following:

## 7.9.0
### 🚀 Features
- **rule-tester:** check for missing placeholder data in the message

For complete control over changelog formatting, provide a workspace path or package specifier for a JavaScript or TypeScript module that exports a class extending DefaultChangelogRenderer. Use module.exports from a CommonJS module or a default export from an ECMAScript module (ESM).

The examples use CommonJS JavaScript because it works without additional TypeScript tooling or ESM configuration. You can use ESM or TypeScript instead when your workspace is configured to load it. For workspace files, start the path with {workspaceRoot} because plain relative paths such as ./tools/custom-changelog-renderer.js don't resolve from the workspace root.

nx.json
{
"release": {
"changelog": {
"projectChangelogs": {
"renderer": "{workspaceRoot}/tools/custom-changelog-renderer.js",
},
},
},
}

Override render() when you want to replace or wrap the complete changelog output. For a targeted change, override one of the protected rendering or formatting methods instead. The inherited render() method continues to assemble every section you don't customize. Common extension points include renderVersionTitle(), renderChangesByType(), renderBreakingChanges(), renderDependencyBumps(), renderAuthors(), and helpers such as formatChange().

Override a protected method to change one part of the changelog while keeping the rest of the default output:

tools/custom-changelog-renderer.js
const DefaultChangelogRenderer =
require('nx/release/changelog-renderer').default;
module.exports = class CustomRenderer extends DefaultChangelogRenderer {
renderVersionTitle() {
return `# Release ${this.changelogEntryVersion}`;
}
};

Override render() without calling super.render() when you want to generate the complete entry:

tools/custom-changelog-renderer.js
const DefaultChangelogRenderer =
require('nx/release/changelog-renderer').default;
module.exports = class CustomRenderer extends DefaultChangelogRenderer {
async render() {
return `# ${this.changelogEntryVersion}\n\nGenerated by our release workflow`;
}
};

Suppose your release process publishes extended notes to a separate internal site. This hypothetical renderer calls super.render() to keep the default changelog, then appends a link:

tools/custom-changelog-renderer.js
const DefaultChangelogRenderer =
require('nx/release/changelog-renderer').default;
module.exports = class CustomRenderer extends DefaultChangelogRenderer {
async render() {
const changelog = await super.render();
if (!changelog) return changelog;
const releaseUrl = `https://releases.example.com/releases/v${this.changelogEntryVersion}`;
return `${changelog}\n\nSee the [extended release notes](${releaseUrl}).`;
}
};

The release URL uses the default v{version} tag pattern for fixed releases. Adjust it when you use independent releases or a custom release tag pattern.

Some extension points run only when their corresponding gate returns true. For example, Nx calls renderBreakingChanges(), renderDependencyBumps(), and renderAuthors() only when hasBreakingChanges(), hasDependencyBumps(), or shouldRenderAuthors() returns true.

The typescript-eslint custom changelog renderer is a real-world JavaScript example that follows this pattern.