---
title: "Configure React, Vue, and Angular rendering so search engines index every page"
description: "Compare CSR, SSR, SSG, and ISR, then set up Next.js, Nuxt, and Angular with server metadata, JSON-LD, sitemaps, crawlable links, and lean bundles."
canonical: "https://scalewithsearch.com/articles/javascript-seo-frameworks"
date: "2026-03-20"
modified: "2026-09-25"
---
## Site navigation

- [Scale With Search](https://scalewithsearch.com/)
- Real estate
  - Real estate
    - [Real estate](https://scalewithsearch.com/for/real-estate)
- Work
  - Start here
    - [Send your brief](https://scalewithsearch.com/work#send-your-brief)
    - [Prepare your six-question brief](https://scalewithsearch.com/work#prepare-your-six-question-brief)
  - Build
    - [Site build, content library with SEO, signal desk](https://scalewithsearch.com/work)
- For your business
  - Trades and home services
    - [Auto body and collision shops](https://scalewithsearch.com/for/auto-body-and-collision-shops)
    - [Foundation and home repair contractors](https://scalewithsearch.com/for/foundation-and-home-repair)
    - [Garage door and fencing contractors](https://scalewithsearch.com/for/garage-door-and-fencing-contractors)
    - [HVAC contractors](https://scalewithsearch.com/for/hvac-contractors)
    - [Janitorial and commercial cleaning companies](https://scalewithsearch.com/for/janitorial-and-commercial-cleaning)
    - [Locksmiths](https://scalewithsearch.com/for/locksmiths)
    - [Moving companies](https://scalewithsearch.com/for/moving-companies)
    - [Pest control companies](https://scalewithsearch.com/for/pest-control-companies)
    - [Plumbing and electrical contractors](https://scalewithsearch.com/for/plumbing-and-electrical-contractors)
    - [Restoration and water or fire damage companies](https://scalewithsearch.com/for/restoration-and-water-fire-damage)
    - [Roofing companies](https://scalewithsearch.com/for/roofing-companies)
    - [Towing companies](https://scalewithsearch.com/for/towing-companies)
    - [Tree services and landscaping companies](https://scalewithsearch.com/for/tree-services-and-landscaping)
    - [Solar installers](https://scalewithsearch.com/for/solar-installation)
    - [General contractors](https://scalewithsearch.com/for/general-contractors-and-construction)
    - [Paving, concrete, and flooring contractors](https://scalewithsearch.com/for/paving)
  - Practices and professional services
    - [Bookkeeping and tax practices](https://scalewithsearch.com/for/bookkeeping-and-tax-practices)
    - [Dental practices](https://scalewithsearch.com/for/dental-practices)
    - [Family and criminal defense law firms](https://scalewithsearch.com/for/family-and-criminal-defense-law-firms)
    - [Med spas and aesthetics practices](https://scalewithsearch.com/for/med-spas-and-aesthetics)
    - [Personal injury law firms](https://scalewithsearch.com/for/personal-injury-law-firms)
    - [Veterinary clinics](https://scalewithsearch.com/for/veterinary-clinics)
    - [Gyms and fitness studios](https://scalewithsearch.com/for/fitness)
    - [Therapy and outpatient health practices](https://scalewithsearch.com/for/therapy-and-outpatient-health)
    - [Medical billing companies](https://scalewithsearch.com/for/medical-billing)
    - [Insurance agencies](https://scalewithsearch.com/for/insurance-agencies)
    - [Financial advisors](https://scalewithsearch.com/for/financial-advisors)
    - [Property management companies](https://scalewithsearch.com/for/property-management)
    - [Recruiting and staffing agencies](https://scalewithsearch.com/for/recruiting-and-staffing)
    - [Architects and interior designers](https://scalewithsearch.com/for/architects-and-interior-designers)
    - [Logistics and supply chain companies](https://scalewithsearch.com/for/logistics-and-supply-chain)
  - Agencies, MSPs, and manufacturing
    - [IT and managed service providers](https://scalewithsearch.com/for/it-and-managed-service-providers)
    - [Machine shops and precision manufacturers](https://scalewithsearch.com/for/machine-shops-and-precision-manufacturing)
    - [Marketing agencies and freelancers](https://scalewithsearch.com/for/marketing-agencies-and-freelancers)
    - [SEO agencies and consultants](https://scalewithsearch.com/for/seo-agencies-and-consultants)
    - [Small manufacturers and fabricators](https://scalewithsearch.com/for/small-manufacturers-and-fabricators)
  - Restaurants, shops, studios, and nonprofits
    - [Restaurants and hospitality businesses](https://scalewithsearch.com/for/restaurants-and-hospitality)
    - [Retail stores and ecommerce sellers](https://scalewithsearch.com/for/retail-and-ecommerce)
    - [Photographers, event planners, and travel agents](https://scalewithsearch.com/for/photographers)
    - [Churches and nonprofits](https://scalewithsearch.com/for/churches-and-nonprofits)
  - [All industries](https://scalewithsearch.com/for/)
- Learn
  - For your office
    - [Office job guides](https://scalewithsearch.com/guides/)
    - [Browser calculators](https://scalewithsearch.com/tools/)
  - Start here
    - [How it works](https://scalewithsearch.com/how-it-works)
    - [Free Starter Kit](https://scalewithsearch.com/kit/business-memory-starter-kit.zip)
    - [Synthetic specimen](https://scalewithsearch.com/specimen/working-session-specimen.zip)
  - Guides
    - [The Complete Guide to Business Memory for AI Agents](https://scalewithsearch.com/articles/business-memory-for-ai-agents-guide)
    - [The Complete Small-Business Guide to AI Agent Governance](https://scalewithsearch.com/articles/ai-agent-governance-guide-small-business)
    - [The Complete Guide to Leaving Vendor AI Memory](https://scalewithsearch.com/articles/leaving-vendor-ai-memory-guide)
  - Articles by cluster
    - [Business memory](https://scalewithsearch.com/articles/business-memory-for-ai-agents-guide)
    - [Agent governance](https://scalewithsearch.com/articles/ai-agent-governance-guide-small-business)
    - [Migration and ownership](https://scalewithsearch.com/articles/leaving-vendor-ai-memory-guide)
  - For machines
    - [llms.txt](https://scalewithsearch.com/llms.txt)
    - [llms-full.txt](https://scalewithsearch.com/llms-full.txt)
    - [Machine view](https://scalewithsearch.com/?view=machine)
- Company
  - Evidence
    - [Proof](https://scalewithsearch.com/proof)
  - Company
    - [About](https://scalewithsearch.com/about)

# Configure React, Vue, and Angular rendering so search engines index every page.

A software company builds its marketing site as a Vite and React single-page app. The product pages are well written. Google indexes them slowly, Bing shows thin snippets, and the Core Web Vitals report marks most pages as slow on mobile.

React, Vue, Angular, and their meta-frameworks (Next.js, Nuxt, and SvelteKit) power most modern web apps. Their defaults can hide content from crawlers. Client-side rendering delays content, client routing can hide URLs, and large bundles slow pages. This article compares the four rendering modes and gives the configuration for each framework. It then covers the metadata, structured data, sitemap, link, and performance work that every JavaScript site needs.

## Understand the problem with client-side rendering

A traditional HTML site sends the full content in the first response. Client-side rendering (CSR) sends a small HTML shell. JavaScript then fetches data and builds the page in the browser.

Googlebot renders JavaScript with a current version of Chromium, but CSR still carries four costs:

1. A render step after the crawl. Google indexes the HTML at once and renders JavaScript in a queue. Google said in 2019 that the median wait was about five seconds, with a long tail. If rendering fails, the content is missing.
2. Limited resources. Very heavy apps can render only in part.
3. More crawl work. Each page needs a fetch and a render, not a fetch alone.
4. Weaker support elsewhere. Bing renders JavaScript but can index less of it than Google. A Vercel analysis published in December 2024 found that major AI crawlers, including GPTBot and ClaudeBot, fetched JavaScript files but did not execute them.

The [Googlebot rendering guide](/articles/googlebot-javascript-rendering) shows how to test what Google receives.

## Compare the four rendering modes

| Mode | How it works | Search result | Cost | Use it for |
|---|---|---|---|---|
| Client-side rendering (CSR) | Server sends a shell; the browser builds the page | Content depends on rendering; LCP is often slow | Low server cost | Internal dashboards, logged-in apps, tools that need no search traffic |
| Server-side rendering (SSR) | Server builds full HTML for each request; JavaScript hydrates it | Crawlers get full HTML at once; faster LCP | Server work on every request | Content-heavy sites, ecommerce, news, marketing pages with live data |
| Static site generation (SSG) | Build step writes every page to static HTML | Fastest delivery; no JavaScript needed for content | A rebuild for each change | Blogs, documentation, marketing pages that change rarely |
| Incremental static regeneration (ISR) | Static pages that rebuild in the background after a set time | Static speed with fresh data | More complex cache logic | Product pages, large content sites, frequently updated articles |

Do not use CSR for public content, ecommerce, blogs, or marketing sites. SSR is available in Next.js (React), Nuxt (Vue), Angular's SSR package, and SvelteKit. SSG is available in Next.js, Nuxt, Gatsby, SvelteKit, and Astro. ISR-style regeneration is available in Next.js and Nuxt. The [server-side rendering guide](/articles/server-side-rendering-seo) compares the trade-offs in more depth.

## Configure each framework

### React

A React app built with Create React App or plain Vite renders on the client. The React team deprecated Create React App in February 2025. For SEO pages, move to Next.js, the most widely used React framework with SSR and SSG.

In the Next.js Pages Router, choose the mode per page:

- `getStaticProps` for SSG: articles and product pages.
- `getStaticProps` with `revalidate` for ISR: content that changes each hour or each day.
- `getServerSideProps` for SSR: pages that need request data.

```javascript
// SSG with ISR
export async function getStaticProps() {
  const data = await fetchData();
  return {
    props: { data },
    revalidate: 3600, // Rebuild at most once each hour
  };
}

// SSR
export async function getServerSideProps(context) {
  const data = await fetchUserData(context.req);
  return { props: { data } };
}
```

In the App Router, Server Components render on the server by default. Export `revalidate` from a route for ISR, and use `generateStaticParams` to prebuild dynamic routes.

Four further steps help:

- Use `next/image` for resized, modern-format images.
- Load third-party scripts with `next/script` and `strategy="lazyOnload"`.
- Split large components with dynamic imports.
- Generate the sitemap with `next-sitemap`, or with an `app/sitemap.js` file in the App Router.

Use this decision rule for Next.js routes:

- Static pages such as About and landing pages: SSG.
- Articles and product pages: SSG with ISR.
- Search results and pages that depend on the request: SSR.
- Interactive tools and calculators with no search value: CSR is acceptable.

### Vue

A Vue app built with Vue CLI or Vite renders on the client. Move to Nuxt, Vue's equivalent of Next.js.

Nuxt 3 and later render on the server by default (`ssr: true`). Set the mode for each route group with `routeRules`:

```javascript
// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },           // SSG for the homepage
    '/blog/**': { swr: 3600 },          // Cached, revalidated each hour
    '/dashboard/**': { ssr: false },    // Client-only, no search value
  },
})
```

To generate a fully static site, run `npx nuxi generate`. Older guides show `target: 'static'` in the config. That option belongs to Nuxt 2.

Four further steps help:

- Use `NuxtImg` and `NuxtPicture` from Nuxt Image for optimized images.
- Add the `@nuxtjs/sitemap` and `@nuxtjs/robots` modules.
- Set metadata with the `useSeoMeta` or `useHead` composables.
- Load heavy components on demand with `defineAsyncComponent`.

### Angular

An Angular app is a client-rendered single-page app by default. Since Angular 17 (November 2023), server rendering and prerendering are part of the Angular CLI:

```bash
ng add @angular/ssr
```

Older projects used Angular Universal with `ng add @nguniversal/express-engine` and the `@nguniversal/builders:prerender` builder. On current versions, turn on prerendering in the build options of `angular.json`. List static routes there, or let the builder discover them.

Four further steps help:

- Add `provideClientHydration()` so the client reuses the server HTML and cached HTTP responses. On older versions, the `TransferState` API did this job by hand.
- Lazy-load feature routes.
- Use the `NgOptimizedImage` directive for images.
- Set metadata with the `Meta` and `Title` services from `@angular/platform-browser`.

## Make URLs, metadata, and links crawlable

### Use real URLs

Use `example.com/products`, not `example.com/#/products`. Google does not treat hash fragments as separate pages. Modern routers use the HTML5 History API (`pushState`) by default. Confirm that yours does.

Configure the server to answer every route. A direct request to `example.com/products` must return the rendered page, not a 404 or an empty shell.

### Render metadata on the server

Metadata added late by JavaScript can be missed. Render the title, description, canonical, and Open Graph tags on the server:

- Next.js: `generateMetadata` in the App Router, or `next/head` in the Pages Router.
- Nuxt: `useSeoMeta` or `useHead`.
- Angular: the `Meta` and `Title` services, with SSR turned on.

```javascript
import Head from 'next/head';

export default function Page({ data }) {
  return (
    <>
      <Head>
        <title>{data.title}</title>
        <meta name="description" content={data.description} />
        <meta property="og:title" content={data.title} />
      </Head>
      <main>{data.content}</main>
    </>
  );
}
```

### Render structured data on the server

Put JSON-LD in a script element with `type="application/ld+json"`, rendered on the server. In React, set the content with `dangerouslySetInnerHTML`. Text children can be escaped, which breaks the JSON:

```javascript
export default function Product({ product }) {
  const schema = {
    "@context": "https://schema.org",
    "@type": "Product",
    "name": product.name,
    "description": product.description,
    "image": product.image,
    "offers": {
      "@type": "Offer",
      "price": product.price,
      "priceCurrency": "USD"
    }
  };

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
      />
      <div>{product.name}</div>
    </>
  );
}
```

The [JSON-LD guide for developers](/articles/structured-data-jsonld-developers) covers other types.

### Generate sitemaps in code

A JavaScript site must generate its sitemap in code, because SSR and ISR URLs are not all known at build time. At build time, use `next-sitemap` for Next.js or `@nuxtjs/sitemap` for Nuxt. Angular has no standard package, so write a build script. For SSR and ISR sites, serve the sitemap from a route that reads every URL from the data source.

### Use real links

Internal links must be `<a href>` elements, not click handlers. The framework link components render correctly:

- Next.js: `<Link href="/page">` renders an `<a>`.
- Nuxt: `<NuxtLink to="/page">` renders an `<a>`.
- Angular: `<a routerLink="/page">` is an `<a>`.

Check the rendered HTML to confirm that crawlers can follow each link.

### Check Google's view

Use the URL Inspection tool in Search Console to test a live URL. Compare the rendered HTML with what you see in DevTools. Also check the page resources and JavaScript console messages it reports. Track the count of indexed pages in the `Page indexing` report. Slow growth points to a rendering problem.

## Keep bundles small

JavaScript frameworks ship large bundles that hurt Core Web Vitals. Four methods reduce the load. The [Core Web Vitals engineering guide](/articles/core-web-vitals-engineering) covers measurement.

### Split the code

Next.js splits code by page automatically. Load heavy components on demand:

```javascript
import dynamic from 'next/dynamic';
const HeavyComponent = dynamic(() => import('./HeavyComponent'));
```

In Vue and Nuxt:

```javascript
const HeavyComponent = defineAsyncComponent(() => import('./HeavyComponent.vue'));
```

In Angular, lazy-load a route:

```typescript
const routes: Routes = [
  {
    path: 'feature',
    loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule)
  }
];
```

### Use the framework image components

Images are often the heaviest files on a page. `next/image`, `NuxtImg`, and `NgOptimizedImage` resize images, serve modern formats, and lazy-load images below the fold.

### Defer third-party scripts

Analytics, ads, and chat widgets block the main thread. Load them after the main content:

```javascript
import Script from 'next/script';

<Script src="https://analytics.example.com/script.js" strategy="lazyOnload" />
```

Outside Next.js, use `defer` or `async`, and load scripts that are not critical after the `load` event.

### Reduce hydration work

Hydration attaches JavaScript to server-rendered HTML. Slow hydration delays the first response to input and hurts Interaction to Next Paint (INP). INP replaced First Input Delay as a Core Web Vital in March 2024. Three approaches help:

- Partial hydration: Astro hydrates only interactive "islands." Qwik resumes the page state instead of a full hydration.
- Progressive hydration: hydrate components as they enter the viewport, not all at page load.
- React Server Components in the Next.js App Router: components with no interactivity send no JavaScript to the browser.

## Choose a framework and test each template

Next.js and Nuxt give the strongest SEO defaults, with SSR, SSG, and ISR in few lines of configuration. Angular's built-in SSR works well since version 17, with a little more setup.

If search traffic matters, move a Create React App site to a framework with server rendering. Googlebot renders most client-side apps, but SSR or SSG removes the dependency on rendering and helps every other crawler too.

To test a site, run URL Inspection on each page template. Look for missing content, JavaScript errors, and missing meta tags or structured data in the rendered HTML. The [JavaScript SEO guide](/articles/javascript-seo-guide) lists the remaining checks for links, lazy loading, and pagination.

----

```text
                  .|########||.                                       .|########||.                                       .|########||.
               |##||.      .||##|.                                 |##||.      .||##|.                                 |##||.      .||##|.
             |#|.              .|#|.                             |#|.              .|#|.                             |#|.              .|#|.
           |#|                    |#|                          |#|                    |#|                          |#|                    |#|
         .#|                        |#.                      .#|                        |#.                      .#|                        |#.
        .#.                          .#|                    .#.                          .#|                    .#.                          .#|
       |#.                            .#|                  |#.                            .#|                  |#.                            .#|
      |#             ......             #|                |#             ......             #|                |#             ......             #|
     .#           ||#########|           #|              .#           ||#########|           #|              .#           ||#########|           #|
    .#.         |######||######|.        .#.            .#.         |######||######|.        .#.            .#.         |######||######|.        .#.
    #.        .##|###|##|#|######|        .#            #.        .##|###|##|#|######|        .#            #.        .##|###|##|#|######|        .#
   ||        |##|#||||||||||||#||#|        ||          ||        |##|#||||||||||||#||#|        ||          ||        |##|#||||||||||||#||#|        ||
   #        |#||||||||||||||||||||#|        #.         #        |#||||||||||||||||||||#|        #.         #        |#||||||||||||||||||||#|        #.
  ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||
  #       .#||||||||||||||||||||||||#|       #        #       .#||||||||||||||||||||||||#|       #        #       .#||||||||||||||||||||||||#|       #
 ||   ....|||#||||||##|#|||#|#||##||||....|. ||      ||   ....|||#||||||##|#|||#|#||##||||....|. ||      ||   ....|||#||||||##|#|||#|#||##||||....|. ||
 #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#      #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#      #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#
 #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.     #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.     #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.
.|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||    .|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||    .|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||
||   |....  #. ....|#.      |. ...|. ....||   ||    ||   |....  #. ....|#.      |. ...|. ....||   ||    ||   |....  #. ....|#.      |. ...|. ....||   ||
#.  .||||||##||||||##||####|||||||#||||||#|   .#    #.  .||||||##||||||##||####|||||||#||||||#|   .#    #.  .||||||##||||||##||####|||||||#||||||#|   .#
#    .||####|###########################|.     #    #    .||####|###########################|.     #    #    .||####|###########################|.     #
#      .#||||||.#.|| # |. ..# #| #|||||#|      #    #      .#||||||.#.|| # |. ..# #| #|||||#|      #    #      .#||||||.#.|| # |. ..# #| #|||||#|      #
#      .#|||||| ..  |# ## |#| ...#|#|||#|      #    #      .#|||||| ..  |# ## |#| ...#|#|||#|      #    #      .#|||||| ..  |# ## |#| ...#|#|||#|      #
#      .#|||#|# .# .#| #| ##|.#..#|||||#|      #    #      .#|||#|# .# .#| #| ##|.#..#|||||#|      #    #      .#|||#|# .# .#| #| ##|.#..#|||||#|      #
#      .#||||||############|######|||||#|      #    #      .#||||||############|######|||||#|      #    #      .#||||||############|######|||||#|      #
#   |...||#||||||#||||#|#||||||#|||||#||| |.|  #    #   |...||#||||||#||||#|#||||||#|||||#||| |.|  #    #   |...||#||||||#||||#|#||||||#|||||#||| |.|  #
#. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#    #. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#    #. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#
|| |  ...||  ...##| |  #| .|. |. #####  .. .| ||    || |  ...||  ...##| |  #| .|. |. #####  .. .| ||    || |  ...||  ...##| |  #| .|. |. #####  .. .| ||
|| ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||    || ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||    || ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||
.# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.    .# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.    .# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.
 #.|||||||#############################| ||| .#      #.|||||||#############################| ||| .#      #.|||||||#############################| ||| .#
 ||       ##||#||#||||||#||#||#||#||##.      ||      ||       ##||#||#||||||#||#||#||#||##.      ||      ||       ##||#||#||||||#||#||#||#||##.      ||
  #       .#|||||||||#||#|||||||||||#|       #        #       .#|||||||||#||#|||||||||||#|       #        #       .#|||||||||#||#|||||||||||#|       #
  ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||
  .#        |#||||||||||||||||||||#|        #.        .#        |#||||||||||||||||||||#|        #.        .#        |#||||||||||||||||||||#|        #.
   ||        |#||||||||||||||||||#|        ||          ||        |#||||||||||||||||||#|        ||          ||        |#||||||||||||||||||#|        ||
    #.        .######|#|#########|        .#            #.        .######|#|#########|        .#            #.        .######|#|#########|        .#
    .#.         |#####||||#####|         .#.            .#.         |#####||||#####|         .#.            .#.         |#####||||#####|         .#.
     |#           ||########||           #.              |#           ||########||           #.              |#           ||########||           #.
      |#             ......             #|                |#             ......             #|                |#             ......             #|
       |#.                            .#|                  |#.                            .#|                  |#.                            .#|
        |#.                          .#.                    |#.                          .#.                    |#.                          .#.
         .#|                        |#.                      .#|                        |#.                      .#|                        |#.
           |#|                    |#|                          |#|                    |#|                          |#|                    |#|
            .|#|.              .|#|.                            .|#|.              .|#|.                            .|#|.              .|#|.
               |##||.      .||##|                                  |##||.      .||##|                                  |##||.      .||##|
                 .||########||.                                      .||########||.                                      .||########||.

Scale With Search  2026  [scalewithsearch.com](https://scalewithsearch.com)
```
