Open-Source Wikis

/

Next.js

/

Systems

/

Pages Router

vercel/next.js

Pages Router

The original Next.js router, rooted at the pages/ directory in user code. Still fully supported alongside the App Router. Many production apps run both routers in the same project.

Anatomy

graph TD
    Request[Request] --> Match[base-server matches /pages route]
    Match --> Module[Pages route module<br/>route-modules/pages/]
    Module --> Render[render.tsx<br/>renderToHTML]
    Render --> GetData[getServerSideProps<br/>getStaticProps<br/>getInitialProps]
    GetData --> ReactRender[React.renderToString /<br/>renderToPipeableStream]
    ReactRender --> Response[HTML response]

Server side

render.tsx

packages/next/src/server/render.tsx (51 KB) is the entry point. It:

  1. Loads the page module, the _app, and the _document from .next/.
  2. Runs the page's data-fetching method (getServerSideProps, getStaticProps, getInitialProps).
  3. Calls React's renderToString (or the streaming variant) on <App pageProps={...}><Component /></App>.
  4. Wraps the result in the <Document> shell.
  5. Serializes data into the __NEXT_DATA__ script tag for client hydration.

Despite being part of the older router, this file is still actively maintained — App Router improvements often have a Pages Router counterpart.

Static and SSG

getStaticProps returns either pre-rendered HTML files (built via packages/next/src/build/static-paths/) or pages with a configured revalidate interval. The runtime serves the cached HTML and re-runs the data fetch on revalidation triggers.

API routes

pages/api/* files become serverless API endpoints. They are dispatched through packages/next/src/server/route-modules/pages-api/ and run in the Node runtime.

The request and response objects are augmented with helpers like req.cookies, res.json(), res.status(). The augmentation lives in packages/next/src/server/api-utils/.

Built-in pages

packages/next/src/pages/ contains the framework's built-in _app, _document, and _error defaults that are used when the user doesn't provide their own.

Client side

router.ts

packages/next/src/client/router.ts is the user-facing API surface (useRouter, withRouter). It re-exports the router state from packages/next/src/shared/lib/router/router.ts (2,630 lines) — the actual Pages Router state machine.

The state machine handles:

  • Client-side navigation (router.push, router.replace)
  • Prefetching of next/link targets
  • Scroll restoration
  • Page transitions
  • Locale-aware routing for i18n
  • Re-renders when getServerSideProps data changes

Hydration

After the server renders the HTML, the client picks up the __NEXT_DATA__ JSON, hydrates <App> with it, and starts the router. The hydration entry is packages/next/src/client/index.tsx (31 KB).

Coexistence with the App Router

Both routers can serve the same project:

  • A request to /about matches a Pages Router page if pages/about.tsx exists.
  • A request to /dashboard matches an App Router page if app/dashboard/page.tsx exists.
  • If both define the same path, the App Router wins by default. The framework warns about the conflict at build time (see packages/next/src/build/validate-app-paths.ts).

The route matcher managers (packages/next/src/server/route-matcher-managers/) coordinate this dispatch.

Data fetching APIs

API When File
getInitialProps Pre-Next.js-9 legacy Page-level
getServerSideProps SSR per request Page-level
getStaticProps Build-time / ISR Page-level
getStaticPaths Defines dynamic SSG paths Page-level

The framework reads these exports via SWC analysis (packages/next/src/build/analysis/) at build time to decide each page's rendering mode.

Custom Document and App

Users override the document shell and the per-page wrapper:

  • pages/_document.tsx — defines <html>, <body>, and where <Head>, <Main>, and <NextScript> mount.
  • pages/_app.tsx — wraps every page; common place for layout and providers.

Default implementations live in packages/next/src/pages/_document.tsx and _app.tsx.

i18n

The Pages Router has built-in support for locale subpaths and domain locales. Configuration is the i18n block in next.config.js. Implementation: packages/next/src/server/lib/i18n-provider.ts. The App Router handles internationalization via user-defined middleware and dynamic segments — there is no built-in i18n config for the App Router.

Integration points

  • The build pipeline analyzes page exports to decide rendering mode (see build).
  • next/link and next/router from this codebase back the public API.
  • Pre-rendered output is cached by the caching layer.
  • pages/api/* requests are dispatched by the same server runtime as other routes.

Entry points for modification

  • To change Pages rendering: packages/next/src/server/render.tsx.
  • To add a new data-fetching helper: packages/next/src/build/analysis/ (recognition) + packages/next/src/server/route-modules/pages/ (execution).
  • To change client navigation: packages/next/src/shared/lib/router/router.ts.
  • To change i18n behavior: packages/next/src/server/lib/i18n-provider.ts.

Key source files

File Purpose
packages/next/src/server/render.tsx Pages Router server renderer
packages/next/src/server/route-modules/pages/ Pages route module
packages/next/src/server/route-modules/pages-api/ API route module
packages/next/src/server/api-utils/ req/res augmentation
packages/next/src/pages/ Built-in _app, _document, _error
packages/next/src/client/router.ts useRouter, withRouter user-facing API
packages/next/src/shared/lib/router/router.ts Client router state machine
packages/next/src/client/index.tsx Pages Router hydration entry
packages/next/src/server/lib/i18n-provider.ts i18n locale resolution

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Pages Router – Next.js wiki | Factory