In my last post I detailed how I used Jekyll and the the new version (3) of the Minima theme, to style my site so that it looked similar to the WordPress team’s Twentythirteen theme.
In this post, I am going to outline how I created a new layout portfolio that could showcase any project of my making/tinkering/engineering/enginerding - be it a woodworking project, a mechanical contraption, or a Python script.

Design considerations

The portfolio layout started with a basic need. I wanted portfolio to keep the layout I was using on my WordPress site, which uses a paid plugin called GridKit. I was quite happy with the layout this plugin allowed me to have, but I wanted a bit more.
My WordPress portfolio using GridKit My WordPress portfolio using GridKit
First, I wanted to be able to display code snippets and projects’ readme’s. Second, I wanted to have a better understanding of how things were built. Third, though the plugin has got a free version, I found that it was not enough for what I wanted to display, and it was costing me money.
So, I set out to find how I could display a grid of pictures representing my projects, with a description scrolling from the top of each grid box describing the specific project on :hover, then on a click to open a modal displaying the project’s content - be it a README.md, a code snippet, or pictures.
GridKit portfolio modal GridKit portfolio modal

Finding solutions

Using Jekyll’s structure and YAML front matter

I started out with adding a collection to my _config.yml, then adding a new layout, _layouts/portfolio.html. A new page, portfolio.md was also added, as well as some markdown files in the _portfolio/ folder, describing the project and adding some content for the new layout to parse. The example below is of one the projects, and displays nicely a lot of the capabilities. It has a title, and some cover picture, and a text displaying the project in a few words. It also has tags, so the layout can group several projects sharing the same tag for the person viewing the portfolio to filter by, and a link to the project’s web page (in this case a github repository for the project). The last part of the yaml front matter is an array containing pictures, code, or markdown, to be rendered in the specific project’s modal.

---
cover: ble_slider_web_app_2.png
title: "Web-BLE control app + esp32 sketches"
tags: iot control
link: https://github.com/UriShX/ESP32_fader
modal:
  - md: https://raw.githubusercontent.com/UriShX/ESP32_fader/master/readme.md
  - img: ble_slider_web_app_2.png
  - img: ble_slider_web_app_1.png
---
A web-ble responsive web app to demonstrate control over BLE of ESP32 projects. 
Includes links to github repo of web app, and to a couple of ESP32 sketches for testing.

However, when displaying code, my layout needs a bit more information, so an object specifying the language to be displayed and whether line numbers should be rendered is also required. That is since code in one language can sometimes contain bits in some other language, such as a HTML page contained inside an embedded C code, for example.

modal:
  - code: 
      link: https://raw.githubusercontent.com/UriShX/portfolio/master/Roboclaw_control_over_ESP32_with_AP_for_control/roboclaw_esp32_w_AP_and_config.ino
      lang: cpp
  # - linenos: linenos

Adding modals

The two main characteristics of the GridKit portfolio I had on my WP site were its general layout, and that each project was displayed in its own modal window. Laying out the projects in a grid and animating their display is done through Jekyll’s own structure, and detailed below. But I had to come up with a way to display each project’s content in it’s own modal, which is not part of the theme I was using, Minima.

I started out looking for a ready-made solution, and my search parameters were threefold:

  1. I wanted a modal library that will use the least amount of JavaScript - so, mostly implemented in CSS.
  2. I wanted the modal library to be either pure CSS, or - preferably - in Sass.
  3. I also did not want to include a whole CSS framework, mostly because I wanted to use the existing layout of the Minima theme.
  4. And, naturally, I would prefer a library that will have ample examples, and is developed enough to use in production.

Searching Google got me to CSS-Modal, which checked all the boxes. All I had to do was figure out how to use it in my new layout. I copied it’s .scss files into Jekyll’s _sass/ folder (under a fitting subfolder, _sass/drublic-css-modal/), and it’s few JS utilities into Jekyll’s assets folder, under assets/script.

Importing and displaying remote code

As I wrote above, I wanted to add the ability to display projects that consist of code or markdown files. Simply put, not all of my projects have a visual element to them, but I still wanted to display them in a way that will be similar to the more visually- centric projects.
I wanted to use Jekyll’s statically built structure to my advantage, and import all the code snippets and MD files at build time. That way, the site contains all of it’s components, and can even be displayed off-line quite easily, which can be important when displaying my work in places with bad internet connection. In those cases, the site can be displayed directly from my phone’s cache.

For achieving that, I had to use a couple of Jekyll plugins.
The first one because Jekyll’s include and include_relative tags were designed to include HTML files in layouts, and not content - thus they allow only for including files from the current Jekyll project.
The second plugin was needed to allow passing parameters to Jekyll’s highlight tag, in a similar way to what’s possible with the include tags. Jekyll uses Rouge to format code snippets, and it does so quite intelligently, figuring out the code’s language from its’ syntax. Since some of my projects mix languages (as I wrote above, HTML code in an embedded C program, for eg.), or use non standard file extensions (such as .pde for Processing, or .ino for Arduino), I wanted to have the same control over the rendered language as for the source itself.

I searched RubyGems for Jekyll plugins that could quite fill my requirements, but couldn’t find any ‘out of the box’ solutions, so I set about adapting and writing some code.

For including files, I found jekyll-remote-include. This plugin can include a remote file in a similar way to Jekyll’s include tag already, but I wanted to add to it a capability. I wanted to be able to use Liquid to render my portfolio from a template, so each included remote source should be passed on as a variable. To achieve that, I forked the plugin’s repository, and added a begin/rescue block (which is Ruby’s way of calling a try/catch block). In this block the plugin simply tries to parse the URI from the given parameter, and if it fails, it tries to parse the URI as a context variable. That seems to work in a decent enough manner, so I opened a PR with my addition, which I hope will be merged to the plugin repo some day. In the meantime, my revised plugin can be found here.

As for passing variables to the highlight tag, I really couldn’t find what I was looking for as a plugin, so I set about writing my own, or rather re-writing Jekyll’s mainline implementation. My first implementation was pretty rough. I basically tried to use the same method as I did with the remote-include plugin, using a begin/rescue block, but that only got me part way to my goal. What it actually do is fail gracefully, by checking if the code is a context variable, and trying to parse it. If it cannot do that, the code simply continues as the mainline tag does. Once I figured that didn’t quite do what I was expecting it to do, I set about implementing a better model for selecting the route to go by.
Implementing a better model for detecting the passed parameters required a change to the regular expression in the tag’s code. I wanted the syntax to be as close to Jekyll’s implementation of Liquid, so my implementation is looking for curly braces to filter passed variables, and if it does not find any - it considers the parameter as a constant. That means backwards compatibility is maintained with Jekyll’s highlight tag, while allowing for variables to be passed. I opened a feature request for that in Jekyll’s repository, but I haven’t opened a PR yet. My implementation can be found on rubygems.org as jekyll-highlight-param.

Adding the plugins into a Jekyll site is quite simple, by directing the Gemfile to pull straight from Github:

# frozen_string_literal: true

source "https://rubygems.org"

gem "jekyll", "~> 4.1"
gem "minima", :github => 'jekyll/minima' #:git => "git@github.com:jekyll/minima.git" # github v.3.0, latest build is 2.5.1

group :jekyll_plugins do
    gem "jekyll-remote-include", :github => 'UriShX/jekyll-remote-include', :branch => 'context-variables' #:git => "git@github.com:UriShX/jekyll-remote-include.git", :branch => "context-variables"
    gem "jekyll-highlight-param", :github => 'UriShX/jekyll-highlight-param' #:git => "git@github.com:UriShX/jekyll-highlight-param.git"
end

Note, that to direct a plugin to a specific branch (like to my revised jekyll-remote-include plugin, which accepts variables, and is not yet merged to the main plugin repo), it is possible to pass :branch => to the gem.

building up the page

Building the page using Liquid

Building a portfolio from a collection and a bunch of markdown was a bit convoluted. I used quite a lot of flow control logic, checking whether the collection was indeed a portfolio, looking through the files in the _portfolio directory, pulling the content of each (the text describing the project), and creating a modal for each sort of project - code based, a markdown file, a picture gallery, a combination of those, or even none at all. I then arranged the projects (programatically) by order of their place in Jekyll’s _config.yml, and push the projects that were found in the _portfolio folder but were not in the _config.yml to be sorted alphabetically at the end of the portfolio.
Cover images and tags are also pulled from the project’s front matter, and by using some icons from Google’s Material Design Icons, (linked to in _includes/custom-head.html), links and modals are linked to each graphical representation of a project.

Most of the modal code for image galleries is based on the examples for the CSS modal library I used. With some Liquid control logic, and with the aid of the two plugins I wrote of above, creating a nice modal view of markdown and code files was not that difficult to implement also.

The whole portfolio layout can be found in my jekyll-portfolio repository, under _layouts/portfolio.html.

Layout using Sass

Since I’m using Minima v.3, it was quite easy to link the CSS modal library. All that’s needs to be done was linking the modal library’s .scss files, which I placed under _sass/drublic-css-modal, into Minima’s _sass/minima/custom-styles.scss, under an @import tag.

The rest of the portfolio styling can be found on lines 226 onward:

I then used the new CSS grid layout to style the layout of the .portfolio-wrapper class, in a similar way to how GridKit styles portfolios.

Some more styling for each .portfolio-block class to get the zoom-in and sliding animations for the text and links, darkening the background when a modal is open, as well as creating a satisfying layout for narrow screens such as phones, and that was it.

Filtering using JS

Finally, I needed a way to filter the projects by some key words. I used Jekyll’s tags to group them using Liquid in _layouts/portfolio.html, then display the tags on top of the portfolio blocks.

I then wrote a short JS script for querying the list of a href links created by the Jekyll layout, generating an array of links to projects, and by adding an event listener to the hashchange event, hiding or revealing the projects with the appropriate tags.

The script uses a mix of ES5 and ES6, though I believe it is quite easy to read and understand. I made a conscious decision to not provide support for older browsers, so using modern JS is easier for me.

Conclusions

This has been a really long post, so I think I’ll end here. The whole layout can be found on the repository I opened for it, called jekyll-portfolio.

Writing my own implementation for a portfolio layout in Jekyll was quite a learning experience. I still have some ways to go, as I still need to figure out a better way for sizing images better, and perhaps adding a PWA capability.

Besides that, the versioning for jekyll-highlight-param’s does not follow the semantic versioning scheme, and my additions to jekyll-remote-include need some refining.