Context

When you use the BrowserRouter component from the react-router-dom library, you will be able to set up routes in your React JS application that can be visited from the frontend.

It works on your local development environment. But it stops working after deploying it to GitHub pages! You will see a 404 error whenever you try to visit any of the routes.

One of the "fix" that I used to do was to use a HashRouter to solve this issue. This is because the original path remains the same. We just use anchors or "hashes" to switch between page content.

Why

Let's first look at why BrowserRouter is not friendly with GitHub Pages. GitHub Pages has this thing where when we access an URL other than the root URL, it looks for a physical folder there.

So, when we visit /country/india for example, it will look for /country/india/index.html. This way of looking for files is not always feasible for us in production. Perhaps SSG would help fix this issue but even there we are limited because we need to know in advance about all the countries in the world so that we can generate html files for them.

Fix

So, how do we fix it now?

There is this feature in GitHub Pages where if we put a file called "404.html", at the root of your static file deployment, it will use that as the 404 page instead of the one that GitHub shows by default. This is simply an out of the box GitHub feature that is provided to the user to show their own custom 404 page.

We are going to take advantage of this custom 404 page 😈

We are going to simply clone our index.html file when we run the GitHub pipeline for Pages. We will rename the cloned file to 404.html. After this, all the 404 requests will go to index.html and it will serve the required content as expected.

Sample code

Here is a sample GitHub Actions YML file to get this done with a project scaffolded using Vite JS. I have added a comment in the line that does our fix.

name: gh-pages build

on:
    push:
        branches: [master]

jobs:
    build:
        permissions:
            pages: write
            id-token: write
        environment:
            name: github-pages
            url: ${{ steps.deployment.outputs.page_url }}
        runs-on: ubuntu-latest
        steps:
            - name: Checkout ⏬
              uses: actions/checkout@v2

            - name: Install 🔧
              run: npm install

            - name: Build 🔥
              run: CI='' npm run build && cp ./dist/index.html ./dist/404.html # THE FIX

            - name: Setup Pages ⚙
              uses: actions/configure-pages@v3

            - name: Upload artifact 🔼
              uses: actions/upload-pages-artifact@v3
              with:
                  path: "./dist"

            - name: Deploy to GitHub Pages 🚀
              id: deployment
              uses: actions/deploy-pages@v4

Follow me for more tips on React JS, Java, & Docker