Schemescape

Development log of a life-long coder

Designing md2blog, a zero-config static site generator for dev blogs

Background

After investigating many popular static site generators, I wasn't able to find a convenient static site generator that met my needs out of the box. Fortunately, I was able to leverage Metalsmith (and numerous plugins) to get what I wanted. I'm calling the resulting tool md2blog.

In this post, I'm going to cover the design of md2blog. Note that md2blog is a work in progress that has not been released yet. Update: md2blog has since been released.

Design goals

Here's the overarching goal of md2blog:

Convert a self-contained, organized pile of Markdown posts into a minimal, but fully functional static blog, requiring zero configuration.

The key differentiator for md2blog is the "self-contained, organized" part. By this, I mean:

Additionally, the produced site is "minimal, but fully functional" in the following sense:

Note that "zero configuration" implies that md2blog is highly opinionated, to the point that there are no options to configure. Instead of fiddling with options and themes, the user's focus is strictly on writing and publishing content.

Input

Here's a more detailed look at building a dev blog with md2blog.

Directory structure

site.json

Here's an example site.json file:

{
    "title": "My dev blog",
    "url": "https://mydevblog.com/",
    "description": "A very good dev blog indeed"
}

Schema:

Field Type Required? Note
title string Required
url string Recommended Must end with "/"
description string Optional

Note that the site will generally work without specifying a URL, but the Atom feed will be forced to use relative links instead of absolute URLs.

Posts

Posts are written in Markdown and use YAML for front matter.

Front matter

Here's an example showing all of the supported YAML front matter properties (keywords and draft are optional, the rest are required):

---
title: First post
description: First post on my blog, with a relative link.
date: 2021-10-26
keywords: [additional-tag]
draft: true
---
(Markdown content follows...)

Schema:

Field Type Required? Note
title string Required
description string Required This text is displayed on index pages
date YYYY-MM-DD Required
keywords string[] Optional Additional tags for categorizing the post
draft Boolean Optional If true, the post will only be built when serving locally

Content

Here's example Markdown content, demonstrating relative links (these links get translated to the corresponding HTML files and checked at build time; they also work in VS Code's and GitHub's Markdown previewers):

# Relative links
Here's a relative link to another post in this category: [link](post2.md)!

And here's one to another category, with an anchor: [link 2](../category2/post3.md#some-section).

# Image
Here's an image:
![test](../../assets/test.png)

Finally, here is an example of including a code block (specifying the language is recommended, but optional):

# Code block
Here's some code:

```javascript
const add = (a, b) => a + b;
```

Output

All output is written to the out/ directory. Here's what the output might look like for the example above:

As noted previously, the entire site can viewed directly from the file system (no web server required).