Writing Blogging Software with Flat Files and Markdown

On Wednesday, November 27th 2019, 6:42:49 pm by Lee Nattress

I started this personal blog using some free software called Publii. It came with a simple template that served its purpose and allowed me to upload to an AWS S3 bucket. I got some articles about some things I was interested in and all was well.

Publii was great but I did not feel I had enough control over the content, and I wanted to have something more custom. I decided to write my own blog software, but it had to have some strict criteria.

  1. I want to be able to use markdown for the content
  2. I don't want any databases or vendor lock-in. If you want to migrate away from this software, you can easily.
  3. I want the result to be flat html and css.
  4. I want to be able to put the resulting html into an S3 bucket

Other than this, I can do it any way.

I decided to make a command-line application so that people can install it using a command like:

npm install my-app-name -global

...and use it in their terminal.

Plix is Born

The first command you'll use after installing plix is plix new blog-name. This will create a folder and create a set of files and folders.

The folder structure plix creates looks something like this:

│   plix.json
├───dist
├───src
│   │   404.md
│   │   index.md
│   └───assets
└───themes
    └───simplest
        │   index.html
        │   page.html
        │
        └───assets

Our new blog has a few key elements.

  • A source folder src. This is where our source markdown lives.
  • An output folder dist. This folder will be where our final html will live, and we will upload this to our S3 bucket.
  • A theme folder themes. This is where we keep our template files, css and javascript that make up our theme. The default (and at the time of writing, only) theme lives here, its called 'simplest'.

When we run the plix build command, plix takes the contents of the src folder and converts each one to html, by combining the template from the theme folder with the markdown file from the src folder.

In the src folder we create an index.md and 404.md. By default, AWS S3 buckets use a file called 404.html for any missing pages.

plix builds an index.html in the dist folder, with a list of blog articles, so that there is a way to navigate to them when you first enter the site. If you have enough blog articles, plix will create multiple index pages, with next and previous buttons, to navigate between them.

Other than the articles themselves, and the index pages, plix does not build anything else.

Minimal.

Configuring Using the plix.json

This is the plix configuration for this blog.

{
  "title": "Lee Nattress: Developer",
  "articlesPerPage": 8,
  "url": "http://leenattress.com/",
  "author": {
    "name": "Lee Nattress",
    "bio": "During the day I'm a mild mannered full stack software wizard but at night I become an indie game warrior and all round badass.",
    "photo": "assets/images/leenattress.jpg",
    "job": "I work as a senior developer at <a href='http://www.leighton.com' target='_blank'>Leighton</a>. We write software for employee onboarding, and other <a href='https://www.leighton.com/what-we-do/what-we-do-custom-software/' target='_blank'>amazing things</a>."
  },
  "theme": "simplest",
  "themeData": {
    "headerOverlayColour": "rgba(59, 48, 84, 0.6)"
  },
  "social": {
    "Twitter": "leenattress",
    "Github": "leenattress",
    "LinkedIn": "leenattress"
  },
  "links": {
    "Home": "/",
    "Github": "https://github.com/leenattress/plix",
    "NPM": "https://www.npmjs.com/package/plix"
  },
  "GTM": "GTM-TN8S455",
  "deploy": {
    "s3Bucket": "www.leenattress.com"
  }
}

This configuration is passed into every page, as well as used internally within the plix command-line application. This means you can put global information that will be available on every page in here.

Don't put anything in yours that's private. These things are sometimes used in templates and will be available in the source code of the html.

This JSON file can be added to and modified as you see fit. You can then reference any part of it, including the arrays in your theme file.

Template language and concepts

The template system I chose for plix was Nunjucks.

I wanted development to be swift so I opted for Bootstrap.

<ul>
  {% for name, item in items %}
  <li>{{ name }}: {{ item }}</li>
  {% endfor %}
</ul>

It has branching statements and loops. If you want to see it in action, look in themes/simplest/page.html.

I built the simplest theme from scratch. It contains only a single template file, and contains special cases for the index pages.

We can tell if the page is an index page like this:

{% if isIndex %}
    <!-- This is on an index page -->
{% endif %}

Each markdown you'll notice has some metadata at the top. This is not rendered as part of the page, but rather extracted and available in the Nunjucks template. This is the structure of the data available in the Nunjucks page:

  • {{pageTitle}} is the title found in the markdown meta-data.
  • {{pageDate}} is the data found in the markdown meta-data.
  • {{pageContent}} is the html, rendered using the markdown found in the remainder of the file.
  • {{pageLink}} is the filename of this file, with a html extension.
  • {{pageFeaturedImage}} is the path to a featured image for this blog entry.
  • {{siteConfig}} is the config, found in plix.json

{{siteConfig}}, by default contains the title of your blog, as well as any data you see fit to put in there.

You can access the data like this: {{siteConfig.title}} or {{siteConfig.author.name}}.

For more help creating a template in Nunjucks see here, or open page.html in your favourite editor to take a look at a simple example, with loops and conditional statements in Nunjucks.

Deploy

First, set your AWS keys, by following this guide: Environment Variables To Configure the AWS CLI.

I won't get into the technicalities of both creating and managing an S3 bucket on AWS, we're going to assume you have one set up and it's set up for public web hosting.

After you have set up your security you'll need to make sure that your bucket and region are set inside the plix.json file.

  "deploy": {
    "s3Bucket": "www.leenattress.com",
    "s3Region": "eu-west-2"
  }

Finally, run this command: plix build && plix deploy.

Why Markdown?

The reason I wanted a folder full of markdown is so that I could use git to manage my blog content. I wanted a series of simple text files in a known format so that I could migrate them easily if necessary.

plix can be used in continuous integration, and this is how I'm using it to build this very blog.

Getting Started

Here are the starter commands to install and build your html. Of course, you will need node installed.

npm i plix -g
plix new my-fabulous-blog
cd my-fabulous-blog
plix page my-first-page
plix build

What's Next?

This is a personal project and I really only put it together so I could make this blog more fun to create. If anybody wants to add features or talk about extending plix then get in touch.

Short Bio

Lee Nattress profile image
Lee Nattress

During the day I'm a mild mannered full stack software wizard but at night I become an indie game warrior and all round badass.

Job

I work as a senior developer at Leighton. We write software for employee onboarding, and other amazing things.

Social

Recent

Multi-browser Automated Testing with Selenium and...

Saturday, November 2nd 2019, 9:36:02 am

Designing and 3D Printing My First Useful Thing

Saturday, November 2nd 2019, 1:57:25 pm

Space Engineers IRL: Hydroponics Build Part 1

Saturday, November 2nd 2019, 4:48:10 pm

Couch Multiplayer With Pico-8 - Part 1

Saturday, November 2nd 2019, 7:08:51 pm

PicoBreed Breakdown - It’s full of stars

Saturday, November 2nd 2019, 7:44:04 pm