Summary
src/app/loading.tsx renders <FullPageSpinner /> at the root segment level:
import { FullPageSpinner } from '@/components/LoadingSpinner';
export default function Loading() {
return <FullPageSpinner />;
}
In Next.js App Router, a loading.tsx at the root wraps every page segment transition in a Suspense boundary. This means navigating from / to /policies — a transition that often completes in under 100 ms on a warm cache — flashes a full-screen spinner that replaces the entire page content.
The result is a jarring, disorienting experience for fast navigations and makes the app feel slower than it is. Sub-100 ms transitions should either show nothing or use a thin top-of-page progress bar (e.g. NProgress or the built-in Next.js useRouter event hooks).
Fix direction
- Remove or scope the root
loading.tsx so it only applies to genuinely slow data-fetching routes (e.g. move it to src/app/pools/loading.tsx)
- For cross-page navigation feedback, add a lightweight top progress bar using a route-change event approach
- Keep per-route skeleton loading as-is in individual page components
Acceptance criteria
Summary
src/app/loading.tsxrenders<FullPageSpinner />at the root segment level:In Next.js App Router, a
loading.tsxat the root wraps every page segment transition in a Suspense boundary. This means navigating from/to/policies— a transition that often completes in under 100 ms on a warm cache — flashes a full-screen spinner that replaces the entire page content.The result is a jarring, disorienting experience for fast navigations and makes the app feel slower than it is. Sub-100 ms transitions should either show nothing or use a thin top-of-page progress bar (e.g. NProgress or the built-in Next.js
useRouterevent hooks).Fix direction
loading.tsxso it only applies to genuinely slow data-fetching routes (e.g. move it tosrc/app/pools/loading.tsx)Acceptance criteria
loading.tsxeither removed or replaced with a progress bar that does not blank the screen