Add Changelog Entry¶
Author a new changelog entry for the Quoi de neuf ? page in bricksoffice-projects. The entry is for non-technical end users (ops, customer-success, finance, sales). It must read like a product release note — not a commit log.
When to use¶
- User asks to "add a changelog entry", "release a new version of the BO", "publish what's new", or runs
/add-changelog-entry. - Concrete reference:
projects/bricksoffice-projects/src/modules/changelog/data/entries.tsalready holds the seed entry (v1.0.0, 2026-05-20). New entries are prepended soentries[0]is always the latest.
Inputs to gather (ask if not provided)¶
- Version — bumped by
patch(default),minor, ormajorfromentries[0].version. The version renders on the page as av1.1.0badge next to the date, AND is used as the localStorage key (bo:changelog:lastSeenVersion) so the red dot clears when the user has seen the latest entry. Don't bumppackage.json; the data file IS the source of truth. - Release title — short headline that frames the release for the user (e.g.
M5 · Virements à assigner). The team usesM<n> ·prefixes internally; keep them only in thetitle, never indescriptioncopy. - Diff scope — default is
git logsince the latest entry'sdate. The user can override with a different--sinceor a branch name (<branch>..HEAD).
Scope of a changelog entry¶
A changelog entry ships atomically with the PR that introduces it. Include changes from the current branch even if they're not yet committed — run git status --short plus a working-tree diff and treat staged-and-untracked files as in-scope. The seed v1.0.0 already followed this rule by forward-listing /virements-a-assigner before its route file landed. Only exclude truly speculative scaffolds that won't ship in this PR.
Concrete signal that the bundle ships together: the changelog data file (entries.ts) itself is uncommitted on the branch you're working on.
Procedure¶
1. Read the current state¶
- Read
src/modules/changelog/data/entries.ts. - Extract
entries[0]—version(for the bump) anddate(for thegit log --sincecutoff). Abort if the file or array is empty.
2. Collect candidate commits¶
Run, scoped to paths that actually affect the BO Projects UX:
git log --no-merges --since="<latestDate>" \
--pretty=format:'%h %s' --date=short HEAD -- \
projects/bricksoffice-projects \
projects/common/back-office \
projects/common/both/api-communication-bricksoffice
If the user wants the new entry to summarise the current branch only (typical case when a feature ships from a single branch), prefer:
where <baseBranch> is develop (this app's main branch — see CLAUDE.md).
Optional context for hints:
2b. Second pass — UX wins hidden inside refactors and shared-lib changes¶
Commit subjects routinely undersell user-facing wins. feat(dependencies): add dnd-kit unlocks drag-reorder columns; feat(management-fees) smuggled in the DisabledTooltip primitive and the column-config UI used across every table. Always run this second pass before filtering — read the file list, not just the subject.
# Added files in BO design-system — new primitives usually map to a user-visible UX win
git log --diff-filter=A --name-only --pretty=format:'COMMIT %h %s' <latestRef>..HEAD -- \
projects/common/back-office/src/design-system/components \
projects/common/back-office/src/design-system/tables \
projects/common/back-office/src/design-system/inputs \
projects/common/back-office/src/design-system/modals
# Working tree (since the bundle ships atomically — see Scope above)
git status --short
git diff --stat HEAD -- projects/common/back-office/src/design-system projects/bricksoffice-projects
# Rule files — a new bullet in table.mdc / form.mdc / modal.mdc almost always
# reflects a user-visible affordance worth a changelog line.
git diff <latestRef>..HEAD -- .cursor/rules/bo/
Map common BO file changes to user-facing copy (extend this table over time):
| BO file added/changed | Surfaces as user-facing |
|---|---|
tables/hooks/use-table-column-config.ts + dnd-kit deps |
Personnalisation des colonnes (glisser-déposer, épinglage, masquer, réinitialiser) |
tables/hooks/use-table-page-size-persistence.ts or persistAs: arg on use-table-url-search |
Persistance de la taille de page par tableau |
tables/hooks/use-compact.ts (module singleton replacing per-table provider) |
Préférence d'affichage compact/étendu persistante |
tables/exporters/xlsx.* or exportTableToXlsx wired into actions-menu.tsx |
Export Excel (XLSX) en plus du CSV |
components/disabled-tooltip.tsx |
Boutons désactivés plus explicites (raison au survol) |
inputs/read-only-field.tsx |
Champs en lecture seule plus lisibles dans les modales |
New cell-highlight-* / row-highlight-* utility in styles/tables.css |
Mise en avant visuelle des retards / valeurs anormales |
New status-badge-tone-* utility in styles/badges.css |
Badges de statut homogènes |
New modules/changelog/ or routes/_authenticated/changelog.tsx |
Page « Quoi de neuf ? » |
3. Filter aggressively — this is for end users¶
Keep only commits whose effect a non-technical user can see or feel.
| Conventional prefix | Decision |
|---|---|
feat: / feat(...) |
Keep as feature only if it changes something the user sees or does. feat(api): for a not-yet-consumed endpoint → skip. |
fix: / fix(...) |
Keep as fix only if it's a user-facing bug. Test fixes, CI fixes, type-only fixes → skip. |
perf: |
Keep as improvement. Frame the benefit, not the mechanism ("la liste se charge plus vite" — not "memoised the row renderer"). |
| security fixes / CVE-driven dep bumps | Keep as improvement with copy "Renforcement de la sécurité de l'application.". Never disclose the vector, the CVE id, or the package name. |
refactor: |
Skip pure internal reshuffles (file moves, dead-code removal). Keep as improvement when the refactor re-shapes a user-visible affordance — e.g. TableCompactProvider → module-level useCompact() makes the compact preference app-wide instead of per-table, which the user feels. The 2b table is your reference. |
style:, docs:, test:, ci:, chore:, build: |
Skip outright. Dep bumps included — except when 2b shows the dep unlocks a UX win (e.g. dnd-kit → drag-reorder columns); then keep as improvement and frame the win, not the dep. |
| Anything ambiguous | Check the 2b table and the rule-file diffs first; if still unclear, ask the user. Better to skip than ship refactor(table): … user-facing. |
4. Infer deep-links from new route files¶
For each kept feature, scan the diff for new route files under src/routes/_authenticated/:
git diff --name-only --diff-filter=A <latestRef>..HEAD -- 'projects/bricksoffice-projects/src/routes/_authenticated/*'
Map the file path to a route path:
src/routes/_authenticated/foo.tsx→to: '/foo'src/routes/_authenticated/projects/bar.tsx→to: '/projects/bar'src/routes/_authenticated/index.tsx→to: '/'
If multiple new route files match and you can't unambiguously assign one to the feature, ask the user.
5. Rewrite each kept commit as user-facing French¶
For every commit that survived the filter, write:
label— 5–10 words in plain French. Use the domain noun ("Virements à assigner", "Échéancier"). Never quote the codebase: no module / file / endpoint / hook names, no commit hashes, no PR numbers, no English, noM5, no[BRI-...].description— 1–2 sentences, ~25 words max, plain French. Subject is the user, not the codebase.- For
feature: 1 sentence on what it is + 1 sentence on where / how. Example: "Affectez les virements reçus aux bons projets quand le rapprochement automatique n'a pas pu être fait. Accessible depuis le menu de gauche." - For
improvement: state what changed and the benefit. Example: "Les filtres se conservent désormais entre deux visites — vous retrouvez votre vue à l'identique." - For
fix: state what was broken and is now resolved. Don't expose the root cause. Example: "Le tri par date dans la liste des projets ne renvoyait pas le bon ordre. Corrigé."
Forbidden in user copy: "Refactor", "DataTable", "Drawer", "Sheet", "TanStack", "Query", "Mutation", endpoint names, prefix codes like M5, English verbs ("Add / Fix / Update"), commit hashes, PR numbers, file paths.
6. Compute today's date¶
7. Bump the version¶
Starting from entries[0].version:
patch→1.0.0→1.0.1(small UX fixes, polishes)minor→1.0.0→1.1.0(a new page or substantial feature)major→1.0.0→2.0.0(a breaking change in how users interact)
The version renders as a v<x.y.z> badge on the page, so keep it readable semver.
8. Prepend the entry¶
Use Edit to insert the new entry at the top of the array in src/modules/changelog/data/entries.ts, immediately before the existing first entry. Schema:
{
version: '<bumped-version>',
date: '<YYYY-MM-DD>',
title: '<release title>',
changes: [
{
type: 'feature', // 'feature' | 'improvement' | 'fix'
label: '<short headline>',
description: '<1–2 sentences>',
to: '<route path>', // optional — only when a new page exists
},
// …more changes
],
},
Order inside changes: feature first, then improvement, then fix. The page renders sections in this same order, so authoring in this order keeps file diff order ≈ visual order.
9. Stop. Show the diff¶
Do not commit. Per CLAUDE.md: the user reviews and commits manually. Show the diff (git diff src/modules/changelog/data/entries.ts) and stop.
Worked example¶
Given the seed entry (v1.0.0, 2026-05-20) and a branch that ships two new pages, the "Quoi de neuf ?" page itself, AND a set of cross-cutting table improvements smuggled in via a feat(dependencies) commit (dnd-kit) plus a feat(management-fees) commit that landed DisabledTooltip and useTableColumnConfig, the skill produces:
{
version: '1.1.0',
date: '2026-05-21',
title: 'Budget chantier, frais de gestion & confort des tableaux',
changes: [
{
type: 'feature',
label: 'Suivi du budget chantier',
description:
"Suivez les demandes de virement de budget chantier transmises par les promoteurs, et déclenchez les approbations ou les transferts vers l'échéancier en quelques clics.",
to: '/projects/budget-chantier',
},
{
type: 'feature',
label: 'Suivi des frais de gestion',
description:
'Visualisez les frais de gestion à percevoir avec mise en avant des retards, et marquez les paiements reçus ou déclenchez les transferts en un clic.',
to: '/suivi-frais-gestion',
},
{
type: 'feature',
label: 'Page « Quoi de neuf ? »',
description:
"Retrouvez ici l'historique des nouveautés et améliorations apportées au back-office. Un point rouge dans la sidebar signale les nouveautés à découvrir.",
to: '/changelog',
},
{
type: 'improvement',
label: 'Personnalisation des colonnes',
// Source: feat(dependencies) (dnd-kit) + new `useTableColumnConfig` hook in BO.
// Surfaced by step 2b — the commit subject said nothing about columns.
description:
"Depuis le menu Colonnes, réorganisez les colonnes par glisser-déposer, épinglez-les à gauche ou à droite, masquez celles dont vous n'avez pas besoin, et réinitialisez l'ensemble. Le choix est mémorisé par tableau.",
},
{
type: 'improvement',
label: 'Export Excel (XLSX)',
// Source: `exportTableToXlsx` wired into `actions-menu.tsx` (step 2b).
description:
"En plus de l'export CSV, vous pouvez désormais exporter chaque tableau au format Excel depuis le menu Actions.",
},
{
type: 'improvement',
label: 'Boutons désactivés plus explicites',
// Source: new `components/disabled-tooltip.tsx` primitive (step 2b).
description:
"Les actions grisées affichent désormais la raison du blocage au survol — plus besoin de deviner.",
},
],
},
Notice how every improvement is sourced from step 2b (file-list scan), not from the commit subjects. That's the point of the second pass — without it, this entry would have been the two pages only.
What NOT to do¶
- ❌ Bump
package.jsonversion. Theentries[0].versionIS the source of truth for the "Nouveau" pastille. - ❌ Quote commit messages verbatim. They're written for the codebase, not the user.
- ❌ Include refactor / chore / test / docs / ci / build commits, even if they "feel important" internally.
- ❌ Disclose security vectors, CVE ids, or package names in security-flavoured entries.
- ❌ Use English, codebase nouns (DataTable, Drawer, TanStack…), prefix codes (M5, BRI-…), commit hashes, or PR numbers in user-facing
label/description. - ❌ Auto-commit the diff. The user reviews before any commit.
- ❌ Hand-edit
routeTree.gen.ts— the route file from the diff is enough; the plugin regenerates the tree. - ❌ Skip a commit because its conventional-commit subject doesn't mention the UX win (e.g.
feat(dependencies)that ships drag-reorder columns,feat(management-fees)that smuggles inDisabledTooltipanduseTableColumnConfig). Always run step 2b — read the file list, not just the subject. - ❌ Limit the entry to committed work when the changelog data file itself is uncommitted on the same branch — that's the canonical signal the whole bundle ships together. Pull in working-tree changes too.