feat(dashboard): enable unified snapshot for atomic first paint

Default the dashboard snapshot flag to ON (disable with
NEXT_PUBLIC_DASHBOARD_SNAPSHOT=false). The legacy four-cell waterfall
let the mood cache resolve first and pop in ahead of the rest of the
strip; the snapshot path hydrates every tile from one un-gated cell so
the whole strip shares a single completion moment.

Defaulting on rather than gating on === "true" sidesteps the
NEXT_PUBLIC_* build-time-baking trap: the production image and dev/e2e
all exercise the snapshot path without a special build flag. Fully
reversible to the legacy path via the env var. Comment-only sync in
page.tsx; no logic change there.
This commit is contained in:
Marc-André Bombeck committed 2026-05-31 19:37:02 +02:00
1 parent 5dde85da84
commit 7802ce1e11
2 files changed
+23 -20

No files matched your search

+8 -8
View File
@@ -120,8 +120,8 @@ function getHourForTimeZone(timeZone?: string): number {
* v1.7.0 — first-paint gate for the dashboard tile strip.
*
* `primaryLoading` must come from whichever query actually drives the
* tiles: the snapshot cell under `NEXT_PUBLIC_DASHBOARD_SNAPSHOT=true`,
* the slim analytics cell otherwise. A disabled TanStack query reports
* tiles: the snapshot cell by default, the slim analytics cell when
* `NEXT_PUBLIC_DASHBOARD_SNAPSHOT=false`. A disabled TanStack query reports
* `isLoading: false` (idle fetch status), so keying off the wrong
* source flashes the empty state for the whole fetch. Pure + exported
* so the gate has direct unit coverage without mounting the page.
@@ -245,12 +245,12 @@ export default function DashboardPage() {
// Both queries share `caches.analytics` server-side so warm hits
// stay free, and TanStack's parallel-mounting keeps the network fan-
// out flat.
// v1.7.0 W6 — unified first-paint snapshot (reversible rollout flag).
// When `NEXT_PUBLIC_DASHBOARD_SNAPSHOT=true`, every tile hydrates from
// ONE un-gated `/api/dashboard/snapshot` cell so the whole strip
// shares one completion moment and the `/api/auth/me` round-trip
// leaves the cold critical path. Flag OFF keeps the legacy four
// independent cells (today's behaviour, byte-identical).
// Unified first-paint snapshot (reversible rollout flag, default ON).
// Every tile hydrates from ONE un-gated `/api/dashboard/snapshot` cell
// so the whole strip shares one completion moment and the
// `/api/auth/me` round-trip leaves the cold critical path. Set
// `NEXT_PUBLIC_DASHBOARD_SNAPSHOT=false` to fall back to the legacy
// four independent cells.
const snapshotEnabled = isDashboardSnapshotEnabled();
const snapshotQuery = useDashboardSnapshot(snapshotEnabled);
+15 -12
View File
@@ -1,18 +1,21 @@
/**
* v1.7.0 W6 — reversible rollout flag for the unified dashboard
* snapshot consumption (R-firstpaint §6 rollout).
* Reversible rollout flag for the unified dashboard snapshot
* consumption.
*
* The `GET /api/dashboard/snapshot` endpoint and the
* `insight-pregenerate` cron ship inert in step 1. This flag controls
* step 2 — whether the dashboard page reads every tile from the single
* snapshot cell (flag ON) or keeps the legacy four independent cells
* (flag OFF, today's behaviour, zero risk). Default OFF so the swap is
* opt-in until the stagger is verified gone in production.
* Controls whether the dashboard page reads every above-the-fold tile
* from the single `GET /api/dashboard/snapshot` cell (default) or falls
* back to the legacy four independent cells (slim analytics + thick
* analytics + mood + widget layout). The snapshot path is the desired
* behaviour: one un-gated request hydrates the whole strip so every
* tile shares one completion moment, instead of four parallel cells
* where the mood cache resolves fastest and pops in ahead of the rest.
*
* Build-time `NEXT_PUBLIC_*` env var so the bundle is statically
* branched; flipping it is a redeploy, not a runtime toggle, which
* keeps the off-path bundle identical to today's.
* Default ON. Set `NEXT_PUBLIC_DASHBOARD_SNAPSHOT=false` to fall back
* to the legacy multi-cell path. Defaulting on (rather than gating on
* `=== "true"`) avoids the `NEXT_PUBLIC_*` build-time-baking trap: the
* snapshot path is exercised in dev / e2e without a special build
* flag, and the production image gets it without a Dockerfile ARG.
*/
export function isDashboardSnapshotEnabled(): boolean {
return process.env.NEXT_PUBLIC_DASHBOARD_SNAPSHOT === "true";
return process.env.NEXT_PUBLIC_DASHBOARD_SNAPSHOT !== "false";
}