How To Achieve SEO For React SPA

- 1 answer

The SEO topic has been debated to an extraordinary length and React SPAs are very common. Yet searching SO yields no clear coding guidance complimented by a simple to follow sequence of specific practical steps required to deploy a React SPA and achieve SEO.

The existing Q/A are either not very helpful or use links. This question is not related to React, the detailed answer considers deprecated AJAX technology. Although its upvote and viewing counts show the importance of this topic.



Website Deployment

The deployment is based on Crisp React boilerplate (I'm the author) and uses Cloudflare Pages.

This particular boilerplate has been chosen due to its features, like the variety of deployments, both Jamstack and full stack. It makes it easy to alter the deployment described below and switch from Jamstack to full stack if need be. The ready-to-replace Structured Data placeholders provided by the boilerplate could help with SEO as well.

The steps:

  • Clone Crisp React repository:

    git clone
    cd crisp-react
  • Simplify the configuration by replacing the code fragment with the following code:

    /****************** Start SPA Configuration ******************/
      var SPAs = [
        new SPA({
          name: "index",
          entryPoint: "./src/entrypoints/first.tsx",
          ssr: false,
          redirect: true
      SPAs.appTitle = "Crisp React";
    /****************** End SPA Configuration ******************/

    Additionally replace "Crisp React" with your SPA title. It's important for SEO to have a unique and sensible title.

  • Review the client codebase to ensure each page sets the <title> HTML element and the canonical <meta> tag to the values that are meaningful for your website. This can be done by searching all the client/src/components/*.tsx files for the <Helmet> pattern and reviewing the relevant code:

      <link rel="canonical" href={getCanonical()} />
    // Simplified code
    export const getCanonical = (pagePath?: string): string|undefined => {
      return !!pagePath? (window.location.origin + pagePath) : window.location.href;
    // Simplified code
    export const getTitle = (pageTitle?: string): string => {
      return !!pageTitle? `${SPAs.appTitle} - ${pageTitle}` : SPAs.appTitle;
  • Commit the changes:

    git add client
    git commit -m "Changed configuration"
  • Create a new GitHub repository by visiting

  • Point the cloned repository to the newly created one and push it there:

    git remote set-url origin
    git push
  • Deploy to Cloudflare Pages by logging into the Cloudflare dashboard and creating a Cloudflare Pages project.

    This step will take several minutes spent mostly on waiting. It should take around a minute to copy the data provided below and paste it into the single configuration screen presented by Pages.

    Use Menu > Pages > Create a project. You will be asked to authorise read-only access to your GitHub repositories with an option to narrow the access to specific repositories. Select the repository which you pushed to GitHub at the previous step and on the "Set up builds and deployments" screen, provide the following information:

    Configuration optionValue
    Production branchmaster
    Build commandyarn build:jamstack
    Build output directoryclient/dist

    Add the following environment variable:

    Environment variableValue

    Optionally, you can customise the "Project name" field. It defaults to the GitHub repository name and is used to create a subdomain e.g. <project-name>

    After completing the configuration, click on the "Save and Deploy" button. When the deployment pipeline finishes, point a browser to https://<project-name> to check the website is online.

    Finally use the 'Custom domains' tab to map the deployed website to a domain you own.

Requesting Google to Index the Website

Add some original content to the webpages to avoid duplicate content.

You can choose either passive approach and simply wait until Googlebot discovers your website or proactively ask Google to index it. If you choose the latter, use Google Search Console (GSC):

  • Add your custom domain to GSC using the "+ Add Property" menu.
  • Click on the "URL Inspection" menu to activate the URL Inspection Tool and type the path to the page you would like to index. The response will state that "URL is not on Google" telling you the page hasn't been indexed yet.
  • Click on the "TEST LIVE URL" button to get confirmation the page can be indexed. Optionally review the screenshot of the page rendered by GSC.
  • Request indexing for the page by clicking on the "REQUEST INDEXING" link. The response should say your request has been added to the priority crawl queue.

The last 3 steps will have to be repeated for each SPA page.

The deployed skeleton website lacks commonly used, though not strictly necessary for SEO files, such as sitemap.xml and robots.txt. Sitemap is more important for the passive approach. The robots.txt file is not needed unless you want to put some crawling restrictions in place.

The website doesn't use all Crisp React features e.g. the ability to split a React app into multiple SPAs and selectively prerender the landing/index page of each SPA for better performance. If you need this functionality along with SEO, consider switching to full stack build or using a Cloudflare Worker as described in this article.