Is your Next.js page actually server-rendered?
"use client" does not turn that off. Pages come back client-rendered mainly when their main content is fetched inside useEffect or a client data-fetching hook, which runs only after hydration.That default is why the Next.js diagnosis is usually more subtle than a plain React SPA. The page is rarely empty — it comes back as a server-rendered shell with the parts that matter missing, which reads as HYBRID rather than CSR. That verdict is easy to dismiss and is normally the one worth acting on.
What "use client" actually does
This is the most common misunderstanding in Next.js SEO, and it costs people real time. "use client"does not mean "render this in the browser only". Client components are still prerendered on the server into HTML. The directive marks a boundary for hydration and interactivity, not for rendering.
A page with "use client" at the top and content in its JSX will pass this check with a green verdict. What breaks SEO is not the directive — it is fetching data inside the component after mount. The directive is a prerequisite for that pattern, which is why the two get blamed together.
A client component that receives its data as props from a server component. The data is resolved before the HTML is sent.
A client component that calls an API inside useEffect and renders a spinner until it resolves. Crawlers capture the spinner.
App Router and Pages Router fail differently
Both routers server-render by default, but the way they break is not the same, and the fix differs accordingly.
In the App Router, components are server components unless marked otherwise. The failure mode is a server component that renders a client child which then fetches the real content. The page looks server-rendered — the header, nav and footer are all in the HTML — while the product grid or article body is absent. That produces a HYBRID verdict with a high content ratio, which is exactly the result people skim past.
In the Pages Router, the split is more explicit. A page with getServerSideProps or getStaticProps resolves its data before the HTML is sent. A page with neither, doing its fetching in useEffect, is effectively a client-rendered route inside an otherwise server-rendered app. Because it is per-page, you can have some URLs indexing well and others not indexing at all in the same deployment — which is usually what sends people looking for a checker in the first place.
SSG, SSR and ISR all pass this check
A point worth being clear about, because it causes unnecessary re-architecture: this tool cannot distinguish static generation from server-side rendering, and neither can Googlebot. Both deliver complete HTML on the first request. So do incrementally regenerated pages.
The choice between them is about data freshness and infrastructure cost, not about SEO. If someone is proposing a move from getStaticProps to getServerSideProps for ranking reasons, that is not a rendering fix — and it will make your pages slower to serve.
Your configuration and the verdict to expect
Find your setup below. If the tool gives you something different from the expected verdict, that difference is the bug.
Why a Next.js page comes back CSR or HYBRID
In rough order of how often each one turns out to be the cause:
Metadata, canonicals and the title mismatch
A separate failure worth checking even when the body content passes. If Google shows a title that is not the one you set, the title is probably being written client-side.
The Next.js metadata export and generateMetadata both run on the server and put tags in the initial HTML — that is the correct approach. Setting document.title in an effect, or using a client-side head library carried over from an older React setup, means the tags are not there when the raw HTML is captured. The check reports title, description and canonical separately from body content for exactly this reason.
Next.js rendering FAQ
Yes. In the App Router every component is a server component unless it is marked with the use client directive, and pages are prerendered to HTML on the server. A page only fails a rendering check when its main content is fetched client-side after hydration.
