CHANGELOG.md Builder
A good changelog tells users what changed without making them read commit logs. The Keep a Changelog standard gives that structure: newest releases on top, an Unreleased staging area, and a fixed set of categories. This builder assembles a compliant CHANGELOG.md from your release entries so the formatting is correct every time.
How it works
The output starts with the standard header noting the file follows Keep a Changelog and Semantic Versioning. It then renders an ## [Unreleased] section followed by each release as ## [version] - YYYY-MM-DD. Within every section, non-empty categories appear in the canonical order: Added, Changed, Deprecated, Removed, Fixed, Security. Each entry becomes a - bullet. Empty categories are omitted so the file stays clean.
Tips, example, and notes
A typical entry looks like:
## [1.2.0] - 2026-06-06
### Added
- CSV export on the reports page.
### Fixed
- Crash when opening an empty project.
Keep entries written for humans, in past or imperative tense, and avoid raw commit hashes. When you release, promote the Unreleased items into a dated version and open a new empty Unreleased section. Reserve the Security category for vulnerability fixes so they are easy to audit.
Writing good changelog entries
The quality of a changelog depends on the quality of its individual entries. A good entry is written for the person consuming your software — not the person who wrote the code.
Bad entries are either too technical or too vague:
Fix bug— tells the user nothingRefactor authentication module internals— describes your work, not the user’s experienceUpdate dependencies— almost never meaningful to an end user
Good entries describe the change from the user’s perspective:
Fixed: email verification links now work correctly when the link is opened in a different browserAdded: CSV export button on the reports pageSecurity: Patched XSS vulnerability in the comment rendering pipeline (CVE-XXXX-XXXX)
The test is: if someone reads only this one line, do they know whether this release matters to them?
When to bump each version number
Semantic versioning (MAJOR.MINOR.PATCH) maps cleanly to the changelog categories:
| SemVer part | When to bump | Related changelog categories |
|---|---|---|
| PATCH | Bug fix only, backward compatible | Fixed |
| MINOR | New feature, backward compatible | Added, Deprecated |
| MAJOR | Breaking change | Removed, Changed (breaking), any breaking API or behavioural change |
The Security category does not map to a single SemVer increment — a security fix might be a PATCH (if no API changes) or a MAJOR (if the fix requires a breaking change to close a vulnerability). Make the version bump match the actual scope of the change.
Why the Unreleased section matters
The Unreleased section serves as a staging area between your version control history and your official release notes. Keeping changes there as they merge lets you:
- Preview what will be in the next release at any time.
- Group related changes under a single version entry when you release.
- Avoid the pressure of writing release notes at the last minute under a release deadline.
Some teams generate the Unreleased section automatically from conventional commits using tools like standard-version or semantic-release. This builder is for teams that prefer to write their changelog manually, which often produces more human-readable results.