Definition of instant navigation
A navigation is instant when the browser can start rendering the new page the moment the user clicks, with static, cached, and fallback content showing up right away, while the server streams the remaining content into its fallbacks. This definition assumes caches are warm; cold caches still require the server to compute the cached result once, so the first navigation to a route may still wait.
Different initial UI for direct visits vs client navigations
Direct visits get the static shell as HTML, typically from a CDN. Client navigations only re-render below the layout the current and destination routes share, so the fallback UI defined by a Suspense boundary above that point cannot be used during the transition. Whether the new page appears instantly depends on the Suspense boundaries and caching present below the shared layout.
Why page loads and client navigations produce different initial UI
On a page load, the entire page renders from the document root and every component runs on the server, with anything that suspends caught by the nearest Suspense boundary in the full tree. On a client navigation between routes (e.g., /store/shoes to /store/hats), only the components below the shared layout (/store) re-render. A Suspense boundary in the root layout covers everything on a page load but sits above the re-render scope on client navigation and does not trigger. This is also why client-side hooks like useSearchParams() behave differently: useSearchParams() suspends during server rendering because search params are not available at build time, but on a client navigation, the router already has the params from the URL and the hook resolves synchronously.
Enabling instant navigation quick start configuration
To get the most out of Instant Navigation, enable cacheComponents and partialPrefetching in next.config.ts.
App Shell generation and Partial Prefetching
Next.js can generate an App Shell per route, which renders during client navigations while remaining content streams. Partial Prefetching uses the App Shell as the default Link prefetch. A link with prefetch={true} can also resolve cached content that depends on that link's URL data.
Validation of instant navigation in Cache Components apps
By default (validationLevel: 'warning'), Cache Components apps validate every Page and Default segment in development. Validation surfaces what would keep navigations into a segment from being instant—which navigations would block, where a Suspense boundary is missing, and which data is reaching the user uncached.
Manual validation mode for instant navigation
To opt out of automatic validation and only validate segments that explicitly export instant, set validationLevel to 'manual-warning' in next.config.ts under experimental.instantInsights.
How validation simulates different navigations
For each validated route, Next.js checks both the initial page load and client navigations at different points in the route hierarchy. For a route like /shop/[slug], validation checks the page load (full tree renders from root, root layout Suspense catches everything) and client navigation (e.g., from /shop/shoes to /shop/hats, where /shop layout is already mounted and only the page below re-renders, with root layout Suspense not covering this navigation). Each case is validated independently. A Suspense boundary that covers one navigation path might not cover another.
Example product page with instant navigation
The following example shows a product page at /store/[slug] with two data fetches: product details (cached with 'use cache') and inventory (uncached, in Suspense). The page uses 'use cache' in getProduct() and wraps both ProductInfo and Inventory components in separate Suspense boundaries with fallbacks. This structure allows navigation to appear instant with the cached product info and a loading state for inventory.
Fixing blocking navigations step 1: move slug-dependent work into Suspense
When validation surfaces a per-slug product fetch as blocking, extract the slug-dependent work into a sub-component and wrap it with Suspense. Pass params as a prop to the sub-component. This allows await props.params and the product fetch to suspend together, moving the error to the next blocker.
Fixing blocking navigations step 2: cache the featured fetch
When validation flags an uncached fetch like getFeatured(), add a 'use cache' directive to the fetching function. The result is cached at the fetch level, and the featured list ships with the App Shell.
Loading states optimization after validation passes
Validation passing means the navigation is instant, but not that the loading states are good. A Suspense boundary placed high in the tree might satisfy validation but replaces most of the page with a single fallback on every navigation. The best loading states keep as much real, cached content visible as possible and only show fallbacks where data is actually in flight. Use DevTools to see what users see, or use an agent to automate the loop of pushing boundaries down.
Three levers for optimizing instant navigation
Agents working on a Cache Components route typically reach for three levers: (1) Push down—extract I/O into a Suspense-wrapped child so the parent stays static and static siblings lift into the shell. (2) Cache—pair 'use cache' with cacheLife to assign a freshness profile. (3) Per-link prefetching (nav-only)—when a route reads URL data (searchParams or params), opt it into per-link prefetching so the framework resolves that data at link-prefetch time.
Opting out of instant validation with instant = false
Set instant = false on the page or layout file to opt the segment out of validation feedback. The segment may still navigate instantly if its structure supports it; the framework just won't surface insights for it. Navigations between sibling segments below are still validated.
next-cache-components-adoption and next-partial-prefetching-adoption Skills
There are Skills available to automate the instant navigation adoption process: next-cache-components-adoption (https://www.skills.sh/vercel/next.js/next-cache-components-adoption) and next-partial-prefetching-adoption (https://www.skills.sh/vercel/next.js/next-partial-prefetching-adoption). The next-cache-components-optimizer Skill packages the optimization loop: it confirms the target UI renders normally, writes an instant() test that fails before the fix, then works it to green against a production-like build and ships it as a regression guard.