About this site
This site was created with GitHub Pages. In the process of learning about GitHub Pages, we decided to also document what we learned. The GitHub Pages approach leverages Jekyll. We also have sister site to this one where we build documentation with a different technology. That site is: travelmarx.github.io/scrapbook101core/.
Initial steps
We started out simply by creating this repository and editing using the GitHub user interface in a browser. We were able to set up the initial skeleton of the site with a few pages in under an hour.
We decided on the approach of using a folder named docs
located in the master branch. See the GitHub Pages docs for other choices. After seeing that we could choose a theme in our repository setting, we choose a theme and build our docs. We immediately got a decent looking site right-out-of-the-box. Behind the scenes, GitHub Pages takes what you have checked in and automatically generates your web site from any HTML or markdown files you have in the document root.
So far so good, but we wondered about how we could have a table of contents (TOC) show up in the left frame of our rendered site. This led us to reading about GitHub Pages and Jekyll. Jekyll is what turns markdown files into HTML. We took the following steps:
- Copy our Jekyll theme’s layout
_layouts/default.html
file into our project and modify it. - Add custom style in
assets/css/travelmarx.css
. - Add a
_data/toc.yaml
file to describe our table of contents. The_data
folder is a Jekyll directory convention convention and after reading this YAML tutorial, it all started to come together on how to create a table of contents.
Our table of contents file, toc.yaml
, looks like this:
toc:
- title: Introduction
url: index
- title: Get Started
url: get-started
sections:
- title: Run local
heading: run-local
- title: Run live
heading: run-live
...
The code to read the toc.yaml
appears in the _layouts\default.html
file and is logically this:
for itemLevel1 in site.data.toc.toc
link = itemLevel1.url, text = itemLevel1.title
for itemLevel2 in itemLevel1.sections
link = itemLevel1.url#itemLevel2.heading, text = itemLevel2.title
for itemLevel3 in itemLevel2.sections
link = itemLevel1.url#itemLevel3.heading, text = itemLevel3.title
endfor
endfor
endfor
After almost one hundred small commits with the GitHub user interface via a browser, it became obvious that the next step was to build the docs locally because the browser, even with multiple windows, was not a good solution for bulk writing and meaningful commits.
Running locally
Running our site locally, enables to
- Edit offline and with different tools and environments. (We use a combination of Git Bash, GitHub Desktop and Visual Studio Code.)
- Check in many changes at once.
- Speed up write-build cycle by finding and fixing build problems quicker. (Errors appear in the window where you start the Jekyll process.)
For more information about running Jekyll locally, see Setting up your GitHub Pages site locally with Jekyll. After following the help, our site wasn’t rendering correctly and we realized that while working only on-line (with the GitHub UI) our pages didn’t seem to need what’s called front matter, but locally it was needed for each page. A simple front matter looks like this:
---
layout: default
toc_entry: about-this-site
---
The next thing we realized was that we would need a Gemfile
to describe Ruby dependencies (Jekyll is written in Ruby) and a .gitignore
to avoid checking in local files we didn’t need saved, including the locally built site HTML files.
Here’s an overview of the key commands used in Git Bash to get going locally:
$ git init travelmarx
$ cd travelmarx
$ get clone https://github.com/travelmarx/scrapbook101.git
Create Gemfile base as suggested by the help page.
$ bundle install
$ cd docs
$ bundle exec jekyll serve
Notes:
-
You have to restart (
bundle exec jekyll serve
) to pick up changes in the_config.yml
. For example, if you add a new site variable. For other changes, you do not need to restart. -
If something doesn’t seem right with the build, check the build output in your Git-Bash window. This is where your big time savings comes in because you can see what the problem is right away and address it.
-
bundle is a Ruby Dependency Manager. The
exec
argument executes a script in the current bundle, in this case Jekyll gem. Theserve
option builds the site any time a source file changes and serves it locally.
Further tweaks
Here is a running of list of further tweaks to our document editing and setup process, presented in approximate order we implemented them.
Add Boostrap
After running this doc site for a few weeks, we wanted to add tabbed content using Bootstrap. This lead us discover that there is a GitHub Page theme with Bootstrap 4 startup site. However, instead of using this, we ended up injecting the necessary Bootstrap scripts into the _layouts\default.html
.
Relative Link
At first we didn’t notice the difference between the local URL (e.g., http://localhost:4000/index) and the live site URL (https://travelmarx.github.io/scrapbook101/index). The difference of “scrapbook101” made relative document links work locally but not live. This SO post pointed the way that we could specify a baseurl parameter when starting Jekyll locally. We do two things:
- We define any internal links without a forward slash (/).
- We start Jekyll locally specifying a baseurl parameter like so
bundle exec jekyll serve --baseurl '//scrapbook101'
.
Another way to do this is outlined in the Jekyll help for Project Page URL Structure.
Highlight TOC
To make it easier to see what page of the TOC is currently in view, we apply the active class to the current page TOC entry. The Jekyll instructions to do this are here. At first, we tried to use page.url
variable but ran into problems with the index.md
page in that the page variable returned just a /. Also, we saw that the page.url
included file extensions (e.g., .html), and to match we’d have to remove that, which isn’t hard with the Liquid templating language syntax. In the end, we decided to add a variable to each page’s front matter called toc_entry
and used it match the TOC name in the _data\toc.yaml
file.
Simple Navigation
To implement a simple previous/next page control (top right corner of page), we also used the custom page variable toc_entry
and add some logic to create the previous/next text and links. It helps to study up a little on the Liquid sytnax. We found the Jekyll page useful as well as the Shopify Liquid basics page. The basics of the code, which we fully admit may not be optimal, depend on assigning a variable, incrementing a counter, and using the index operation in the TOC arraw of pages.
{% assign prev_page = "" %}
{% assign prev_url = "" %}
{% assign next_page = "" %}
{% assign next_url = "" %}
{% assign num_toc_elem = site.data.toc.toc.size | minus: 1%}
{% assign my_counter = 0 %}
{% for itemLevel1 in site.data.toc.toc %}
{% if itemLevel1.url == page.toc_entry %}
{% if my_counter > 0 %}
{% assign prev_page = last_page %}
{% assign prev_url = last_url %}
{% endif %}
{% if my_counter != num_toc_elem %}
{% assign my_counter = my_counter | plus: 1 %}
{% assign next_page = site.data.toc.toc[my_counter].title %}
{% assign next_url = site.data.toc.toc[my_counter].url %}
{% endif %}
{% break %}
{% endif %}
{% assign last_page = itemLevel1.title %}
{% assign last_url = itemLevel1.url %}
{% assign my_counter = my_counter | plus: 1 %}
{% endfor %}
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="nav navbar-nav ml-auto">>
{% if prev_page != "" %}
{% assign prev_page = "« " | append: prev_page %}
<li class="nav-item nudge">
<a role="button" class="btn btn-outline-primary" href="{{prev_url}}">{{prev_page}}</a>
</li>
{% endif %}
{% if next_page != "" %}
{% assign next_page = next_page | append: " »" %}
<li class="nav-item">
<a role="button" class="btn btn-outline-primary" href="{{next_url}}">{{next_page}}</a>
</li>
{% endif %}
</ul>
</div>
Update Layout
We were inspired by the collapsible sidebar navigation examples on Bootstrapious and created a cross between what we had and what was suggested on Bootstrapious. The changes were made to the Jekyll Layouts page _layouts\default.html
.