Day#4: Releasing the First Version — Lessons in Developer-Facing Documentation

After a week or so of bootstrapping a modular backend platform using NestJS, TypeORM, and Turborepo, I finally reached a point where I could tag and release the very first version of one of the internal APIs.

It wasn’t just a matter of bumping a version and pushing a commit. I wanted this release to be documented, understandable, and reproducible — for myself and for anyone who will interact with the codebase in the future.

mariusz
mariusz
20 posts
2 followers

Foundations: Why a Manual RELEASES.md?

I decided early on not to rely solely on autogenerated changelogs like CHANGELOG.md. While useful, they’re geared toward machines and don’t give the clarity or narrative I want for human readers.

Enter RELEASES.md: a structured, manually curated changelog that provides context, highlights technical decisions, and communicates meaningful updates.

This post documents how I structured the release, how I generate and maintain the changelog, and how I integrated it into the workflow alongside changesets.


Setup: Changesets + Manual Releases

The project uses @changesets/cli for versioning packages within a monorepo.

Steps to version a package:

npx changeset          # creates a new changeset file
npx changeset version  # applies version bump & updates CHANGELOG.md
git commit -am "chore(release): bump <package> to x.y.z"

Once the above is done, I generate a manual release note and append it to RELEASES.md.


Example Entry in RELEASES.md

## 📦 @my-org/example-api — version 0.1.0

### ✨ New Features

- Implemented Address module with:
  - Entity + Swagger decorators
  - Full CRUD controller
  - DTO validation
  - Service layer with TypeORM
  - NestJS module integration

### 🧪 Technical Highlights

- Endpoints fully documented using `@nestjs/swagger`
- Route parameter validation via `ParseUUIDPipe`
- DTOs are Swagger-integrated
- Ready for composition in higher-level business flows

---

**Commit:** `chore(release): bump @my-org/example-api to 0.1.0`
**Tag:** `example-api-v0.1.0` 
**Released:** 📅 2025-06-09

Automating the Format (Optional)

I created a reusable template for RELEASES.md entries:

## 📦 <package-name> — version <version>

### ✨ New Features

- ...

### 🧪 Technical Highlights

- ...

---

**Commit:** `<commit-message>` 
**Tag:** `<tag>` 
**Released:** 📅 <date>

Stored as:

./RELEASE_TEMPLATE.md

This template can be copied manually or parsed by a custom release script in Node or Bash if automation is needed in the future.


Commit Hooks for Consistency

To ensure every change is well-formatted and won’t break style guides, I added a pre-commit hook:

npm install --save-dev husky lint-staged
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"

And in package.json:

"lint-staged": {
  "**/*.{ts,js,json,md}": "prettier --write"
}

Summary

Setting up a clean release process takes a bit of effort, but the result is rewarding:

  • Reproducible changelogs
  • Structured documentation for each release
  • Versioned API modules ready for future integration
  • A base for automated changelog publishing if needed

This workflow strikes a healthy balance between automation and clarity — machines help, but humans read.


Opublikowano

w

,

przez

Komentarze

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *