GitHub Pages

A basic project on how to create and deploy GitHub pages

GitHub Pages

18 November 2024

sha

updated: 26-04-2025

Documenting work is very important. If we do not document our work, with the passage of time we forget the steps and process that helped us achieve our goal. Also, documentation helps showcase work, collaborate with others, and makes it easier for others to build upon our dreams after we leave. It also helps improve writing. GitHub pages is an easy to use service for this purpose.

GitHub pages is a static website deployed on GitHub. The pages are used for documentation (for everything related to open source projects on GitHub) and GitHub user profiles. In this project, we are going to learn how to create and deploy multi-repo GitHub pages under a GitHub organization, with comments functionality enabled using giscus. We will also learn how to setup GitHub actions and workflows for building and deploying the pages.

1. Setup GitHub Pages

If we already have html files and do not need a build, Github pages setup becomes very simple:

Every time we make a commit, behind the scene, a workflow is triggered that deploys the pages. To stop this auto behavior, we may optionally change the pages setting for the repo to Github Actions (means user will have to provide Github Actions for building and deploying the pages). After we have made all the commits, unless we have our own workflows and actions setup, we will need to change the setting back to main branch to trigger the github provided workflow.

If we want to create pages for any of the repos under our account or org, we will need to enable pages for the corresponding repo and set the pages source to the main branch (root or docs folder). This will auto trigger deploys on every commit in the repo. The pages will show up under {your account or org}.github.io/{repo_name}/path_to_html. For the repos other than the .github.io repo, we will need repo_name in the path to access assets like js and css.

See the example repo and the deployed pages.

In the following discussion, we learn how to setup GitHub pages that require a build.

1.1 Setup a GitHub organization

The purpose of creating an organization is to isolate all the repos we will need in this project. You will be the only member of the organization, there is no need to add other members for now.

1.2 Setup a GitHub pages repo

We now have the organization named gh-pages-project (or the organization name that you picked while creating the organization). we need a repo named [your organization name].github.io under this organization. This repo is required for deploying GitHub pages.

If all of the steps were successful, visit the site at https://[your organization name].github.io and you see your static website hosted on GitHub!

1.3 Add a theme

Our website layout is very basic so far. To improve it, we need to use a theme. Github Jekyll based supported themes make this step very simple. To use the theme, we need to create a new file at the root of our repo.

title: GitHub Pages
description: Bookmark for updates!
remote_theme: pages-themes/cayman
plugins:
- jekyll-remote-theme

Where cayman is the name of the theme we want to use. You may use any of the supported themes.

1.4 Create your first page

So far we have been using our README.md file for our homepage. Let us create our first page with some content in it.

---
layout: default
title: GitHub Pages
description: Create and deploy GitHub pages
permalink: /
---
This project is about GitHub pages.

Wait for a minute or so as GitHub rebuilds your site, visit the site (https://[your organization name].github.io) and refresh your browser, you will see the updated content.

1.5 Enable GitHub pages for another repo

Sometimes we have multiple projects in several repos and we want to keep the documentation where it belongs. It would be great if we have a way to show all our documentation on a single website. GitHub makes it very easy, below we go through the steps needed to enable the pages from a different repo. The process may be used for any new repos you create under the organization.

The last step above is necessary for enabling pages for a repo, it was not needed for the repo [your organization name].github.io as the pages are enabled by default for a repo with the name *.github.io.

title: project-repo docs
description: Docs for the project-repo
remote_theme: pages-themes/cayman
plugins:
- jekyll-remote-theme
---
layout: default
title: Docs for the project-repo
description: Docs for the project-repo
permalink: /
---
This is the docs homepage for the repo [project-repo](https://github.com/gh-pages-project/project-repo).

Visit the link https://[your organization name].github.io/project-repo and if everything went well you will see the homepage for the project repo docs. Well done! Before we take a coffee break, let us create a link to the above page:

Visit the example repo [example](https://github.com/gh-pages-project/project-repo) with a docs folder as the source of pages [pages for example repo docs](https://gh-pages-project.github.io/project-repo/).

Wait for a minute or so and visit the page https://[your organization name].github.io/ and click on the link you have just created. Great, let us take a coffee break.

2. Implement Comments

Taking comments from others about your work is a step towards collaboration and it also helps improve your work. Let us implement comments functionality for our site.

In the subsections below, you will see some code using html, Liquid, and Jekyll jekyll docs. In this project we are not going to explain the code, that is beyond our current scope, we just want to implement comments here.

2.1 Enable discussions for the pages repo

Enabling discussions is a requirement to allow comments on our pages. For a demo, We will enable discussions only for the pages repo [your organization name].github.io, this will allow us to enable comments in the pages we create in the repo.

Now discussions are enabled, next step is to install giscus app.

2.2 Install giscus app for the organization

We are going to use giscus app (it is free and open source) as a backend for the comments functionality. We will install the app at the organization level so that we can use it for multiple repos if the need arises.

We are done with installing the giscus app. In the next exercise, we are going to generate html code that we need to include in our pages to allow comments.

2.3 Include giscus generated html code

The html code we need is unique for every repo. We can generate it for any or every repo under our organization. For our demo, we need it only for our pages repo [your organization name].github.io.

<script src="https://giscus.app/client.js"
    data-repo="gh-pages-project/gh-pages-project.github.io"
    data-repo-id="R_kgDONOp0jQ"
    data-category="Announcements"
    data-category-id="DIC_kwDONOp0jc4CkRnZ"
    data-mapping="url"
    data-strict="0"
    data-reactions-enabled="1"
    data-emit-metadata="0"
    data-input-position="top"
    data-theme="preferred_color_scheme"
    data-lang="en"
    crossorigin="anonymous"
    async>
</script>
<div style="max-width: {{ site.max_width }}; margin: 0 auto;">
code generated by giscus app here
</div>

2.4 Create a page layout in the pages repo

---
layout: default
---
<h1>{{ page.title }}</h1>
<p>{{page.date}}</p>
<p>{{page.author}}</p>
{{content}}   
{% if page.giscus_comments %}
{% include giscus.liquid %}
{% endif %}

2.5 Create a test page for comments

---
layout: page
title: A page with comments enabled
description: test giscus comments
giscus_comments: true
author: author_name
date: 17-11-2024
---

This is a test page with comments enabled.

Let us create link for the test_comments page for easy navigation:

Exercise: visit the root folder of the pages repo, edit the file pages/home.md by adding the following content at the bottom of the page:

A page for testing giscus comments functionality is [here]({% link pages/test_comments.md %}).

Note: The two methods used above for linking a page use different file paths for the same page, *test_comments.md vs pages/test_comments.md”. In this introductory project we will not discuss this subject (links and linking in Jekyll)). A tutorial on Jekyll and Liquid syntax is beyond the scope of this project. Great, we are done with enabling the comments.

2.6 Enable discussions for the organization

Enabling discussions for a repo is a requirement to allow comments on our pages. We can also optionally enable discussions at the organization level, that will be a place to discuss the organization level topics.

Great, we now have a place to discuss everything that comes under our organization. Next let us implement a GitHub workflow for our pages project. Break time.

3. Setup a GitHub workflow

GitHub actions and workflows help us automate CI/CD. In fact, in this project, we are already using a GitHub workflow behind the scenes. Whenever, we make changes to a file in the pages and project repos ([your organization name].github.io and project-repo), GitHub runs a work flow to build and deploy the pages. If we click on Actions tab for one of the repos, we will see a list of runs of the workflow pages build and deployment under All workflows. This workflow runs whenever we commit to the main branch of our repo (the runs are listed under actions tab for each repo with pages enabled).

The default workflow mentioned above is nice but it is not in our hands. Let us create our own workflow to build and deploy GitHub pages (see docs for more info):

3.1 Enable custom workflows for a repo

The following exercise will disable the default workflow and enable our custom workflow to build and deploy pages.

3.2 Write a custom workflow

name: build_deploy_gh_pages
on: 
  workflow_dispatch

jobs:
  # Build job
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v5
      - name: Build with Jekyll
        uses: actions/jekyll-build-pages@v1
        with:
          source: ./
          destination: ./_site
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ./_site
  # Deployment job
  deploy: 
    permissions:
      contents: read
      pages: write
      id-token: write
    environment:
      name: github-pages
      url: ${{steps.deployment.outputs.page_url}}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

3.3 Run the custom workflow

The above workflow will not run automatically. Every time we want to rebuild the pages after making changes, we will need to run the workflow manually as follows:

So far we have implemented a custom workflow only for the repo [your organization name].github.io. We will need to repeat the process for our other repo named project-repo: Exercise: Follow all steps in section 3 above for the repo named project-repo. The only change we need to make is the value of source field under actions/jekyll-build-pages@v1 in the workflow code: change “./” to “./docs”.

There is one improvement we should make. We have almost the same code for the workflows in both of the repos ([your organization name].github.io and project-repo). It would be nice if we can create a reusable workflow that both repositories can call. Let us do that now.

3.4 Reusable workflow

We need to create a new repo that will host the reusable workflow that both of our repos can call, then create a reusable workflow in it and change the code of the repo workflows we have created above so that we can call the reusable workflow from both repos.

name: build_deploy_gh_pages reusable workflow
on:
  workflow_call:
    inputs:
      build_source:
        description: source directory for build
        required: false 
        type: string
        default: ''
      build_destination:
        description: destination directory for build
        required: false 
        type: string
        default: _site
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: checkout file
        uses: actions/checkout@v4          
      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v5
      - name: jekyll-build-pages@v1
        uses: actions/jekyll-build-pages@v1
        with:
          source: ${{inputs.build_source}}
          destination: ${{inputs.build_destination}}
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ${{inputs.build_destination}}
  deploy_gh_pages:
    needs: build
    permissions:
      contents: read
      pages: write
      id-token: write
    environment:
      name: github-pages
      url: ${{steps.deployment.outputs.page_url}}
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
name: build_deploy_gh_pages
on:
  workflow_dispatch 
jobs:   
  job1: 
    permissions:
      contents: read
      pages: write
      id-token: write
    name: call the reusable workflow
    uses: gh-pages-project/workflows/.github/workflows/build_deploy_gh_pages.yml@main
    with:
      build_source: './'

Now let us test our new setup. Click on Actions tab and run the updated workflow. Wait for the workflow to finish. If it finishes successfully, go to your pages site and refresh your browser. If all went well you will see your site.

We need to repeat the above steps for our repo named project-repo with the following change in the workflow code: Change the value of build_source from ‘./’ to ‘./docs’. Also test the workflow.

4. Including Code, Images, Diagrams, and Math

This topic is a bit advanced for this project, a separate project is needed for this topic. Just a quick rundown:

4.1 Images

Include a local image (image source):

The code

        ![test image](/your_image_location/img3783small.jpeg)

renders:

test image

4.2 Code blocks

Code blocks are enclosed inside triple backticks with the coding language name appended as below:

        ```html
        <p> html code example </p>
        ```

the above code renders as:

<p> html code example </p>

4.3 Diagrams and math

We use Mermaid for diagrams, and MathJax for math equations. See test pages (test_mermaid and test_mathjax). See the source code in the _includes and pages folders of the repo.

Great, the project is done. Happy writing ❤️.

Acknowledgments: I got a lot of help from github docs and jekyll docs for writing this document.