# Release-notes cadence

Internal ops doc. Covers when to write a long-form release article, who writes it, and how the content gets from a `_template.html` copy to the live site.

For the rendered template see `docs/release/_template.html`. For a worked example see `docs/release/v0.0.0-template-example.html`.

## Two surfaces, one source

We maintain two release-notes surfaces. They are linked but not redundant:

| Surface | Source | Tone | Audience |
|---|---|---|---|
| `/changelog` | `lucasmccomb/voxstr:Sources/Voxstr/Resources/CHANGELOG.md` (proxied via `/api/changelog`) | Terse, keep-a-changelog style | Returning users, in-app upgrade card |
| `/docs/release/v{X.Y.Z}` | Hand-written HTML article in this repo | Editorial, narrative, "why it matters" | New users, social shares, marketing posts |

The `CHANGELOG.md` is the source of truth for the *fact* that a release shipped. The article is the source of truth for the *story* of a release.

## When to write an article

Rule of thumb:

- **Major releases (X.0.0)** — required. New backend, new model, new product surface, public launch.
- **Minor releases (0.X.0)** — optional. Write one if the release has at least one feature you would tweet about. Skip if it is a bag of small improvements.
- **Patch releases (0.0.X)** — skip. The line in `CHANGELOG.md` is the whole story.

Always write one for:

- First public launch
- New STT backend (Parakeet -> something else, or a meaningful version bump)
- New cleanup model (MLX swap, quantization change that affects RAM or quality)
- New language support
- Pricing changes that affect existing users
- Security or privacy changes that affect user trust

## Who writes it

Lucas, solo, pre-launch. Post-launch this can be delegated to a "drafted by AI, edited by Lucas" workflow — the template is structured so an LLM can fill placeholders from the `CHANGELOG.md` diff and a list of merged PRs, then a human passes a self-edit before push.

There is no formal review step pre-launch. Self-edit pass before pushing is the bar.

## Workflow

For a release `vX.Y.Z`:

1. Copy the template:
   ```bash
   cp docs/release/_template.html docs/release/vX.Y.Z.html
   ```
2. Replace every `[FILL: ...]` placeholder. Search-and-find them with:
   ```bash
   grep -n '\[FILL:' docs/release/vX.Y.Z.html
   ```
3. Add an entry at the **top** of `docs/release/index.html`. Use the `RELEASE: vX.Y.Z` HTML comment markers so additions stay clearly delimited and any future tooling (RSS, sitemap) has a clean parse target.
4. Cross-link from the in-app changelog. Add a line under the version's heading in `Sources/Voxstr/Resources/CHANGELOG.md` (in the app repo):
   ```
   [Read the full notes →](https://voxstr.com/docs/release/vX.Y.Z)
   ```
   This makes the link surface in both the in-app changelog window and on `/changelog`.
5. Commit the article and the index update on the same PR as the release tag, or on a fast-follow merged before the release goes wide.
6. Push. Cloudflare Pages auto-deploys on push to `main` (1-3 minutes).
7. Smoke-test the live URL: `curl -I https://voxstr.com/docs/release/vX.Y.Z.html` should return 200.

## Length

400-1500 words in the article body (excluding chrome). Anything longer should be split into a separate docs article and linked from the release notes.

The example article (`v0.0.0-template-example.html`) is ~740 words in the body — that is roughly the sweet spot for a major release.

## Tone

Same voice as the rest of the docs and the landing page: direct, technical, no marketing fluff in the body. The "Highlights" bullets at the top are allowed to be punchier — those are what gets quoted on social and pasted into the in-app upgrade card.

Things to avoid:

- "We're excited to announce..." — every release should be exciting; saying so adds nothing.
- "Game-changing" / "revolutionary" / "powerful" — empty calories. Show the change, the reader will rate it.
- Long preamble. Lead with what shipped, then explain why it matters.

Things to lean into:

- Concrete numbers (model size, RAM use, latency).
- Trade-offs, named honestly. If a feature has a downside, say it.
- Links into deeper docs for users who want more.

## Cross-link checklist

For every published release article, before considering the release "done":

- [ ] `docs/release/vX.Y.Z.html` exists and renders cleanly.
- [ ] `docs/release/index.html` has a new entry at the top, inside the `BEGIN/END release list` markers.
- [ ] `Sources/Voxstr/Resources/CHANGELOG.md` includes a `Read the full notes →` link in the version section.
- [ ] `curl -I https://voxstr.com/docs/release/vX.Y.Z.html` returns 200 after Pages deploy.
- [ ] In-app "What's new" surface picks up the link via the changelog parser.

## Future work

- RSS feed at `/docs/release/feed.xml` — deferred until there is real demand. The HTML comment markers in `index.html` are there partly to make a future generator's life easy.
- `og:image` per release — currently uses the site default. Switch to a per-release image once we have a brand template for them.
- A "draft this from CHANGELOG.md diff + PR list" command — captured as a future tool, not blocking.
