GitHub Pages are a great way to deploy a simple frontend website. And React is a great tool to build the said website. I am by no means a frontend master, but DevOps, deploying and building applications on all kinds of platforms is very much my forte. Recently I tried deploying a small React website with a few routes to GitHub Pages. And quickly ran into a problem.

The problem

As long as the routing is done in the browser, all is good. So if we visit the homepage on the root /, GitHub Pages correctly resolves our request to index.html and our React App gets rendered. So far, so good. Let’s say we have a link on this page pointing to /some-page. If we click it, the redirect will happen on client side, in the browser. This is handled by React (Router) and works just fine. So all good? Not really, if we try to refresh the site or visit the link /some-page directly, oh no, we get a 404. 😢

What happens? GitHub pages tries to find a document some-page, and since this does not exist, we get a 404 - Not Found. Usually, a static website hosting allows us to set up how to handle requests where the document was not found, like sending all requests to index.html. Unfortunately, that is not the case with GitHub pages.

The solutions

There are a couple of solutions to work around this limitation.

Hash routing

This is probably the cleanest solution, we can use hash routes. Those are handled by the frontend application by default. Therefore they will work just fine with GitHub Pages.

Redirect script

There is a rather complex redirect script that redirects requests from a 404 page back to our index.html. This has been described in other places in detail.

The hack

Time to adopt a hacker mindset and think about how we could work around this problem. GitHub allows us to set our custom 404.html page for the requests where a document was not found.

So, if we can’t send all requests to index.html, couldn’t we just make 404.html be the same as index.html? 🤔

Turns out, yes, yes we can!

So the proof of concept would something along these lines:

# Build the React website
npm run build

# Copy index.html to 404.html
cp ./build/index.html ./build/404.html

I deployed my React App using GitHub Actions, the full workflow can be found here. The source code of the full example application can be found in my GitHub at: github.com/bloomsei/example-react-router.

Of course, I deployed the app on GitHub Pages too: bloomsei.github.io/example-react-router/

Limitations of this approach

The GitHub server still returns a status code 404 for everything that is not in root /. I am no SEO expert, but crawlers probably don’t like that. So you should probably not use this approach if you want your pages indexed. Still, I find it useful for experimental things that I don’t care about being indexed, but want to have a nice URL anyway.