Resolve the signed-in user once per server render

Merged
FR
6d ago
+175-46

What & why

Server-side follow-up to the slow-network work (#654–#656). A dashboard render looked up the signed-in user four separate times before any HTML reached the browser:

  • the (app) layout
  • the dashboard layout (through getOAuthMetadata)
  • the header (through getAuthenticatedUser)
  • the page (and generateMetadata too when ?item is set)

Each lookup is a Supabase Auth getUser round trip plus the MFA check. getClaims is another round trip on projects with symmetric JWT keys, and the dashboard page fetched claims only to discard them.

  • getRequestUserWithMfa() and getRequestClaims() in @/lib/supabase/server wrap those lookups in React cache, so one render makes one call. The viewer is still recorded on every call, because each caller may run in its own viewer frame.
  • getAuthUser and getOAuthMetadata now go through them. getOAuthMetadata no longer takes a client.
  • The (app) layout, dashboard page, /save page and dashboard layout use them directly.
  • Server components only. Server actions and route handlers keep calling getUserWithMfa on their own client, so a sign-in or sign-out mid-request can never read a stale cached user. Every caller of the cached helpers is a page, a layout or a server component.
  • The MFA check is unchanged: the same getUserWithMfa runs once instead of four times. The middleware's own check is untouched.

Checklist

  • User-facing change → added/updated a PostHog event, or N/A. N/A: server latency only.
  • User-facing or service change → docs updated, or N/A. N/A.
  • New error paths report via captureServerException / the error boundary, or N/A. N/A: no new paths.
  • New behavior is covered by tests, or N/A. request-user.test.ts stands in for one render and asserts that three callers make one getUser and one getClaims call, and that the viewer is recorded for each caller. user-metadata.test.ts is updated for the new signature.
  • If this fixes a recurring defect, considered a guardrail via the learn skill, or N/A. N/A.

Notes

  • Touches auth helpers, which the repo says to flag; the user approved this change.
  • Not measured against a live Supabase. Going by the code, a dashboard render drops from about four Auth round trips to one, and from two getClaims calls to one.

Generated by Claude Code