release: dev → prod 2026-08-03 (dashboard perf + session freshness) - #1104
release: dev → prod 2026-08-03 (dashboard perf + session freshness)#1104teetangh wants to merge 4 commits into
Conversation
chore: sync prod → dev (re-align release merge history)
…ads (#1101) Memoizes getSession with React.cache so nested layout gates share one Better Auth call per render, narrows the consultant home/appointments Prisma graphs, drops pending-approval nests that were fetched and discarded, and code-splits the onboarding steps, create-org wizard, EarningsTabs (recharts) and SafeUnifiedCalendar. Measured: /form/onboarding first-load JS 392 kB -> 319 kB against a control route that grew 5 kB over the same window. A first pass moved the layout gates and requireApiAuth onto the Better Auth cookie cache; that is reverted. customSession re-runs its Prisma enrichment on every getSession call regardless, so the cache skipped roughly one query in four, while lib/auth-guard.ts has no ban check of its own and relied on the forced read to catch bans, DPDP erasure and revoked sessions. requireAuth now force-reads and checks banned explicitly too. Also fixes correctness regressions the perf work introduced: Financial Summary counts derived from a truncated array, an approvals badge that contradicted NeedsYou on the same screen, Home ranking that could empty Today/Upcoming, an INNER JOIN that blanked Trending, and a StreamProvider element-type swap that remounted the whole dashboard subtree. Pinned by __tests__/dashboards/consultant-home-read-shape.test.ts, each test verified by reintroducing its bug. Deriving UserRoleEnum from Prisma removes five 'as never' casts in onboarding. No raw SQL remains in lib/data or app.
Splits the dashboard prefetch and NeedsYou roll-up into their own async components behind Suspense, and renders the page header as real text outside them. The server now emits a shell at ~500ms instead of producing nothing until all ~14 queries resolve. Measured on the deploy preview (same URL/account/route, warm): shell HTML moved from blocked-behind-data to ~500ms. FCP did NOT move (6240ms -> 6008ms), and that is expected: the dashboard layout is a client component that wraps children in StreamProvider with ssr:false, so the server renders a spinner instead of the subtree and <h1> never reaches the HTML. Suspense can only stream markup the server is willing to produce. Restoring that SSR is the follow-up; this change is its prerequisite, because restoring SSR while the page still blocks on every query would just move the 4.9s wait into the HTML. Also fixes a real bug: the header title came from the session, which belongs to the VIEWER, so an ADMIN/STAFF inspecting another consultant's dashboard was greeted by their own name. Inspectors now get a neutral title. The auth gate stays outside the boundaries, prefetch and dehydrate stay in one component, and the page stays first in the file so the textual ownership-order assertion in personal-dashboard-ssr-ownership.test.ts still holds.
StreamProvider wrapped {children} in a next/dynamic component with ssr:false,
which skips server rendering for the component AND its children. The connector
now renders null as a sibling and publishes state to a module store read via
useSyncExternalStore, so children sit in a fixed position.
That also removes the once-per-session remount documented in StreamProviderImpl
(children -> <StreamVideo> -> <Chat> as the sockets settled), which tore down
the whole dashboard — the storm behind 'I pressed Join ten times' (#248).
The SDK contexts move to the surfaces that consume them: <Chat> to the three
Messages tabs, <StreamVideo> to /meetings. A completeness sweep caught a latent
bug this scoping would otherwise have introduced: useEventActions:115 powers
Join on consultee and org appointments, routes that no longer mount
<StreamVideo>, so every Join there would have failed. It now reads the singleton
at click time via getGlobalVideoClient().
Does NOT improve FCP, and is not merged as a perf claim. Measured on the
preview, the server HTML still contains no <h1> and no layout nav: the client
layout returns PersonalDashboardShellSkeleton instead of children while its
queries load, which is always during SSR because consultant-data is never
server-prefetched. That is the dominant blocker and the next PR.
Verified on the preview: consultant Messages (channels render, unread badge
live, no console errors), consultant Appointments, and /meetings mounting
without a context crash.
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
✅ Deploy Preview for familiarise ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
|
|
Closing for now — batching more PRs before promoting to prod. The branch is deleted; a fresh release branch off dev will be cut when we're ready. |




Promotes the three merged dashboard-performance PRs from
dev.React.cache), slimmer Prisma graphs, code splitting. Reverts a Better Auth cookie-cache experiment and makesrequireAuth/requireApiAuthforce-fresh with an explicit ban check.Risk notes for this promotion
/settings,/profileand/dashboard/org-workspace/**do one extra session read per request; in exchange, bans, DPDP erasure and revoked sessions take effect immediately instead of up to 5 minutes late.count()(uncapped, matching NeedsYou) and Home ranks appointments by soonest slot rather thancreatedAt. Pinned by__tests__/dashboards/consultant-home-read-shape.test.ts, each test verified by reintroducing its bug.Verified on preview: consultant Messages (unread badge live), Appointments, /meetings mount. Not covered: consultee/org Messages, a live meeting join.