Search code examples
http-status-code-404markdowngithub-pagesrelative-pathgithub-flavored-markdown

Github-pages relative links not working when custom domain is used


I'm using Github-pages with no Jekyll, just bare markdown .md files.

To link from that .md to some folder inside my repo I'm using relative links.

Why relative links? I was using absolute links like https://github.com/USER_NAME/REPO_NAME/blob/master/FOLDER_NAME but then I changed my repo name and every link stopped to work.

This is why I moved to relative links but then when I checked how the page works under custom domain -> every link stopped to work.

By "stopped" to work I mean: now when I go to www.CUSTOM_DOMAIN.com/REPO_NAME/FOLDER_NAME I'm getting 404.



EDIT 1:
When I was trying to edit this question for this comment I realized the problem is different: - links to files works fine - but links to folders doesn't work, i.e. REPO_NAME is not added to URI, there should be:

www.CUSTOM_DOMAIN.com/REPO_NAME/FOLDER_NAME

while actually there is:

www.CUSTOM_DOMAIN.com/FOLDER_NAME.

So my repo looks like this:

REPO_NAME/
├── README.md
├── FOLDER_NAME/
│   ├── FOLDERFILE.md

So the link in my README.md is (NOK):

[some string for folder](/FOLDER_NAME)
(which is unwrapped by github-pages-engine to)
www.CUSTOM_DOMAIN.com/FOLDER_NAME

It works fine when I link to a file, like this (OK):

[some string for file](/FOLDER_NAME/FOLDERFILE.md)
(which is unwrapped by github-pages-engine to)
www.CUSTOM_DOMAIN.com/REPO_NAME/FOLDER_NAME.html



EDIT 2:
the page I'm trying to fix is NOT the organization/user page so it should have REPO_NAME in the path.



EDIT 3:
I changed links to remove leading slash and they still does not work. Now link in my README.md is (NOK):

[some string for folder](FOLDER_NAME/)
(which is unwrapped by github-pages-engine to)
www.CUSTOM_DOMAIN.com/REPO_NAME/FOLDER_NAME

or (also NOK):

[some string for folder](./FOLDER_NAME/)
(which is unwrapped by github-pages-engine to)
www.CUSTOM_DOMAIN.com/REPO_NAME/FOLDER_NAME

Solution

  • You have two problems:

    1. You are not using relative URLs.
    2. You are not accounting for the server root being different with a custom domain.

    Relative URLs

    A relative URL is a path which is relative to the current location. However, a URL which starts with a slash is not relative to the current location. The opening slash indicates a path from the server root. In other words, to "normalize" the URL, simply prepend the domain.

    Therefore, for a link to be relative to the current location, it cannot begin with a slash. Using your example structure, any links in the FOLDERFILE.md file would look like this:

    [REPO_NAME](../)          <= step back one directory
    [README.md](../README.md) <= step back one directory
    [FOLDER_NAME](./)         <= the current directory
    

    And any links in the README.md file would look like this"

    [REPO_NAME](./)
    [FOLDER_NAME](FOLDER_NAME/)
    [FOLDERFILE.md](FOLDER_NAME/FOLDERFILE.md)
    

    If it helps, you could start all URLs with the current directory (./). While not necessary, some people find it more readable. In that case, the README.md file would look like this"

    [REPO_NAME](./)
    [FOLDER_NAME](./FOLDER_NAME/)
    [FOLDERFILE.md](./FOLDER_NAME/FOLDERFILE.md)
    

    Server Root

    It is important to understand the difference between the server root and your site's root. When they are the same, absolute links will work fine. However, when they are different, only true relative links will work across the two.

    When you set up GitHub pages using the GitHub provided domain, your site is hosted at https://USERNAME.github.io/REPO_NAME. In that case, the server root is at USERNAME.github.io/ and that's where / points to. However, your site's root is in the subdirectory /REPO_NAME. Therefore for absolute URLs to work, the must include /REPO_NAME/ in them.

    However, when you set up a custom domain, then the server root and the site's root are at the same location: https://example.com/. There is no REPO_NAME subdirectory. The contents of REPO_NAME are at /.

    To illustrate, the following URLs point to the same location depending on whether you are using a GitHub domain or a custom domain.

    GitHub Domain                        | Custom Domain
    ------------------------------------ | --------------------------
    /REPO_NAME/                          | /
    /REPO_NAME/README.md                 | /README.md
    /REPO_NAME/FOLDER_NAME/              | /FOLDER_NAME/
    /REPO_NAME/FOLDER_NAME/FOLDERFILE.md | /FOLDER_NAME/FOLDERFILE.md
    

    And that difference is why you need to use true relative URLS -- URLs which do not start with a /.