How to Do SEO for a JavaScript Website (React, Next.js, Vue)

On this page

JavaScript frameworks can rank. Whether they do depends in large part on where each page’s content gets rendered, and your framework’s default is the first place to look. Google renders JavaScript pages and, per its JavaScript SEO basics, also uses the rendered HTML to index them. One risk is a render that comes back incomplete, for example from a blocked script, an API call that fails or content that waits for a click. Content in the server’s HTML response doesn’t depend on any of that. So the practical questions for a React, Next.js or Vue site are what your framework renders on the server by default, which content escapes that, and how you check what Google received.

Start from your framework’s default

Each stack starts from a different place, and the default decides how much of your content is in the first response.

  • Next.js (App Router). The Next.js documentation on Server and Client Components says that by default, layouts and pages are Server Components, which lets you fetch data and render UI on the server. Content you fetch and render there is in the HTML from the start.
  • Vue. Vue’s server-side rendering guide says that by default, Vue components produce and manipulate DOM in the browser. It lists better SEO as an advantage of SSR, and says that if content is fetched asynchronously on pages where SEO matters, SSR might be necessary. A plain Vue app is client-rendered until you add SSR or static generation.
  • Plain React. A React app built as a client-side single-page app renders in the browser. The React team announced on February 14, 2025 that it was deprecating Create React App for new apps and encouraging existing apps built with it to migrate to a framework or a build tool. If your site still runs on it, the rendering decision is part of that migration.

For any other framework, look up the same thing in its current documentation: which routes render on the server by default, and how you switch a route to server rendering or static generation.

Where content escapes the server HTML

Even on a server-rendering framework, content can end up rendered only in the browser. The patterns to look for:

  • Data fetched after the page loads. Reviews, prices, listings or related items requested by the browser once the page is up aren’t in the server response. Move fetches for content that has to rank to the server side of your framework.
  • Components that skip server rendering. A component that waits for browser-only data, or is set up to render only in the browser, leaves its content out of the server response. Keep the content that needs to rank where the server renders it, and put interactivity around it.
  • Content that waits for an interaction. A tab or “load more” that fetches its content on click leaves that content out of what Google renders.

A useful rule for every route that needs to rank: the headline, the main copy, the links and the structured data should all be in the server’s response.

Google’s link best practices say that Google can generally crawl a link only if it is an <a> element with an href attribute, and that it can’t reliably extract URLs from elements that act as links through script events. Navigation that changes state on a click handler, with no href, may never be followed. Framework link components render real anchors; use them, or plain <a href> elements, for every route you want crawled.

Keep hydration consistent

Hydration is the step where the browser attaches interactivity to the HTML the server sent. When the client renders something different from the server HTML, users can see content shift or change, and the page Google renders may differ from the response you tested. Keep server and client output consistent, and treat hydration warnings in your console as defects on pages that need to rank.

Check what Google received

Two checks per important template:

  1. The server response. Open view-source or fetch the URL from the command line and search the raw HTML for your main heading and copy. Missing there means it arrives only through client-side rendering.
  2. Google’s render. Run a live test in the URL Inspection tool and open the tested page to see the rendered HTML, the screenshot and any failed resources.

If content that should rank appears only in the second check, move it into the server response.

Rankings fell after moving to a JavaScript framework

Don’t start with rendering. A move to a new framework can bring new URLs, new templates and new redirects, and missing or broken redirects can cost rankings no matter how pages are rendered. Google’s site move guide builds a move with URL changes around redirecting old URLs to their new equivalents. Confirm that every old URL redirects to its new equivalent, then check rendering on the templates that lost traffic.

One shortcut to avoid: a separate prerendered version served only to bots. Google’s documentation titles that approach dynamic rendering as a workaround and recommends server-side rendering, static rendering or hydration instead. Fix rendering in the framework itself.

Frequently asked questions

Does using React or Vue hurt my SEO?

Not in itself. What matters is whether the content that needs to rank is in the server’s HTML response. Next.js renders layouts and pages on the server by default; a plain Vue or React single-page app renders in the browser unless you add server rendering or static generation.

How do I know if Googlebot can see my content?

Compare the page source with Google’s rendered page in a URL Inspection live test. Content that appears only in the rendered version depends on client-side JavaScript.

My rankings dropped after migrating to Next.js. Is it rendering?

Check redirects first. Missing or broken redirects from old URLs can cost rankings regardless of rendering. Once every old URL redirects correctly, compare the source and the rendered page on the templates that lost traffic.

Leave a comment

Your email address will not be published. Required fields are marked *