跪拜 Guibai
← Back to the summary

Next.js 16.3 Turns Every Page into a Shell, Cache, and Stream Assembly

Hello 👋, I'm Moment, currently building DocFlow with Next.js, NestJS, Tiptap, and LangGraph.

DocFlow is a collaborative document platform for AI full-stack scenarios, centered around rich text editing, real-time collaboration, and AI workflows.

If you're interested in AI full-stack development, Tiptap, LangGraph, or collaborative documents, feel free to add me on WeChat yunmz777 to chat. If you find the project useful, a star ⭐ on DocFlow is also welcome.

eb44cd75f896ed5cf3ba3aad76fb3fdb.png

Past discussions of Next.js updates mostly focused on build speed, rendering performance, caching strategies, and React APIs.

With 16.3, the framework's boundaries have clearly expanded. The Instant Navigations announcement pushes the user-side experience forward, while the AI Improvements documentation begins systematically adapting to Coding Agents like Claude Code, Cursor, and Codex.

One thread targets end users: giving server-driven pages near-SPA instant feedback.

The other thread targets developers and Agents: enabling them to read the correct version of documentation, modify code, check runtime status, and verify results.

As of June 29, 2026, Next.js 16.3 is still in Preview and can be tested early via next@preview. Some APIs and configurations may still change before the stable release.

The Root Cause of Slow Server-Side Navigation

Server Components can directly access databases, internal services, and sensitive resources, and also reduce client-side JavaScript. But they have always had a clear shortcoming: page navigation often requires waiting for the server to finish reading data before the user sees any page change.

Traditional server-side navigation must wait for a complete response to return; after clicking, the user experiences a noticeable blank wait. SPAs are different—after clicking, the target page structure appears immediately, and data fills in progressively.

The Instant Navigations documentation breaks slow navigation into two separate problems: the network round-trip from client to server, and the time the server takes to generate a complete response. The former is addressed by prefetching, and the latter by Stream and Cache, so the server no longer blocks the entire page output.

What Instant Navigations aims to do is combine the instant feedback of an SPA with the data capabilities of server-side rendering: continue using Server Components and server-side data, display the already-determined structure of the target page first, then stream in dynamic data. It is not turning Next.js back into a client-side SPA.

Slow navigation usually gets stuck in two places: the network round-trip delays the first frame after clicking, and server-side blocking forces the entire page to be computed before returning. Instant Navigations handles these two gaps with Partial Prefetching and Stream/Cache respectively.

20260630102052

Optimizing only one of these gaps can still result in a white screen or repeated prefetching after clicking. Only when both gaps are handled does navigation truly approach the instant feel of an SPA.

Entering the Target Page Immediately After Clicking a Link

To use Instant Navigations, you need to first enable Cache Components:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  cacheComponents: true,
};

export default nextConfig;

The official documentation treats this flag as the entry point for new behavior returning to dynamic by default, and it is likely to become the default configuration in a future major version. Once enabled, every server-side await in a page must explicitly choose Stream, Cache, or Block; the framework no longer makes implicit decisions for you.

Stream: Show Structure First, Then Load Data

Wrap content that can appear later with <Suspense>:

import { Suspense } from "react";

export default function DashboardPage() {
  return (
    <main>
      <h1>Dashboard</h1>

      <Suspense fallback={<DashboardSkeleton />}>
        <DashboardData />
      </Suspense>
    </main>
  );
}

async function DashboardData() {
  const data = await getDashboardData();

  return <DashboardContent data={data} />;
}

After entering the page, users can first see the title, layout, and skeleton. Once the server-side data is ready, the real content continues to stream back. This approach suits statistics data, search results, recommendation content, and message lists.

Cache: Reuse Already-Generated Content

For data that can be reused across requests, use 'use cache':

import { cacheLife } from "next/cache";

async function ArticleHeader({ id }: { id: string }) {
  "use cache";

  cacheLife("minutes");

  const article = await getArticle(id);

  return <h1>{article.title}</h1>;
}

Caching suits article information, basic product data, public navigation, and infrequently changing configurations. When users enter the page, existing content can be reused directly without waiting for the server to re-run all computations.

Block: Wait for the Complete Result

Some pages are unsuitable for showing skeletons or using caches. For example, when a blog post body must be returned in full and a loading shell is not allowed, you can explicitly disable instant navigation:

export const instant = false;

Such pages will still wait for the server to return the complete result, and the corresponding Instant Insight will disappear in the development environment.

Stream, Cache, and Block are not about superiority but about three different product choices. The official description frames them as making asynchronous operations into instantly presentable content: Stream trades placeholder UI for time, Cache trades existing results for time, and Block actively accepts waiting.

After enabling Cache Components, every server-side await must fall into one of these three strategies. Choosing incorrectly will directly show up in Instant Insight.

20260630102011

Use Stream for content that can appear later, Cache for content that can be reused, and Block for pages that must return in full. Next.js previously tended to automatically decide between static and dynamic rendering; 16.3 further emphasizes explicitly expressing the behavior of data and pages.

Instant Insights Help You See Why Navigation Is Blocked

After enabling Cache Components, if an asynchronous operation is neither cached nor placed inside Suspense, Next.js will provide an Instant Insight in the development environment and treat slow navigation as a development-time error.

It not only points out where navigation is blocked but also offers three tagged fix directions:

Past errors usually only indicated that a piece of code could not be pre-rendered. Now, errors begin to explain the impact on the page experience and how to fix it. The AI Improvements documentation also provides a dedicated documentation page for each rule. Both the Overlay and the terminal include a Copy as prompt button, which can package the problem, code location, fix steps, and verification requirements into a task directly deliverable to a Coding Agent.

Navigation experience issues are starting to shift from something only detectable by human eyes to structured tasks that can be handed off to an Agent.

Partial Prefetching No Longer Repeatedly Prefetches Full Pages

Stream and Cache solve the blocking during server-side response generation. To make the first frame after clicking fast enough, the client must also obtain reusable page structures in advance.

Before 16.2, Next.js would send a prefetch request for each <Link> in the viewport. If a chat sidebar had 20 /chat/[id] links, it would trigger 20 nearly identical prefetches. The official team also acknowledged that this looked quite wasteful in the Network panel.

Partial Prefetching borrows the SPA idea of splitting code by route: instead of prefetching the entire page for each dynamic link, it prefetches one reusable shell per distinct route and caches it within the client session. Suppose a chat application has many dynamic links:

/chat/1
/chat/2
/chat/3
/chat/4

These pages have different parameters but essentially the same layout. What can truly be reused is the sidebar, top navigation, message container, input box, and loading skeleton, not the complete data for each conversation.

The core change of Partial Prefetching is prefetching one Shell per distinct route, rather than repeatedly pulling the full page for each dynamic link.

20260630101852

Enable it as follows:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  cacheComponents: true,
  partialPrefetching: true,
};

export default nextConfig;

The Shell provides the baseline for instant navigation. If a specific link needs a deeper level of prefetching—for example, a chat page header also needs to appear instantly—you can enable per-link prefetching on <Link prefetch={true}>, but the framework will still only pre-render up to synchronously available or 'use cache' marked content, not reverting to the old path of full-page deep prefetching.

When a user clicks any conversation, the client first immediately displays the cached shell, then loads the current conversation's data. This reduces duplicate requests and lowers the prefetching pressure caused by many dynamic links, making it especially suitable for chat applications, admin panels, collaborative documents, workflow platforms, and product listings.

The Page Shell Is Becoming the New Performance Boundary

In the past, we often simply divided pages into static and dynamic. Under Cache Components, Suspense, and Partial Prefetching, a single page can simultaneously contain pre-generated page structures, reusable cached content, dynamic data that must be fetched in real-time, and interactive state that only runs on the client.

Next.js no longer requires the entire page to adopt a single rendering strategy but allows different regions to have different loading methods. The shell of a document editor might be the sidebar, toolbar, and editing area frame; the shell of a chat application might be the conversation layout, input box, and message skeleton; the shell of a workflow platform might be the node canvas, action bar, and property panel.

Within the same page, Shell, Cache, and Stream often coexist, each responsible for the loading rhythm of different regions.

20260630102225

The Shell determines what the user sees in the first frame after clicking; Cache and Stream determine how and when different regions are subsequently filled in. If an entire page is wrapped in a single top-level Suspense, navigation may not be blocked, but the user might still only see a large block of Loading—this is precisely the typical problem the Navigation Inspector is designed to catch.

Navigation Inspector Makes Navigation Experience Testable

16.3 adds a Navigation Inspector, which allows direct observation of which content has entered the prefetch shell during a navigation, which content can be displayed immediately after clicking, which parts still need to wait for the server, and whether Suspense boundaries are placed too high.

It pauses at the shell state during each navigation, letting you see the prefetch result, then click Resume to see the full page. Actual prefetching behavior only takes effect in production mode; during development, the Inspector and Instant Insights are the primary tools for locating problems.

Next.js also provides instant() testing capability for Playwright:

import { expect, test } from "@playwright/test";
import { instant } from "@next/playwright";

test("Product page can immediately display page structure", async ({ page }) => {
  await page.goto("/products/shoes");

  await instant(page, async () => {
    await page.click('a[href="/products/hats"]');

    await expect(page.locator("h1")).toContainText("Baseball Cap");
    await expect(page.getByText("Checking inventory")).toBeVisible();
  });

  await expect(page.getByText("Inventory 12 items")).toBeVisible();
});

instant() asserts what content should already be visible on the page without waiting for the network; complete data is waited for outside the callback. In the past, automated tests usually only verified whether the page was ultimately correct. Now, they can also verify whether the title, layout, skeleton, and key operation areas appear immediately after a user clicks. Navigation experience is starting to shift from a subjective feeling to a regression metric that can enter CI.

The Biggest Pitfall for Agents Is Outdated Training Data

Instant Navigations targets users; the other set of updates in 16.3 targets Coding Agents.

One of the most common problems with Agents is that training data easily becomes outdated. A project may have already upgraded to Next.js 16, but the Agent might still generate old cache patterns, outdated configurations, incorrect params usage, or continue applying historical experience from the Pages Router.

To solve this, Next.js has been including the current version's documentation in the npm package since 16.2. In 16.3, next dev also automatically writes a version pointer to AGENTS.md. The Agent can read local documentation corresponding to the project's actually installed version, rather than relying solely on knowledge memorized during model training.

AGENTS.md Lets Projects Declare Their Own Development Rules

16.3 uses AGENTS.md to tell the Coding Agent which Next.js version the current project uses, where to read local documentation before making changes, not to directly adopt old APIs from training data, and how to verify after modifications are complete.

When next dev detects a Coding Agent environment, it automatically inserts a rule block marked with BEGIN:nextjs-agent-rules. Project custom content is kept outside the markers, and automatic writing can be disabled via agentRules: false.

AGENTS.md is responsible for project rules, not replacing official documentation. Official documentation explains how to use the framework; AGENTS.md explains how this project expects the Agent to work, including directory boundaries, code conventions, prohibitions, and verification requirements.

Skills Turn Knowledge into Executable Processes

16.3 also provides several first-party Skills:

Installation is as follows:

npx skills add vercel/next.js --skill next-dev-loop

Documentation solves how a specific API should be written; a Skill solves how a complete task should be accomplished. The Agent's working method is shifting from single-step code generation to a complete closed loop with verification.

20260630100627

Code generation is just one step; running and verifying constitute the complete closed loop. When verification fails, the process returns to modifying the code and continuing correction, rather than treating the generated result as the final deliverable.

MCP, Agent Browser, and Playwright Each Have Their Role

Next.js hasn't crammed all capabilities into a single MCP Server but has gradually formed a clear layering:

This layering is more reasonable than having a single MCP simultaneously handle knowledge queries, code modification, browser operations, and high-risk commands, and it's easier to control permissions.

Adapter API Handles Deployment Boundaries

Besides rendering and AI Coding, the Next.js 16 series is also advancing the Adapter API. The Across Platforms documentation mentions that after a build is complete, Next.js can output a typed, versioned application description, including routes, static assets, pre-rendering results, runtime targets, and caching rules.

Different deployment platforms can rely on this public contract to deploy Next.js applications to their own CDN, Serverless, Edge, or Node.js infrastructure. Next.js is simultaneously establishing three boundaries: a rendering and caching model for application developers, knowledge and runtime tools for Coding Agents, and a build and runtime contract for deployment platforms.

Should You Upgrade Now

Next.js 16.3 is still in Preview, and it is not recommended to fully enable it directly in core production projects. You can first create a test branch:

git switch -c test-next-16-3
pnpm add next@preview

Focus on verifying these scenarios:

The benefits of this update may be less obvious for typical content websites. Admin panels, chat applications, collaborative documents, workflow platforms, and complex SaaS products are worth testing Instant Navigations, Partial Prefetching, and the Agent development closed loop early. The 16.2 release notes already laid some of the groundwork for Cache Components; 16.3 is more about completing the navigation experience and Agent toolchain on top of that.

There are two known issues in the Preview stage: when Partial Prefetching is enabled, accessing params inside the shell can cause route blocking but may not trigger an Instant Insight; Instant Insights behave unstably in the Safari development environment, so Chrome or Firefox is recommended for debugging.

Summary

On the surface, Next.js 16.3 brings Instant Navigations, Partial Prefetching, and a series of AI Coding capabilities. More importantly, it is changing the framework's boundaries.

Page rendering is starting to shift from a binary choice between static or dynamic to a combination of shell, cached content, and dynamic data. Performance optimization is beginning to focus on what users can see immediately after clicking, not just how long the page ultimately takes to load. Coding Agents are also gradually evolving from code generation tools into development participants capable of reading documentation, modifying code, starting applications, observing state, and verifying results.

What's truly worth paying attention to in 16.3 is not just faster page transitions, but that it is demonstrating the shape of the next generation of web frameworks: a framework is not only responsible for running code but is also beginning to be responsible for providing clear, executable, observable, and verifiable development boundaries to developers, Agents, and deployment platforms. This path won't stop at Next.js; NestJS, Prisma, Drizzle, Nuxt, SvelteKit, and other ecosystems will also gradually fill in versioned documentation, Agent rules, structured CLIs, MCPs, Skills, and verification tools.