Ship text in the response
If a human would need it to understand the page, it belongs in the HTML your server returns. Everything else can hydrate afterwards.
Six patterns account for most of the readable content Lantad measures as missing. Each one has a specific cause in a specific stack, and a change your developer can make this week.
Ordered by how often the scanner raises them. The stack column is where we see the pattern most, not the only place it happens.
| Stack | What causes the loss | The change |
|---|---|---|
| Next.js | Content fetched inside a client component | Move the fetch to a server component, or pre-render the route. |
| React, Vue | A single-page-app shell with no server rendering | Add server rendering, or generate static HTML at build time. |
| Shopify | Review, FAQ and recommendation apps injected after load | Render the app content into the Liquid template, or mirror it in the source. |
| WordPress | Page builders that lazy-render everything below the fold | Disable lazy render for text blocks. Images can stay lazy, copy cannot. |
| Any stack | Tabs and accordions that mount their panel text on click | Ship the panel text in the HTML and hide it with CSS, or use a native details element. |
| Any stack | Consent walls and bot challenges served ahead of the content | Let named AI crawler user agents through at the edge, or serve them the same HTML. |
A linked stack name opens the full guide for that stack. Framer and Lovable are covered by guides of their own in the section below.
Most frameworks can be readable to AI crawlers. The problem is specific choices that hand a no-JavaScript crawler an empty shell. Pick your stack for when that happens and exactly how to fix it.
Next.js hands AI crawlers fully rendered HTML when you use SSR, static generation, or server components, and an empty shell only when your content is rendered client-side or loaded in useEffect after the page mounts.
GuideReact is not invisible to AI, but a client-rendered single-page app ships an empty div and builds the page in the browser, so a crawler that does not run JavaScript receives a shell with almost no text.
GuideA published Framer site is pre-rendered to static HTML and is usually readable without JavaScript, so when ChatGPT misses your content the cause is specific: a code component, an embed, or an interaction that keeps text out of the HTML.
GuideShopify themes are server-rendered Liquid, so most of your store is already readable to AI crawlers, and the real gap is the content third-party apps and widgets inject with JavaScript after the page loads.
GuideLovable server-renders new projects by default and serves older client-rendered projects a rendered copy to recognized crawlers, so many sites are readable. The gap is browser-fetched content and any crawler Lovable does not recognize.
Every fix on this page is the same idea applied to a different tool: the words have to be in the response, not assembled after it.
If a human would need it to understand the page, it belongs in the HTML your server returns. Everything else can hydrate afterwards.
A collapsed accordion whose text is in the DOM and hidden with CSS is fully readable. One that inserts its text on click is invisible.
Deferring images is good practice and costs you nothing here. Deferring paragraphs is the single most common cause of a low score.
A perfect render path still scores zero if your CDN serves a challenge page to GPTBot. Access and parity are separate sub-scores for this reason.
The report ranks by impact rather than by severity label, so the order it gives you is the order worth working.
One block carrying 40% of the page's words outranks four small findings. The ranking already accounts for this.
If the same defect appears across a multi-page scan, it is one change in one template rather than eight separate tickets.
The scan is free and takes under a minute. A fix that did not move the number is a fix that did not work.
Parity regressions are silent: nothing looks wrong in a browser. Monitoring exists because this is the failure mode that comes back.
Almost every parity problem is one of six things. Content fetched inside a client component, a single-page-app shell with no server rendering, storefront apps injected after load, page builders that lazy-render text, tabs and accordions that mount panel text on click, and consent walls served ahead of the content.
None of these are exotic. They are the default behaviour of popular tools, which is exactly why so many sites have the problem without knowing it.
Client-component fetching on Next.js and app-injected content on Shopify, by a distance. Both are the framework's default path rather than a mistake, which is why they show up on sites built by people who know what they are doing.
No. Static generation at build time works just as well, and for most marketing pages it is simpler. The requirement is that the words are in the response, not which mechanism put them there.
No. The list is ranked by impact because the top item is usually most of the problem. Clearing the first one or two findings typically moves a score more than clearing the remaining six.
Interactive tools, dashboards and configurators are not the problem. The problem is prose behind JavaScript. If a paragraph explains what you sell, it belongs in the HTML; if it is a live calculator, nobody expects a crawler to run it.
Generally the opposite. Server-rendered or pre-rendered text arrives faster than text fetched in a second round trip after hydration, so the same change usually improves both the parity score and time to first contentful paint.
The scan names the pattern, shows the words that went missing, and links the fix for your stack. Free, no signup, under a minute.