Is there a configuration in Github Pages that allows you to redirect everything to index.html for a Single Page App?

I’m trying to post my SPA app that works fine locally but when I push it to Github Pages, the interior pages don’t register if you navigate to them directly.

For example http://USER.github.io/PROJECT_NAME/ works but http://USER.github.io/PROJECT_NAME/about doesn’t because theres no redirect or rewrite. The index.html is located at the root of the project.

11 thoughts on “Is there a configuration in Github Pages that allows you to redirect everything to index.html for a Single Page App?”

  1. Add this code to your index.html and 404.html files:

      // if it's on index.html
      if (window.sessionStorage.path) {
      let path = window.sessionStorage.path; // gets the path saved on sessionStorage
      window.history.pushState(null, null, path); // push it on url
      window.sessionStorage.removeItem('path'); // removes from session
    
    } else { // if it's on 404.html (path doens't exist)
      let path = window.location.pathname; // get the path url
      window.sessionStorage.path = path; // saves on sessionStorage
      window.location.href = '/'; // go to index
    }
    
    Reply
  2. Github pages allows you to create a 404.html page that will be shown each time … there is a 404 error. If http://USER.github.io/PROJECT_NAME/about doesn’t exists, it will show your 404.html content with the “not found” url as window.location.

    So, this page can contain a script that redirect to a hashbang style route.
    eg : react router, even using clean urls (browserHistory) can understand a route like PROJECT_NAME/#/about and will automatically push to PROJECT_NAME/about.

    That’s ugly !

    Reply
  3. If you are creating react app and you want to use Browser router in your gh pages the solution is to create 404.html file in your root directory and copy all the content in index.html to 404.html after you have build your react-app.

    When a user try accessing your page e.g https://successtar.github.io/teamwork/ GitHub will serve your index.html page while if a user try accessing https://successtar.github.io/teamwork/foo, since it does not exist, GitHub will serve the 404.html page which has same content as the index.html and with this you get your react app working as expected.

    Here is the source code for the example https://github.com/successtar/teamwork/tree/gh-pages

    UPDATE

    You can automate the process for every time you run npm run build to auto generate the 404.html file.

    First Step: install shx for cross platform commands as follow npm install shx --save-dev

    Second Step: Go to your package.json in the scripts block replace "build": "react-scripts build" with "build": "react-scripts build && shx cp build/index.html build/404.html"

    That is all.

    Whenever you run npm run build the 404.html file will be auto generated.

    Reply
  4. I just built this tiny package (for bower / npm) to solves that exact problem so I thought I’d share it here as an answer to your question,

    https://github.com/websemantics/gh-pages-spa

    If you include the package in your 404.html and index.html pages, it will redirect all the traffic to Index.html,

    It supports Project and User/Org Pages type repositories, handles QueryStrings and comes with a working example,

    Reply
  5. Created two files 404.md and 404.html

    1. 404.md should have below content:
    ---
    permalink: /404.html
    ---
    
    1. 404.html should have the same content as index.html

    this solved my issue for an Angular app.

    Reply
  6. Well, there is an easy way out.
    Create a file in the root directory of your github pages repository named 404.html.
    Contents of that file should be:

    <!DOCTYPE html>
    <html lang="en" id="htmlbody">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Loading...</title>
    </head>
    <body>
        <script>
            var doc = document.getElementById('htmlbody');
            xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                if (this.readyState == 4) {
                    if (this.status == 200) {
                        doc.innerHTML = this.responseText;
                        doc.removeAttribute("id");
                    }
                    if (this.status == 404) doc.innerHTML = "Page not found.";
                }
            }
            xhttp.open("GET", "index.html", true);
            xhttp.send();
        </script>
    </body>
    </html>
    

    Basically, that script just uses Javascript to perform an XHR on index.html and make the content the document.

    I was reluctant to use document.body because I’m thinking of updating the whole document, but if it doesn’t work, change doc variable to document.body.

    Not sure if this works, so I’ll really appreciate feedback.

    Remember to use the same domain for the index.html else CORS will kick in.

    Reply

Leave a Comment