Skip to main content

A SaaS release notes template with a review gate

· 7 min read
Documentation studio

Most SaaS teams do not lack a release notes template. They lack a gate: a point in the release process where someone accountable checks that the notes are true, specific, written for the reader and published on time. Without the gate, the template decays into a list of ticket titles within a quarter. This post gives you both: a template we use, and a review gate that runs in the same pull request flow as the code.

Why release notes go wrong​

The failure modes are predictable, and none of them is about writing talent:

  • They are generated from ticket titles. "PLAT-4411 refactor notif svc" means something to the engineer who wrote it and nothing to an admin deciding whether to tell their team.
  • They bundle. "Bug fixes and performance improvements" is the release notes equivalent of "no comment". Customers who reported a bug cannot tell whether it is fixed.
  • Impact is missing. The note says what changed, not who is affected or what they need to do.
  • Breaking changes are buried in the middle of a list, next to a color tweak.
  • They are late. The feature ships Tuesday, the notes appear Friday, and support spends three days answering questions the notes would have answered.

Every one of these is a process problem. The template helps, but the gate is what fixes it.

Who reads release notes​

Designing the template starts with the readers, and there are more of them than teams assume:

  • Account admins deciding whether a change needs action, training or an announcement to their users.
  • Support agents who need to recognize the change in incoming tickets on day one.
  • Customer success and sales, who use new features in conversations and need the accurate version.
  • Developers integrating with your API, who care about deprecations, new fields and behavior changes.
  • Support bots and search, which will quote your release notes back to customers long after the release.

That list explains the structure: action first for admins, specifics for support, a clear deprecation section for developers, and self-contained entries for search and bots.

The template​

Each release gets one Markdown file. Front matter carries what automation needs; the body carries what readers need, in the order they need it.

---
title: Release 2026.10 – Scheduled exports and SSO changes
date: 2026-10-06
version: "2026.10"
audience: [admins, developers]
---

## Action required

- **SAML certificates:** If you use SSO, upload your new identity provider
certificate under **Settings → Security → SSO** before November 3. After that
date, sign-ins with the old certificate will fail.

## Highlights

- **Scheduled exports.** Admins on the Business and Enterprise plans can now
send any report as a CSV on a daily, weekly or monthly schedule. Go to
**Reports → Export → Schedule**. [Set up a scheduled export](/docs/reports/scheduled-exports)

## New

- ...

## Improved

- ...

## Fixed

- **Invoices:** Invoices downloaded from **Billing → Invoices** now show your tax
ID when one is set. Previously it appeared only in emailed invoices.

## Deprecated and removed

- **API:** The `legacy_status` field on `GET /v2/projects` is deprecated and will
be removed in release 2027.01. Use `status` instead.

## Known issues

- ...

Delete sections that have no entries rather than leaving them empty. If your team already follows the Keep a Changelog convention, its categories (Added, Changed, Deprecated, Removed, Fixed, Security) map cleanly onto these sections; what the template adds is the Action required section at the top, because that is the one admins must not miss.

Rules for each entry​

The template gives the shape; these rules give the content. We put them in the contributor guide and cite them in review:

  1. Lead with what the user can now do or no longer has to do, not with the implementation.
  2. Name the place in the product, in bold, using the exact UI labels.
  3. Say who is affected: plan, role, region or platform. "All users" is a claim; make it deliberately.
  4. Link to the documentation for anything that needs more than two sentences.
  5. One change per entry. If an entry needs "and also", split it.
  6. For breaking changes, answer four questions: what changes, who is affected, when, and what to do.

A before and after makes the difference obvious. Before: "Improved notification service reliability." After: "Notifications: Email alerts for failed payments now arrive within a few minutes of the failure. Previously they could be delayed by up to a day during peak periods." The second one is longer, and it is the only one a support agent can use.

The review gate​

The gate has three parts: routing, automated checks and human review. None of them is heavy.

Routing with CODEOWNERS​

Release notes live in the docs repository, in their own folder, and a CODEOWNERS entry makes sure the right people are asked to review every change:

/release-notes/ @acme/docs @acme/product-ops

The handbook page on review gates covers how we set required reviews so a merge cannot skip them.

Automated checks​

Three checks catch most defects before a human looks. First, a prose linter rule that blocks the vague phrases. In Vale, that is an existence rule:

# styles/ReleaseNotes/Vague.yml
extends: existence
message: "Say what changed instead of '%s'."
level: error
ignorecase: true
tokens:
- bug fixes and improvements
- various bug fixes
- minor improvements
- performance improvements
- under the hood

Second, a small script that checks each file has the front matter and the sections automation and readers rely on:

// scripts/check-release-notes.mjs
import {readFileSync, readdirSync} from 'node:fs';
import {join} from 'node:path';

const DIR = 'release-notes';
const REQUIRED = ['title', 'date', 'version', 'audience'];
let failed = false;

for (const file of readdirSync(DIR).filter((f) => f.endsWith('.md'))) {
const src = readFileSync(join(DIR, file), 'utf8');
const fm = src.match(/^---\n([\s\S]*?)\n---/)?.[1] ?? '';
for (const key of REQUIRED) {
if (!new RegExp(`^${key}:`, 'm').test(fm)) {
console.error(`${file}: missing front matter "${key}"`);
failed = true;
}
}
if (/removed|deprecated/i.test(src) && !src.includes('## Deprecated and removed')) {
console.error(`${file}: mentions a removal but has no deprecation section`);
failed = true;
}
}
process.exit(failed ? 1 : 0);

Third, the site build itself. With onBrokenLinks: 'throw' in Docusaurus, every documentation link in the notes is checked on every pull request, so "see the docs" never points at a page that was renamed last month. The CI job runs all three:

name: release-notes
on:
pull_request:
paths: ['release-notes/**']
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: node scripts/check-release-notes.mjs
- uses: vale-cli/vale-action@v3
with:
files: release-notes
- run: npm run build

Human review, with named roles​

Automation catches form. People catch truth. Each role checks one thing:

  • Product manager: accuracy. Does the note describe what actually shipped, behind which flags, for which plans?
  • Support lead: impact. Will agents recognize this in tickets, and do any macros or help articles need updating the same day?
  • Docs owner: clarity and consistency with the rules above.
  • Engineering owner: only for breaking changes and API deprecations.

Timing: the notes merge before the release​

The rule that makes the gate work: the release notes pull request is part of the release, and the release does not go out until it is approved. In Docusaurus, a clean way to publish notes is a second instance of the blog plugin with its own route, so notes get dates, tags, feeds and archive pages for free:

plugins: [
[
'@docusaurus/plugin-content-blog',
{
id: 'release-notes',
path: 'release-notes',
routeBasePath: 'release-notes',
blogTitle: 'Release notes',
},
],
],

Mark the file draft: true while the release is being prepared, since drafts are left out of production builds, and remove the flag in the final commit on release day.

Release notes are one of the clearest places where documentation behaves like a product, which is the argument we make in documentation is a product, not a release checklist. The handbook page on CI/CD publishing covers the pipeline the gate runs in.

Hand off the routine​

If you want this process set up and run for you, our release notes service covers the template, the gate and the writing each release, as a retainer from $900/month. Tell us your release cadence and where notes live today through the contact page. We reply within 1 business day.