Skip to the solution
MediumFrontend4 min read

What makes a route dynamic in the Next.js App Router?

950 views

The problem

Question presented to candidate: "A marketing page that should be static shows up as dynamic in the build output. How do you find out why, and what are the things that make a route dynamic?"

What a strong answer should cover:

  • A route is dynamic when rendering it needs information that only exists at request time.
  • Request-time APIs: cookies(), headers(), searchParams, connection(), draftMode(); plus fetch with cache: 'no-store' or revalidate: 0.
  • export const dynamic = 'force-dynamic' forces it explicitly.
  • A dynamic layout makes every page under it dynamic, even pages that read nothing.
  • The build table (Ζ’) and a private, no-store cache-control header show the result; with Cache Components the build instead demands a Suspense boundary.

Clarifying questions expected:

  • "Which layouts wrap this page?" β€” the cause is often in a shared layout.
  • "Does the page need that request data for its first paint?" β€” if not, move it into Suspense.

Code / implementation expected: Yes β€” the triggers, and moving one into a Suspense boundary.

  • nextjs
  • dynamic-rendering
  • cookies
  • headers

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

4 min read Β· 8 sections

Read the code

Keeping the page static by isolating the request read
// Before: the whole route is dynamic because the page reads cookies.
// After:
import { Suspense } from "react";
import { cookies } from "next/headers";

async function CartCount() {
  const count = (await cookies()).get("cart")?.value ?? "0";
  return <span>Cart ({count})</span>;
}

export default function Page() {
  return (
    <main>
      <h1>Summer sale</h1>                           {/* no request data */}
      <Suspense fallback={<span>Cart</span>}>
        <CartCount />                                 {/* only this part needs the request */}
      </Suspense>
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 36 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextMedium

Migrating Webpack config to Turbopack β€” what breaks?

Continue