Both architectures are capable of delivering fully-rendered, indexable HTML to Googlebot, so the fundamental indexability principle doesn’t change between them: Google indexes what ends up in the rendered DOM, regardless of which Next.js rendering model produced it. The Pages Router’s getServerSideProps renders a complete page server-side on every request, producing finished HTML before it reaches the client, which is straightforwardly crawlable. The App Router’s React Server Components also render server-side by default and stream HTML to the client, which remains crawlable, but the architecture introduces more moving parts, streaming boundaries, Suspense fallbacks, and client-component hydration, where content can end up delayed past what Googlebot’s rendering process captures if implemented carelessly. The practical difference isn’t “one is indexable and one isn’t,” it’s that the App Router has more places where a mistake can create a rendering gap.
What getServerSideProps does, mechanically
In the Pages Router model, getServerSideProps runs on the server for every request, fetches whatever data the page needs, and returns fully populated props that get rendered into complete HTML markup server-side before that HTML is sent to the browser (or to Googlebot). By the time Googlebot receives the response, the primary content is already present in the HTML document itself, with no dependency on client-side JavaScript execution to appear. This is the most straightforward pattern from an indexability standpoint precisely because there are fewer stages between “server has the data” and “content is present in the HTML Googlebot reads.”
What the App Router changes
React Server Components in the App Router also execute on the server and by default produce HTML, so the baseline behavior is similarly server-rendered rather than client-rendered. The architectural difference is that the App Router is built around streaming: rather than waiting for the entire page’s data to resolve before sending any HTML, it can send an initial shell immediately and stream in additional HTML for slower-loading sections as their data resolves, using Suspense boundaries to define these chunks. This is a genuine user-experience improvement, since it lets fast content appear immediately rather than blocking on the slowest data dependency.
For crawling, this introduces a timing question that didn’t exist in the same form under getServerSideProps: whether Googlebot’s rendering process waits long enough, and processes the page in a way that captures, content that arrives via a later stream chunk rather than the initial HTML response. Google’s rendering infrastructure is built on a modern, evergreen Chromium engine that does process JavaScript and can handle streamed and client-rendered content generally, but any architecture that defers meaningful content behind additional async operations, slow data fetches, or JavaScript that only runs after certain conditions, carries some risk that the content isn’t captured within Googlebot’s rendering budget, and streaming boundaries are exactly the mechanism that can introduce that delay if a critical content section is placed behind a slow Suspense fallback.
The other App Router-specific risk is the interaction between Server Components and Client Components. Content that depends on client-side data fetching, inside a component explicitly marked as a Client Component using its own useEffect or similar client-side fetch pattern, rather than on the Server Component’s own server-side data fetching, behaves like any client-rendered JavaScript content: it has to execute correctly and within budget for Googlebot to see it, which is a different and generally riskier path than data that’s already resolved server-side as part of the Server Component tree.
Hypothetically, imagine a hypothetical publisher we’ll call “Site F” migrating a product catalog from the Pages Router to the App Router. If the team wrapped the product description and pricing block in a Client Component that fetches its data client-side after mount, purely to reuse an existing component, hypothetically that specific block could end up missing from Googlebot’s rendered HTML even though the rest of the page, built with ordinary Server Components, renders and indexes normally.
Where the two approaches are actually equivalent
For the core question of “can Google index the content this page displays,” neither architecture is inherently superior once implemented correctly. A getServerSideProps page can still fail to be indexable if it conditionally renders content based on client-side state that never reflects server data. An App Router page built entirely with Server Components and no unnecessary Client Component data-fetching is just as reliably server-rendered as the Pages Router equivalent, arguably with less client-side JavaScript overall since Server Components don’t ship their rendering logic to the client at all. The framework choice doesn’t predetermine the outcome, the specific implementation choices within either framework do.
Why there’s no Google-specific guidance singling out either approach
Google’s own JavaScript SEO documentation is deliberately framework-agnostic: it describes the general principle of verifying rendered output regardless of what rendering technology produced it, and doesn’t publish framework-specific guidance comparing Next.js’s routing paradigms. Any claim that Google has issued guidance specifically evaluating App Router versus Pages Router should be treated skeptically, the accurate framing is that Google’s general rendering-verification guidance applies equally to both, and the practical differences described above come from how each architecture’s mechanics interact with that general guidance, not from any framework-specific statement Google has made.
Practical implication, comparison summary
| Consideration | Pages Router (getServerSideProps) | App Router (Server Components) |
|---|---|---|
| Default rendering location | Server, per request | Server, by default |
| Content delivery model | Complete HTML in initial response | Streamed HTML across Suspense boundaries |
| Main indexability risk | Minimal if data-fetching is synchronous to render | Content behind slow/late Suspense boundaries or Client Component fetches |
| Verification method | URL Inspection rendered HTML | URL Inspection rendered HTML |
Regardless of which router is in use, verify actual indexability using Search Console’s URL Inspection tool to view the rendered HTML Google captured for representative pages, checking specifically that primary content appears complete and isn’t confined to a Client Component relying on its own client-side fetch. Where the App Router’s streaming introduces meaningful delay for primary content, consider moving that data-fetching earlier in the Server Component tree rather than assuming the framework’s default behavior guarantees full capture.