---
title: "SPA SEO Rendering Failures: Fix Empty Pages | Aemorph"
url: https://aemorph.com/guides/spa-seo-rendering-failures/
description: "SPA SEO rendering failures leave crawlers an empty page where your content loads by JavaScript. See why AI crawlers miss it and how server rendering fixes it."
schema_type: TechArticle
publisher: Aemorph
publisher_entity: https://aemorph.com/entitymap.json#org_aemorph
entities: [concept_spa_rendering_failure]
language: en-SG
updated: 2026-11-01
---

Guides

# SPA SEO Rendering Failures: Why Your JavaScript App Shows Crawlers an Empty Page

**SPA [SEO](https://aemorph.com/glossary/#seo-search-engine-optimisation) rendering failures leave crawlers an empty page shell where your content loads by JavaScript.** The facts about your business then never reach the engines your buyers ask. A single-page app, or SPA, builds its pages in the visitor's browser. Google renders that JavaScript in a separate, later step. Vercel's study of 17 December 2024 found that OpenAI's crawlers, Anthropic's ClaudeBot and PerplexityBot do not render JavaScript. The fix serves the full page content in the HTML from the server.

[Book a strategic conversation](https://aemorph.com/contact/)

Written by [Kevin Dam](https://aemorph.com/about/), founder of Aemorph, who has practised SEO since 2010 and sits on the [Forbes Agency Council](https://councils.forbes.com/profile/Kevin-Dam-Global-Search-Architect-%7C-SEO-GEO-AEO-IMO-LLM-Visibility-Aemorph/4c8c7a38-1285-470d-8ea8-e517a310a00b). Aemorph is a [Google Partner](https://www.google.com/partners/agency?id=4441861842). [LinkedIn](https://www.linkedin.com/in/kevindam)

---

## Rendering Failures Show Up as a Site Visitors See and Crawlers Miss

**An SPA rendering failure shows up as a site that looks complete in a browser while its raw HTML holds little more than a script tag and an empty container, so crawlers that skip JavaScript find no text, no links and no facts to index or cite.** The gap shows only when you compare the page source with the rendered page.

| Symptom | Where you see it | Likely cause to test | Fix | Where it gets fixed |
| --- | --- | --- | --- | --- |
| The page source holds no body text | View source, or a Screaming Frog crawl with JavaScript rendering off | Content built in the browser by JavaScript | Server-side rendering, static rendering or hydration | Application framework and hosting |
| AI chats describe your business from other sites, never your own | Tested prompts in ChatGPT, Claude and Perplexity | AI crawlers that skip JavaScript read an empty shell | Serve core content in the initial HTML | Application framework |
| Routes share one title and description | Search results and a crawl of page titles | Titles and meta tags set only by JavaScript, or not set | Render title, description and canonical tag per route in the HTML | Route templates |
| Missing pages return a 200 status | URL Inspection in Search Console, soft 404 reports | Client-side routing serves the app for each URL | Redirect to a URL that returns 404, or add noindex by JavaScript to error views | Router and server |
| Internal pages go undiscovered | Search Console page indexing report and a crawl | Links built as click handlers or fragment URLs, not a elements with href | Use a elements with href and History API URLs | Navigation components |

*Symptoms, likely causes and fixes for SPA SEO rendering failures.*

SPA rendering failures sit in a group of technical faults that stop the right page being read, and [responsive template heading failures](https://aemorph.com/guides/responsive-template-heading-failures/) start in the same place: the template your developers reuse on each page. Migration redirect failures follow a move to a JavaScript framework when old URLs go unmapped, keyword cannibalisation splits rankings between pages, and the web design and development guide covers build choices before launch.

### Why is Google not indexing my single-page app?

**Google does not index a single-page app fully when the content, titles or links exist only after JavaScript runs and the render step fails, times out or meets routes that return a 200 status for missing pages.** URL Inspection in Search Console shows the rendered HTML Google received for a page.

---

## Rendering Fails Because an SPA Sends Two Readers Two Different Pages

**SPA rendering failures form because a single-page app sends two different pages: an empty shell in the HTML response and a full page only after JavaScript runs, so each crawler sees whichever version its own rules reach.** Google processes JavaScript pages in three phases: crawling, rendering and indexing. Google states that a page waits in a render queue for a few seconds, and that the wait runs longer in some cases.

AI crawlers read the first version only. Vercel's network study of 17 December 2024 found that OpenAI's crawlers and Anthropic's ClaudeBot fetch JavaScript files but do not execute them, so they do not read content rendered in the browser. Gemini uses Googlebot's infrastructure and renders JavaScript.

*[Sources: Google Search Central, October 2026, and Vercel, December 2024](https://aemorph.com/sources/#google-search-central-and-vercel-spa-seo-rendering-failures)*

An SPA that ships an empty shell removes your own site from the sources these AI crawlers read, so the AI chats describe your business from directories, reviews and other sites. Aemorph's [EAV Exhaustion Methodology](https://aemorph.com/guides/eav-exhaustion-methodology/) counts each fact slot your site fills; an empty shell fills not one of them for those crawlers.

### Do AI crawlers read JavaScript content?

**In Vercel's December 2024 tests, OpenAI's crawlers, Anthropic's ClaudeBot and PerplexityBot fetched pages without running their JavaScript, while Gemini rendered it through Googlebot and AppleBot through a browser-based crawler.** Content that appears only after JavaScript runs stays unread by crawlers that skip JavaScript.

---

## The Fix Serves Each Route's Full Page From the Server

**Fixing an SPA rendering failure serves each route's content, title, description, canonical tag and links in the initial HTML through server-side rendering, static rendering or hydration, so crawlers read the full page without running JavaScript.** Google recommends those three approaches and describes dynamic rendering, serving crawlers a separate pre-rendered version, as a workaround and not a recommended solution:

1.  **Compares** the raw HTML with the rendered page for each template, with a Screaming Frog crawl run twice, JavaScript rendering off and on.
2.  **Lists** each fact, link and tag that appears only in the rendered version.
3.  **Specifies** server-side rendering, static rendering or hydration for each affected template, chosen to fit your framework and hosting.
4.  **Moves** titles, meta descriptions, canonical tags and robots tags into the server-rendered HTML for each route, and keeps noindex out of the initial HTML of a page you want indexed.
5.  **Replaces** click-handler and fragment links with a elements that carry an href, and fragment URLs with History API paths.
6.  **Returns** a true 404 status for missing routes, or applies noindex to error views, so empty routes stop reaching the index.
7.  **Verifies** the result with URL Inspection in Search Console, a repeat crawl with JavaScript off and tested prompts in the AI chats.

Aemorph specifies the rendering change, your developers or IT vendor implement it, and Aemorph verifies it once live.

### Is dynamic rendering still a good fix for SPA SEO?

**Dynamic rendering is no longer Google's recommended fix: Google describes it as a workaround that creates extra complexity and resource demands, and recommends server-side rendering, static rendering or hydration instead.** Sites still running dynamic rendering keep it working while the move to server rendering is planned.

---

## Each New Route Ships Empty Until the Rendering Method Changes

**An SPA rendering failure applies to each route the app serves, so each new page your team adds ships to AI crawlers as an empty shell until the rendering method changes.** Aemorph checks rendering on each new template and each framework upgrade.

| Rendering state | What crawlers receive | What it costs you | Next step | What triggers a recheck |
| --- | --- | --- | --- | --- |
| Client-side rendering only | An empty shell; Google renders later | AI crawlers read nothing from your site | Move core templates to server rendering | A new route or template |
| Server-rendered shell, content by JavaScript | Navigation and footer, no body content | Pages index thin and AI answers miss your facts | Render the body content on the server | A content model change |
| Server rendering with JavaScript-only meta tags | Content, but shared or missing titles and canonical tags | Duplicate titles and the wrong canonical URL | Render meta tags per route in the HTML | A routing or SEO plugin change |
| Full server or static rendering | The complete page in the first response | Crawlers read the same page visitors see | Keep the two-crawl comparison in each release | A framework upgrade or a new hosting setup |

*Cost and recheck point by rendering state, as illustrative scenarios.*

Aemorph sets no fixed recheck interval. Your first working day with Aemorph is the first check date, and pages are then assigned for update in order of importance: bottom-of-funnel, middle-of-funnel, then top-of-funnel. For an app, that puts service, pricing and contact routes first.

### Does an SPA need to be rebuilt to fix SEO?

**The rendering fix depends on the app's framework, architecture and hosting: the major SPA frameworks, including Next.js for React and Nuxt for Vue, support server-side rendering, static rendering or hydration, and on those frameworks the fix changes how each route is rendered, starting with the templates that carry your service and pricing pages.** Aemorph checks the framework, architecture and hosting first, because they decide whether a rendering change is enough or a larger rebuild is needed.

---

## Disclosures That Load by JavaScript Drop Out of AI Answers

**A disclosure that loads only after JavaScript runs is missing from what most AI crawlers read, so an AI answer about your product draws on a page without its conditions, fees or eligibility rules.** The page a visitor sees is complete; the version the crawler read is not.

Where a page carries regulated statements, such as a financial product's fees and risks, a health service's conditions or a licence number, the statement belongs in the server-rendered HTML beside the claim it qualifies. Aemorph checks the raw HTML of each regulated page against your [verified record](https://aemorph.com/glossary/#verified-record), the one approved set of facts about your business, after each rendering change. A question about a specific obligation is one for a qualified legal adviser in your jurisdiction.

*General guidance, not legal advice.*

### Does content loaded by JavaScript count for compliance?

**Content loaded by JavaScript appears to visitors whose browsers run it, but it is missing from what most AI crawlers read, so a disclosure that only loads by JavaScript leaves AI answers about your offer without it.** Regulated text sits most safely in the server-rendered HTML beside the claim it qualifies.

---

## Technical SEO Makes Your App Readable to Google and the AI Crawlers

**Aemorph's [technical SEO](https://aemorph.com/services/technical-seo/) compares what each crawler receives with what visitors see, specifies the rendering change for each template and verifies it once live, so Google and the AI crawlers read the same facts your buyers read.** The audit records your robots.txt rules for GPTBot, ClaudeBot, PerplexityBot and Google-Extended alongside the rendering check, and the free [Money on the Table audit](https://aemorph.com/glossary/#money-on-the-table-audit) puts a number on the revenue lost at your current visibility in search.

The [Showstopper Sensor](https://aemorph.com/glossary/#showstopper-sensor-sprint-1) (Sprint 1), a 30-day showstopper-answer sprint for ChatGPT, Claude, Gemini and Perplexity, publishes your approved answers to your [showstopper questions](https://aemorph.com/glossary/#showstopper-questions), the buyer questions that stop a purchase when AI answers them badly, on your site. An answer that loads by JavaScript stays unread by the AI crawlers that skip it, so Sprint 1 answers belong on pages that serve their content in the HTML.

### Who fixes SPA rendering failures, Aemorph or your developers?

**Aemorph specifies the fix and your developers or IT vendor implement it: Aemorph compares what each crawler receives, specifies the rendering method and meta tags per template, and verifies the raw HTML once live.** Your team keeps control of the framework, hosting and release schedule.

Start with a free [strategic conversation](https://aemorph.com/glossary/#strategic-conversation), which includes prompting the AI chats for your current brand answers. Technical SEO fixes are scoped from the audit findings and set out in your quote; starting points are on the [pricing page](https://aemorph.com/pricing/).

[Book a strategic conversation](https://aemorph.com/contact/)

[See technical SEO](https://aemorph.com/services/technical-seo/)

THE STRATEGIC CONVERSATION

## Start with a free *strategic conversation*.

Every Aemorph engagement starts with a free strategic conversation. It is the fastest way to see whether Aemorph fits your business before you commit budget.

[Book a strategic conversation →](https://aemorph.com/contact/)

STARTING POINT

Free

You talk through your goals with Aemorph, and Aemorph quotes your engagement after the conversation.
