ADR-008: Conventional Commits Standard
Date: 2026-01-23 Status: Accepted Deciders: Founder
Context
We need standardized commit messages for:
- Clear history
- Automated changelog generation
- Semantic versioning automation
- Easy navigation of Git history
- Understanding impact of changes
Without standards, commits become:
"fixed bug""updated stuff""WIP"- Useless for understanding changes
Decision
Adopt Conventional Commits specification and enforce it with tooling.
Format
<type>(<scope>): <subject>
<body> (optional)
<footer> (optional)
Types
| Type | Purpose | Example |
|---|---|---|
feat |
New feature | feat(auth): add 2FA support |
fix |
Bug fix | fix(api): resolve null pointer |
docs |
Documentation | docs(readme): update setup |
style |
Code formatting | style(ui): format components |
refactor |
Code refactoring | refactor(db): optimize queries |
perf |
Performance | perf(api): cache OAuth tokens |
test |
Tests | test(auth): add login tests |
chore |
Maintenance | chore(deps): upgrade next |
ci |
CI/CD | ci(actions): add build step |
revert |
Revert commit | revert: "feat(auth): add 2FA" |
Scopes
Define areas of codebase:
auth: Authentication/authorizationverification: ID verificationemail: Email aliasesphone: Phone maskingcards: Virtual cardsoauth: OAuth providerapi: API routesdb: Databaseui: UI componentsconfig: Configuration
Subject Rules
- Lowercase
- No period at end
- Imperative mood ("add" not "added")
- Max 72 characters
- Complete sentence
Body Rules (optional)
- Explain "why", not "what"
- Wrap at 72 characters
- Separate from subject with blank line
Footer Rules (optional)
- Reference issues:
Closes #123 - Breaking changes:
BREAKING CHANGE: API format changed
Examples
Simple Commit
feat(auth): add email verification flow
With Body
feat(auth): add two-factor authentication
Implements TOTP-based 2FA using otpauth library.
Users can enable 2FA in account settings.
Recovery codes are provided during setup.
Closes #45
Breaking Change
feat(api): change OAuth token format
BREAKING CHANGE: OAuth tokens now use JWT format instead of opaque tokens.
Existing tokens will be invalidated. Clients must update token parsing logic.
Closes #78
Bug Fix
fix(verification): handle expired IDs correctly
Previously, expired IDs were approved if face match passed.
Now checks expiration date and rejects if expired.
Fixes #123
Enforcement
Commitlint
Validates commit messages:
// commitlint.config.js
module.exports = {
extends: ["@commitlint/config-conventional"],
};
Husky
Runs commitlint on commit:
# .husky/commit-msg
npx --no -- commitlint --edit $1
GitHub Actions
Validates PR commits:
# .github/workflows/commitlint.yml
- run: npx commitlint --from ${{ base }} --to ${{ head }}
Consequences
Positive
- Readable history:
git log --onelineis meaningful - Automated changelogs: Can generate from commits
- Semantic versioning: Can determine version bumps automatically
- Easy navigation: Find all features, all fixes, etc.
- Code review: Reviewer understands intent immediately
- Debugging: Easy to find when bug was introduced
Negative
- Learning curve: Developers must learn format
- Commit overhead: Takes a few extra seconds per commit
- Rejected commits: Bad messages are rejected, must rewrite
- Discipline required: Easy to get wrong at first
Neutral
- Requires tooling (Husky, Commitlint)
- Works best with English language
Alternatives Considered
1. No Standard
Pros:
- No overhead
- Freedom to write anything
Cons:
- Useless history
- Can't generate changelogs
- Hard to review
- Impossible to navigate
Why rejected: History becomes garbage quickly.
2. Free-Form with Guidelines
Pros:
- Some structure
- Less rigid
Cons:
- Not enforced
- People forget guidelines
- Inconsistent results
Why rejected: Guidelines without enforcement don't work.
3. Custom Format
Pros:
- Tailored to our needs
- No external dependencies
Cons:
- Reinventing wheel
- No tooling support
- Team must learn custom format
Why rejected: Conventional Commits is industry standard with great tooling.
Migration Strategy
Existing Commits
Don't rewrite history. Old commits stay as-is.
New Commits
All new commits must follow format (enforced by hooks).
Team Onboarding
- Read this ADR
- Review examples
- First commit will fail (by design)
- Learn from error message
- Rewrite commit with correct format
- After 5-10 commits, becomes natural
Tools
- Commitlint
- Husky
- Conventional Commits Spec
- Commitizen (optional CLI helper)