From 2a256a8943c090fdf987f7aa6014c59bf945f348 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Sat, 18 Jul 2026 09:24:03 +0200 Subject: [PATCH] docs: scope the "What's New" in-app announcement feature Extends ChangelogEntry with an optional highlights field (editorial, per-version, plain language -- most versions won't have one) instead of forking a second content source. One new users column (lastSeenChangelogVersion, backfilled to current APP_VERSION on migration so existing users aren't flooded with history), two routes, one component mirroring NotificationBell's existing bell/badge/dropdown shape. --- WHATS_NEW_PLAN.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 WHATS_NEW_PLAN.md diff --git a/WHATS_NEW_PLAN.md b/WHATS_NEW_PLAN.md new file mode 100644 index 0000000..6be1bbc --- /dev/null +++ b/WHATS_NEW_PLAN.md @@ -0,0 +1,101 @@ +# "What's New" Plan + +## Status: planning only — nothing in this doc is implemented yet + +The problem this solves: `apps/web/lib/changelog.ts`'s `CHANGELOG` array is +a dev log — migration reminders, bug-fix jargon, internal notes ("not +applied in sandbox") mixed in with real feature announcements. Correctly +not public (per `VITRINE_PLAN.md` §6, which flagged this gap). Users have +no clean way to see what's new since they last looked. + +**Existing precedent to mirror, not reinvent**: `apps/web/components/social/notification-bell.tsx` +is exactly this UI shape already — bell icon, unread badge, dropdown list, +polling `GET` on an interval, a "mark read" POST. Same skeleton, new data +source. + +--- + +## 1. Content — extend `ChangelogEntry`, don't fork a second data source + +Add one optional field to the existing type in `apps/web/lib/changelog.ts`: + +```ts +export type ChangelogEntry = { + version: string; + date: string; + added?: string[]; + fixed?: string[]; + security?: string[]; + notes?: string; + highlights?: string[]; // user-facing, plain language — only set on entries worth telling users about +}; +``` + +Only versions with `highlights` populated ever show up in the "What's New" +panel — everything else in `CHANGELOG` stays exactly as dev-facing as it is +today. This is a deliberate editorial step, not automatic: when a version +ships something a real user would care about, someone (you) writes one or +two `highlights` lines in plain language, same commit as the `added`/`fixed` +entries. Retroactively, only add `highlights` to past entries actually worth +surfacing — no need to backfill all 47+ versions, most were internal +fixes/refactors nobody needs a notification about. + +--- + +## 2. Schema + +One column, `apps/web/packages/db/src/schema/users.ts`: +```ts +lastSeenChangelogVersion: text("last_seen_changelog_version"), +``` +Nullable. On the migration, backfill existing users to the current +`APP_VERSION` at migration time (not `null`) — otherwise every existing +user sees the entire history of `highlights` entries as "new" the moment +this ships, which is noise, not a useful announcement. New signups after +this ships get set to `APP_VERSION` at account-creation time for the same +reason — someone who just joined doesn't need to be told about features +that existed before they showed up. + +--- + +## 3. API + +- **`GET /api/v1/whats-new`** — compares the user's `lastSeenChangelogVersion` + against `CHANGELOG` (imported directly, no DB query needed for the content + itself — it's a static in-code array), returns every entry with + `highlights` whose version is newer (semver comparison, not string + comparison — `"0.9.0" < "0.10.0"` is false under plain string compare). + A tiny local semver-compare helper is enough; no need for a package for + a 3-segment version string this app already controls end to end. +- **`POST /api/v1/whats-new/seen`** — sets `lastSeenChangelogVersion` to the + current `APP_VERSION` for the calling user. Called when the panel opens + (or on explicit dismiss — same UX choice `NotificationBell`'s `markAllRead` + already made for regular notifications, mirror whichever this app's + notifications settled on). + +Both gated by `requireSessionOrApiKey`, same as every other authenticated +route — no new auth pattern needed. + +--- + +## 4. UI + +New component `apps/web/components/layout/whats-new-bell.tsx`, structurally +identical to `NotificationBell`: bell/gift icon, badge showing count of +unseen highlighted versions, dropdown listing them (version, date, bullet +list of that version's `highlights`), placed in `apps/web/components/layout/nav.tsx` +next to the existing `NotificationBell`/`MessagesNavLink` icons in the +authenticated header. + +Not a public/vitrine concern — this lives entirely inside the authenticated +app shell, unrelated to `VITRINE_PLAN.md`'s route group. + +--- + +## 5. Rollout order + +1. Schema migration (backfill existing users to current `APP_VERSION`) — no visible change yet. +2. `highlights` field on `ChangelogEntry` + write it for the next few versions going forward, so there's something to show once the UI ships. +3. API routes. +4. `WhatsNewBell` component wired into `nav.tsx`. +5. Retroactively add `highlights` to a handful of past standout versions (the tier system, the cooking-assistant tools, followers-only visibility) if you want new/returning users to see a bit of history on first exposure, not just what ships after this point.