Problem
Protected pages use inconsistent strategies to avoid flashing unauthenticated content before the auth check completes. Some use useMount() + a full-screen spinner (src/pages/profile/[id].tsx:57-62), some have server-side auth redirects but still render fragments on the client, some have neither. The result is visible visual flicker / layout shift on slow connections.
Expected behavior
One canonical pattern for protected pages:
- Server-side:
getServerSideProps using the new requireAuthSSR / requireAdminSSR helpers (see src/lib/auth-guards.ts from PR #security/auth-hardening) — prevents the FOUC entirely for SSR'd routes.
- Client-side (when SSR isn't possible): a shared
<ProtectedContent fallback={...}> wrapper that reads useSession() and renders a skeleton, not the page shell, until resolved.
Acceptance criteria
Related
src/lib/auth-guards.ts (introduced in PR security/auth-hardening).
Problem
Protected pages use inconsistent strategies to avoid flashing unauthenticated content before the auth check completes. Some use
useMount()+ a full-screen spinner (src/pages/profile/[id].tsx:57-62), some have server-side auth redirects but still render fragments on the client, some have neither. The result is visible visual flicker / layout shift on slow connections.Expected behavior
One canonical pattern for protected pages:
getServerSidePropsusing the newrequireAuthSSR/requireAdminSSRhelpers (seesrc/lib/auth-guards.tsfrom PR #security/auth-hardening) — prevents the FOUC entirely for SSR'd routes.<ProtectedContent fallback={...}>wrapper that readsuseSession()and renders a skeleton, not the page shell, until resolved.Acceptance criteria
<ProtectedContent>component exists and documented.requireAuthSSRor<ProtectedContent>.Related
src/lib/auth-guards.ts(introduced in PRsecurity/auth-hardening).