ssrchecker
HomeCheckFrameworksGatsby

Is your Gatsby site rendering content? (Usually yes — with two catches)

Short answer
Gatsby pre-renders every page to static HTML at build time, with data baked in through GraphQL, so most Gatsby pages return complete content to crawlers. The two things that break this are Deferred Static Generation (defer: true), where a page isn't built until its first request, and a hydration mismatch that blanks the page in the browser even though the HTML is correct.

Gatsby sits on the reassuring side of this set. Like Astro, its default output is real HTML — you are not fighting an empty shell the way you would with a plain React SPA. The interesting part of a Gatsby diagnosis is not "is the content there" but two subtler questions: was this specific page built yet, and does it survive rehydration in the browser.

Check your Gatsby site
https://

Why a Gatsby build is safe by default

Running gatsby build executes your GraphQL queries, pulls the data they resolve, and writes a complete static HTML file for every page the build knows about. By the time the site is deployed, the content is already inside the HTML — there is no client-side assembly step for a crawler to wait on. That is why a healthy Gatsby page returns a content ratio at or near 100% with all metadata present before any JavaScript runs.

The mental model that trips people up: Gatsby is a build-time framework, not a request-time one. The HTML you serve was produced once, at build, not freshly on each request. Every Gatsby-specific issue below flows from that single fact.

The DSG first-request gap

Deferred Static Generation exists to shorten long builds. Marking a page with defer: true in createPages tells Gatsby not to build that page during gatsby build. Instead, the page is generated the first time someone requests it, then cached and served statically from then on. It is Gatsby's answer to sites with tens of thousands of pages where building all of them every time is impractical.

The SEO catch is the very first request. If Googlebot is the first visitor to a deferred page, it triggers the build and may receive a slow response — or, if your hosting mishandles the deferred path, an error or a shell — rather than the finished page. Once the page has been built once, it behaves like any other static page. So a DSG page that checks fine for you (because you already visited it) can still have been served an unbuilt version to the crawler that arrived first. Reserve DSG for genuinely low-priority pages, and keep anything you need indexed promptly in the normal build.

The rehydration blank-flash

This is the Gatsby failure that a green verdict can hide, so it is worth understanding precisely. Gatsby ships correct static HTML, then React rehydrates it in the browser to make it interactive. If the React tree the browser builds does not match the HTML Gatsby wrote at build time, React discards the server HTML and re-renders from scratch — which can flash a blank page, drop content, or scramble the layout.

Why the checker can read green here
The raw HTML genuinely contains your content, so the content ratio is high and the verdict is green. The break happens only after hydration, in the rendered pane. Compare the two panels: if the raw HTML looks complete but the rendered screenshot is blank or broken, you are looking at a rehydration mismatch, not a rendering-location problem. That's covered in depth on the hydration mismatch page.

The usual triggers are the same ones that break any React hydration: rendering new Date() or random values directly, branching on typeof window during render, or invalid HTML nesting that the browser silently corrects. In Gatsby these show up disproportionately because so much of the page is prebuilt — the gap between build output and browser render is exactly where they live.

Stale build-time data

Because GraphQL resolves at build time, the content in your HTML is a snapshot from your last build. Publish an article in your CMS, and it does not appear on the site — or in this checker — until a new build runs. This is not a rendering failure and the tool will not flag it as one, but it is the single most common reason a Gatsby page "isn't showing new content." If your content changes often, wire your CMS to trigger a rebuild on publish, or move the fast-changing pages to getServerData so they render per request.

Side-by-side comparison of a Gatsby page's raw HTML showing full static content versus a rendered pane that has gone blank after a hydration mismatch
The Gatsby trap a green ratio hides: correct HTML, broken rehydration.

Client-only routes are fine — if they shouldn't index

Gatsby supports client-only routes for app-like sections — a logged-in dashboard, an account area — using matchPath so a whole path prefix is handled by client-side routing. These sections are intentionally browser-rendered and will show as CSR in this check. That is correct and fine: dashboards should not be indexed. It only becomes a problem if something that should rank ended up behind a client-only route by accident. Check that your marketing and content pages are ordinary built pages, not swept into a client-only prefix.

Your configuration and the verdict to expect

Find your setup. On Gatsby, an unexpected amber or red almost always points to DSG, hydration, or a client-only route rather than to missing content.

SetupExpectWhy
gatsby build (default SSG page)SSRPre-rendered to static HTML at build with data baked in. The default and the good case.
A page using getServerData (Gatsby SSR)SSRRendered per request to full HTML. Gatsby's true on-demand path.
A DSG page (defer: true), already built onceSSRFirst request built and cached it; now it serves static HTML like any other.
A DSG page (defer: true), never requested yetHYBRID or blockedNot built at build time. The first crawl can hit an unbuilt or slow response before the cache exists.
A page with a hydration mismatchSSRContent IS in the HTML (green ratio), but React discards it on rehydration and can blank the page in the browser.
A client-only route (matchPath / app shell)CSRIntentionally browser-rendered app section. Fine if it shouldn't index — a problem if it should.
Content added to the CMS after the last buildSSR (stale)GraphQL resolves at build time. New content isn't in the HTML until you rebuild.
A component fetching its content client-sideHYBRIDThe static shell is present; the client-fetched section is not until after load.

When Gatsby actually breaks

01
A hydration mismatch blanks the page
The most damaging one, because the HTML is correct and the checker's ratio reads green. React discards the build output on rehydration. Trace nondeterministic renders and typeof window branches.
02
A DSG page served unbuilt to the first crawler
Deferred pages build on first request. If Googlebot arrives first, it can get a slow or incomplete response. Keep pages that need prompt indexing in the normal build.
03
New content missing because there's been no rebuild
GraphQL data is a build-time snapshot. Trigger rebuilds on CMS publish, or move volatile pages to getServerData.
04
A content section fetched client-side
Bolting a client-side fetch onto an otherwise static Gatsby page recreates the SPA problem for that section. Prefer sourcing it into the GraphQL layer at build.
05
Real content behind a client-only route
matchPath sections render only in the browser. Correct for dashboards, wrong for anything indexable that slipped into that prefix.

Gatsby rendering FAQ

By default Gatsby uses static site generation, not per-request server rendering: it pre-builds every page to static HTML at build time with data resolved through GraphQL. For crawlers the outcome is the same as SSR — complete HTML on the first request. Gatsby also offers getServerData for genuine per-request rendering when a page needs it.