skills/write-release-notes/SKILL.md
This skill covers how to write a complete release notes article for a published tldraw SDK release.
All release files live in apps/docs/content/releases/.
| File | Purpose |
|---|---|
next.mdx | Accumulates changes for the upcoming release |
vX.Y.0.mdx | Published releases (immutable except for patch additions) |
Get the version number and find the GitHub release:
gh release view v4.3.0
This shows the release date, tag, and any release notes from GitHub.
List PRs merged between the previous release and this one:
# Find commits between releases
git log v4.2.0..v4.3.0 --oneline --merges
# Or use gh to list PRs
gh pr list --state merged --base main --search "merged:2024-01-01..2024-02-01"
For each PR, get the full details:
gh pr view <PR_NUMBER> --json title,body,labels,author,baseRefName
Look for:
### Release notes section in PR body### API changes section in PR bodyImportant: Only include PRs whose baseRefName is main. PRs merged into feature branches (e.g. default-shape-customization) are not yet released — they will be included when the feature branch itself is merged to main.
List any patch releases for this minor version:
gh release list | grep "v4.3"
For each patch release, find its PRs:
git log v4.3.0..v4.3.1 --oneline --merges
Create apps/docs/content/releases/vX.Y.0.mdx following the style guide.
Every 💥 in the article needs a migration recipe. The tldraw-migrate skill drives off these recipes — it intentionally does not duplicate them in its own SKILL.md, because version-specific knowledge belongs next to the breaking change that introduced it. If the recipe is missing, agents and contributors performing the upgrade have to reverse-engineer it from type defs.
There are two acceptable forms:
For breaking changes with their own featured section (renames, replaced APIs, new patterns), add a <details><summary>Migration guide</summary> block under the section. Include before/after code and call out any silent-compile traps (props the typecheck won't reject, signatures with optional new parameters, etc.):
### 💥 Custom themes with display values
[Description of what changed and why]
<details>
<summary>Migration guide</summary>
`getDefaultColorTheme()` and `DefaultColorThemePalette` have been removed. Use `editor.getCurrentTheme().colors[colorMode]` instead:
```tsx
// Before
const theme = getDefaultColorTheme({ isDarkMode })
// After
const theme = editor.getCurrentTheme()
const colors = theme.colors[editor.getColorMode()]
```
</details>
For one-line 💥 entries in the API changes list, the bullet itself must contain the recipe — name the replacement and any caveats inline:
💥 Replace TLDrawShapeSegment.points with the helper getPointsFromDrawSegment(segment, scaleX, scaleY) so segment points respect the shape's current scale.💥 Remove TLDrawShapeSegment.points. (no replacement → reader has to guess)A symbol that is removed without a replacement is a documentation bug — find the public alternative or, if there genuinely isn't one, say so explicitly so readers know to drop the call site rather than searching for a rename.
Special case — @public → @internal demotions: these compile but disappear from public types. They are still breaking changes for consumers who imported the symbol. Treat them like a removal: mark with 💥, name the public replacement, and explicitly tell readers not to reach for module augmentation to re-expose the demoted symbol.
Check that:
💥 has either a migration guide block or an inline replacement (run grep -nE '💥' apps/docs/content/releases/<file>.mdx and verify each bullet/section)../shared/release-notes-guide.md for guidance on what a release notes article should contain and how to format it.