DeepFrontend
Practice ArenaBlogSign in
Go Pro
DeepFrontend

Interview-grade learning paths and hands-on practice for mid-to-senior engineers. Master internals, patterns, and system architecture with runnable code.

All systems operational

Core Courses

  • -JavaScript Internals
  • -React Reconciliation
  • -TypeScript rigor
  • -Next.js Caching
  • -Node.js Event Loop
  • -System Design
  • -Web Security
  • -CSS & Page Layouts

Explore

  • Learning Paths
  • Practice Arena
  • Pricing Options
  • HTML Sitemap

Resources

  • Privacy Policy
  • Terms of Service
  • Email Support

© 2026 DeepFrontend. All rights reserved.

Expert learning environments for web engineering teams.

Home/Next.js/Pages Router
beginner20 min read·Updated Jun 2025

Pages Router

The Pages Router is Next.js's original routing system — still supported, still asked about in interviews, and still the mental model many existing production codebases run on. This topic is deliberately brief: interview fluency and a clean migration map to App Router equivalents, not a new system to build in.

pages-routergetServerSidePropsgetStaticPropsgetStaticPathslegacyinterview-prep

Knowledge Check

15 questions · pass at 70%

0/15
easymcq

1. In the Pages Router, what determines a route's URL?


Interview Questions

2 questions

Cheatsheet

Download-ready reference
Cheatsheet
Pages Router: file-system routing via pages/ — still fully supported,
  App Router is the recommended default for NEW projects.

getStaticProps        → build time (or ISR revalidate)
                         ≈ async Server Component + "use cache"/cacheLife
getStaticPaths         → lists paths to prerender at build time
                         ≈ generateStaticParams
getServerSideProps     → EVERY request, server-side, no caching
                         ≈ Server Component reading runtime data (no cache directive)
pages/api/*.js          → custom API endpoint
                         ≈ app/api/*/route.ts (Route Handlers)

getInitialProps (legacy, older than the above) — runs on BOTH
  server (initial load) AND client (subsequent nav). Rarely used
  directly in modern Pages Router code.

revalidate: N in getStaticProps = ISR, stale-while-revalidate —
  conceptually identical to the App Router's cacheLife/revalidateTag.

fallback: false/true/'blocking' in getStaticPaths controls what
  happens for paths NOT explicitly listed (404 / generate-on-demand).

Client-side fetching (SWR, React Query) works the SAME way in
  either router — it's router-agnostic.

Related topics

App Router OverviewDynamic RoutesPro

On this page

20m
Knowledge CheckInterview QuestionsCheatsheet

Concept#

The beginner framing: before the App Router, Next.js routed based on files inside a pages/ directory — each file directly became a route, and data fetching was done through a small set of exported functions rather than await-ing inside the component itself.

The precise mental model: the Pages Router still exists and is fully supported, but the App Router (covered throughout the rest of this domain) is the current, recommended default for new projects. This topic exists because production codebases and interview questions both still assume Pages Router fluency — the goal here is recognition and a clean mental map to App Router equivalents, not depth for new development.

// pages/blog/[slug].js — the file itself IS the route: /blog/:slug
export default function BlogPost({ post }) {
  return <h1>{post.title}</h1>;
}
 
export async function getStaticPaths() {
  const posts = await getPosts();
  return { paths: posts.map((p) => ({ params: { slug: p.slug } })), fallback: false };
}
 
export async function getStaticProps({ params }) {
  const post = await getPost(params.slug);
  return { props: { post }, revalidate: 3600 }; // ISR: revalidate every hour
}

The three data-fetching functions, and their App Router equivalents#

Pages RouterWhen it ranApp Router equivalent
getStaticPropsBuild time (or on ISR revalidation)An async Server Component await-ing data directly, with "use cache"/cacheLife for the caching behavior
getStaticPathsBuild time, alongside getStaticProps, to list dynamic paths to prerender

The conceptual shift: Pages Router separated "the component" from "the function that fetches its props," with an explicit function name signaling the rendering strategy (getStaticProps = static, getServerSideProps = dynamic). App Router collapses this — a single async Server Component fetches its own data directly, and whether that data is cached (and for how long) is a property of the data fetching itself ("use cache", cacheLife), not a separate, page-level exported function.

Client-side data fetching: getInitialProps (legacy) vs. hooks#

getInitialProps (older than getStaticProps/getServerSideProps, runs on both server and client) is now rarely used directly — most Pages Router codebases favor getStaticProps/getServerSideProps for initial data and a client-side library (SWR, React Query) for anything fetched after mount, the same client-fetching pattern still valid in the App Router today.


Try It#

Predict what happens before checking the solution.

export async function getStaticProps() {
  const data = await fetchHomepageContent();
  return { props: { data }, revalidate: 60 };
}

A deploy ships new homepage content. A user requests the homepage 30 seconds after the deploy. Do they see the new content immediately?

Solution

Not necessarily. revalidate: 60 means Incremental Static Regeneration (ISR) — the statically generated page is served as-is until 60 seconds have passed since it was last generated, at which point the next request triggers a background regeneration (stale-while-revalidate, conceptually identical to the App Router's revalidateTag/cacheLife behavior covered in Caching). A request 30 seconds post-deploy, within that window, still gets the previously generated (now-stale relative to the new deploy, unless the deploy itself triggered a fresh build) version.


Implement It Yourself#

Model the decision logic mapping a Pages Router data-fetching choice to its App Router equivalent:

function migrateToAppRouter(pagesRouterFunction) {
  const map = {
    getStaticProps: "async Server Component + 'use cache' (+ cacheLife for revalidate timing)",
    getStaticPaths: "generateStaticParams",
    getServerSideProps: "async Server Component reading runtime data (cookies/headers) — dynamic by default, no caching directive needed",
    "pages/api/*.js": "app/api/*/route.ts (Route Handlers)",
  };
  return map[pagesRouterFunction] ?? "no direct equivalent — reconsider the pattern";
}
 
migrateToAppRouter(

This is the exact translation table worth having memorized for interviews — Pages Router's explicit function names map cleanly onto App Router's implicit, directive-driven equivalents.


Under the Hood#

The underlying shift from "a separate function declares the rendering strategy" to "the component itself, plus a directive, declares it" mirrors the same shift from imperative configuration to declarative co-location that runs through the rest of the App Router — compare to how Caching's "use cache" directive lives directly next to the code it affects, rather than in a separately-named, separately-exported function.


Common Mistakes#

1. Assuming Pages Router knowledge transfers one-to-one, syntactically#

The concepts map cleanly (see the table above), but the code doesn't — getServerSideProps's object-returning signature and getStaticPaths's { paths, fallback } shape have no direct syntactic equivalent in an async Server Component; the underlying behavior maps, not the exact API shape.

2. Not recognizing pages/api/*.js as the direct ancestor of Route Handlers#

Confusing Pages Router API routes with something entirely unrelated to App Router's Route Handlers — they solve the identical problem (a custom request handler for a given path), just with a different file convention and Request/Response API.

3. Treating the Pages Router as fully deprecated or unsupported#

It remains fully supported for existing projects — the App Router is the recommended default for new projects, not a forced migration for everything already running on Pages Router.


Best Practices#

  • For new projects, default to the App Router — it's the current recommendation and where new Next.js features land first.
  • For existing Pages Router codebases, know the migration map (this topic's table) rather than assuming a rewrite is always warranted — many production apps run Pages Router indefinitely without issue.
  • In interviews, be fluent in both the Pages Router terms AND their App Router equivalents — this is one of the most commonly tested "do you actually know Next.js across versions" question types.

Performance Tips#

  • ISR (revalidate in getStaticProps) and the App Router's tag/time-based revalidation (see Caching) solve the identical problem — stale-while-revalidate for content that changes occasionally — just with different APIs.
  • getServerSideProps runs on every request with no caching by default, identical in spirit to an App Router Server Component that reads runtime data without any caching directive — both are the "always fresh, always request-time" end of the spectrum.

generateStaticParams
getServerSidePropsEvery request, server-sideA Server Component that simply doesn't opt into caching — dynamic by default when it reads runtime data (cookies(), headers(), uncached fetches)
pages/api/*.jsAn API endpoint fileRoute Handlers (app/api/*/route.ts)
"getStaticProps"
);
// "async Server Component + 'use cache' (+ cacheLife for revalidate timing)"