My goal here is to dynamically generate pages like /categories/code/, that would list all articles categorized in code. As far as I can tell, there’s no standard way. I found a few articles explaining how to create such pages for a given category, but none regarding how to auto-generate them for all your categories.

For this purpose, I resorted to some scripting, which through the power of CI, is completely transparent.

The process is:

1. Create layout for category page
2. Generate a JSON file containing the list of categories.
3. Generate a page for each category using the layout in 1.
4. jekyll build

# Layout

The layout I used ressembles a lot the layout of the home page. In the _layouts folder of Jekyll, I created this file:

---
layout: default
---

<div class="home">

&#123;&#123; content &#125;&#125;

<ul class="post-list">
&lcur;% for post in site.categories.&lbra;page.category] %&#125;
<li>
<a href=""><span class="post-title">&#123;&#123; post.title | escape &#125;&#125;</span><br/>
<span class="post-meta">&#123;&#123; post.date | date: "%Y-%b-%-d" &#125;&#125; | &#123;&#123; post.categories | array_to_sentence_string &#125;&#125;</span>
</a>
</li>
&#123;% endfor %&#125;
</ul>
</div>


This basically iterates through the posts of a category contained in property category of a given page using this layout.

# Category list

In my assets folder, I created an assets.json file with the following contents:

---
---
{
"categories": [

"Psychology",

"Code",

"Code like a monkey",

"Design patterns",

"Process",

"Organization",

"Self improvement",

"Management",

"Source control",

"Devops",

"Coffee script",

"Functional programming",

"Node.js",

"Slack",

"WIP",

"Azure",

"Bot",

"Security",

"Flow",

"Small batches",

"Product management",

"CI",

"AWS",

"Physics",

"KSP",

"Azure functions",

"Lambda",

"Git",

".Net",

"Jekyll",

"Webapps",

"Agile",

"DevOps",

"Smells",

"Memo",

"Architecture",

"VSTS",

"Quick note",

"Software",

"Coding",

"Geek",

"Linux",

"Windows",

"Development",

"Authentication",

"App Services",

"Cloud",

"Other",

"API Management",

"Tools",

"Self organization",

""
]
}


The --- tell Jekyll to build the file. The rest is just simple liquid. When building, the result looks like this.

# Generate a page for each category

The page is plain and simple:

---
layout: category
category: Code
---


We just need to generate one for each in a categories folder, so that they can be accessed through /categories/code/.

Let’s start with a simple node script running through the categories.json:

const path = require("path");
const fs = require("fs");

const categoryFile = path.join("_site", "assets", "categories.json");
const categoryFolder = path.join("categories");

const deserializedCategories = JSON.parse(categoryContent);
const categories = deserializedCategories.categories;

categories.forEach(function(category) {
if (category === "")
return;
const content = "---\nlayout: category\ncategory: " + category + "\n---";
const file = path.join(categoryFolder, category + ".md");
fs.writeFileSync(file, content);
});


I then invoke that in my build script:

#!/usr/bin/env bash

function build {
if [ "\$1" != "--refresh" ]; then
jekyll build --incremental
else
jekyll build
fi
}

function updateCategoryPages {
if [ -d "categories" ]; then
rm -rf categories
fi
mkdir categories
node build/updateCategories.js
}

build
updateCategoryPages
build


The first build is going to generate the categories.json file. Then we iterate through it and generate files. Then we build again.

Having my build done on Codeship, all I need to do is push and this is done automagically.