Next.js SEO: keep your routes indexed even when you ship Client Components
Next.js can serve fully-rendered HTML, but the moment a route is marked 'use client' or fetches data with useEffect, Googlebot reads an empty shell. Hydration takes seconds; crawlers don't wait.
This is a known problem, and the fix is simpler than you think.
Don't want an external tool? We understand.
If you're prepared to refactor every interactive route into a Server Component, move data fetching into loaders, and rebuild any state machines that assume the browser exists, that's the right long-term answer. PageGlass is the five-minute bridge for the routes you don't have time to rewrite.
Fix this in three steps
- Run a free Next.js scan. Confirm the bot visibility gap caused by Next.js client component rendering - the scan takes ten seconds and needs no signup. You get exactly what Googlebot, Bingbot, and the AI crawlers see when they hit your URLs today, side by side with what your users see.
- Add one CNAME record. Point your Next.js site's domain through PageGlass in your DNS provider. The change takes thirty seconds and is fully reversible. Zero code changes, no deploy, no impact on the bundle your real users download.
- Next.js content is now indexable. Bot traffic now receives fully-rendered HTML for every URL on your Next.js site, while human visitors keep getting the exact same dynamic experience as before. Come back to PageGlass and run the scan again to confirm the fix.
Where Next.js SEO actually breaks
Next.js gets credit for being SEO-friendly, and it deserves it - but only
for the parts of your application that are Server Components or use the
Pages Router data-fetching APIs. The moment you mark a page or layout with
'use client', every component below that boundary renders in
the browser. Googlebot still receives HTML, but it's the App Router's
streaming shell, not your content.
The most common pattern that breaks is dashboards or detail pages that
load data with useEffect + fetch or with
useSWR. These run after the React tree mounts, which means
the crawler sees the loading skeleton, not the data.
Common Next.js fixes that don't actually work
- Setting metadata via useEffect. The effect runs after hydration. Crawlers reading the initial HTML never see the title or description you set this way.
- next/head inside a 'use client' component. Deferred until hydration. Same outcome as the useEffect pattern.
- Server Component with a client-only child that owns the data. Looks server-rendered in the parent, but the heading, list, or table that crawlers care about is filled in only after the client child fetches and renders. The shell is server-rendered; the content isn't.
- Trusting Search Console URL inspection. The inspection tool runs Google's full rendering service, which executes JavaScript. A page can pass URL inspection and still be invisible to the first-pass crawler that decides whether to render at all.
What actually works
Three paths: (1) refactor each affected route to a Server Component with
server-side data fetching, which is the official answer but a real time
cost; (2) move to generateStaticParams + ISR for routes
with stable data, accepting that personalised routes still need
another solution; or (3) use PageGlass to detect bot user-agents at the
edge and serve a fully-rendered HTML version of every route - including
Client Components - without touching your application code. The third
option is what most teams actually choose when the rewrite isn't on
this quarter's roadmap.