How I finally got my React app with Routing to work on GitHub pages, no 404 errors, no missing images.

GM Fuster
6 min readJan 4, 2021

I have been learning React and wanted to deploy my app to GitHub Pages. The first time I tried the routing was all messed up and the images were all gone. This is what finally got it working for me.

I’ll be talking about getting GitHub pages set up and the code changes needed to make the app work on GitHub pages.

1 — Install the GitHub pages package.

Go to the folder for your app in your terminal screen and install with:

npm install gh-pages — save-dev

2 — Modify your package.json

You will need to add a homepage attribute to your existing file as a top level one.:

“homepage”: “.”,

Many articles I read said to put your GitHub repo in the homepage attribute instead of just the dot, but then it will not run locally. If you prefer that you would write “https://{username}.github.io/{repo-name}” instead of “.”.

I prefer to just have the “.” here and use a .env file to switch between different environments (more in this later).

You also need to add this to your package.json, under the scripts section:

deploy”: “gh-pages -d build”

If you want your deploy to also build first, you need to add this too:

“predeploy”: “npm run build”

I prefer to just run the build myself and then the deploy manually so I don’t have the predeploy one on my package.json.

3 — .env file

Create a file .env and put it in the root directory of your app. This is what will allow you to have the homepage set to “.” in the package.json file.

You can use this file to set environment variables that you can use in your app’s code. You can name the variables anything you want, but they must start with REACT_APP. You can use this to set the path that your code should be using:

Now wherever you need to use paths in your code (including React routing), you can do this:

const path = process.env.REACT_APP_FOR_PATH;

and use that path in the code, like this:

path = {process.env.REACT_APP_FOR_PATH + “/CanvasTrace”}

I also have a variable there for my images because depending on the type of routing you use (coming later), you can share the same variable for routing and images or not.

<img src= {pathPic +”/images/YourImage.png”

Instead of changing the homepage attribute in package.json I prefer to change the variable in the .env file.

To run locally, your .env file should be like the one shown bellow. (no “”, just nothing):

REACT_APP_FOR_PATH =

4- Running

Just as an additional note, remember to change the .env file before you run locally (npm start) to have the variable set to nothing. If you are using Routing with BrowserRouter you need to set the variable to your GitHub repo before you build and deploy (npm run build, npm run deploy).

5 — Where is your site on GitHub pages?

With the above set up your page is going to be deployed to the gh-pages branch on your repository. In GitHub, make sure to check your settings and have your repo set up for GitHub pages.

scroll down almost to the end:

MAKE SURE you choose the gh-pages branch and not master. I did that by mistake and created a huge mess for myself. The files that you will push with the deploy script are very different from the code files and if you mix those two branches is going to be a mess.

Now you can access your page at https://gmfuster.github.io/Bonico/ (of course replace with your own user and repository :-) )

6 — The images

Make sure you provide the path for your images so GitHub knows where to look for them. This is so you can run both locally and on GitHub. In my case I have this for GitHub:

REACT_APP_FOR_PATH_FOR_PICS = /Bonico

And this for local:

REACT_APP_FOR_PATH_FOR_PICS =

7 — The 404 issues with Routing.

This has been tricky to say the least :-).

The common way to handle routing in React is with the BrowserRouter but for GitHub Pages we will get 404 errors when reloading a page that is not the index one. Or with just entering the link directly to something other than the main index page. In addition, legacy browsers don’t support it.

These are some examples of what the URLs look like with BrowserRouter:

http://localhost:3000/

http://localhost:3000/CanvasTrace

On BrowserRouter, if you check the DevTools on your browser and go to the network tab, you will see this:

Another way to do routing is with the HashRouter. React recommends using the BrowserRouter but that is not going to work with GitHub pages unless you always go in from the main page (index). With HashRouter, a hash symbol is added to the URL, which makes the server ignore what comes after that. The URLs will look something like this now:

http://localhost:3000/#/

http://localhost:3000/#/CanvasTrace

If you check the network tab now, you will see this. Notice it still goes to localhost and not CanvasTrace:

The routing will be done on the client side now, not the server side, which would not find the requested URL and therefore throw the 404 error.

To use the HashRoute I have this:

import {Route, HashRouter as Router, Switch} from ‘react-router-dom’;

<Router baseline=”/”>

Everything else is the same as for BrowserRouter.

It is still a good idea to customize your own 404.html file. You just need to add it to your gh-pages branch and display whatever message you want and a link back to your URL.

One more note on the routing. When you are using HashRoute you don’t need to change the REACT_APP_FOR_PATH to change between building locally and building for GitHub pages. I just have it there anyway and have the code using the path on the links in case I switch back later.

8 — Routing errors with Bootstrap NavBar

I was also having issues with my <Nav.Link>s because those were not using the routing with the hash symbol. What I did was replace those inside the nav with the React <Link> and give them my own styling.

import {Link as ReactLink} from ‘react-router-dom’;

<ReactLink style={reactLinkSt} to= {path + “/”} >Home</ReactLink>

When you are changing things, make sure to remember to use to instead of href. I did not and it took my a while to realize that was the reason it was not working.

If you still have errors with the navbar, include it inside the router. I have the NavBar component before the <Switch> inside the <HasRouter>.

And that should be it! I really hope so because this took me a while.

Thank you for checking this out! I hope it helps.

--

--

GM Fuster

Software Dev. Always learning. Some notes here. I like to use this one for the examples :https://dotnetfiddle.net/