Playing With Fire

Exploring the web one Elixir at a time

Switching from Wordpress to Wintersmith

I recently read an article in Web Designer magazine that got me thinking…

 

Why I switched from Wordpress to Wintersmith…

For those that don’t know what Wintersmith is, it’s a static site generator.

Wintersmith takes a set of text files (containing Markdown content), some plugins written in CoffeeScript, templates written in Jade and style definitions written in Less and munges them together and spits out HTML, CSS and JavaScript that can be hosted cheaply on any web server, anywhere.

That means that all code that is used to generate the site sits on my machine - not on a webserver. There is no hosted database, removing that as an attack vector. There are no issues surrounding updates to the server-side scripting language provided by the webhost. Server security patch/code conflicts are a thing of the past. Additionally, you don’t need to be attached to the internet to get your thoughts out. Just write the content, then build and deploy at a more convenient time - no more hunting for mobile signals whilst out and about.

Obviously there are downsides. User feedback is not going to happen without third-party support - something like Disqus, in fact most user interactivity is pretty much not supported without tapping into a third-party API.

For me, writing my blog, that doesn’t really cause me an issue, its not like I’m trying to build a cheap shop on top of a blogging engine or anything like that.

The last thing is that I really didn’t enjoy using Wordpress. As a piece of tech, it fulfills its job admirably, kudos to the people that work on its core codebase, but its just not for me. I’ve looked at other blogging engines, but I just like things to be simple. When I get time to write, I like it to be distraction free, so I made it as distraction free as possible: Me and Sublime Text 3.

Right, enough about why, lets move on to how.

 

How I switched…

The nice people at Wordpress created a lovely feature that really helps - Export.

 

Exporting Wordpress Content

You’ll need to dig through the Tools menu to find it, but it is there I promise you. Once you’ve found it, get Wordpress to export all the content - you’ll get a big file full of XML.

What you’re essentially looking for is:

<item>
  <title>The Post Title</title>
  <link>The Post URL</link>
  <pubDate>The Post Date</pubDate>
  <dc:creator>The person who wrote it, most likely YOU</dc:creator>
  ...
  <content:encoded><![CDATA[
      HTML content here
  ]]></content:encoded>
</item>
...
<wp:comment>
    A listing of each comment...
</wp:comment>

And there’ll be one of these for each post that was written in your blog. Store this file away somewhere, you’re going to need it later.

Side Note: I chose to convert my posts from HTML to Markdown by hand, but then I’ve only got a few posts so it wasn’t all that onerous. A few choice find and replace using regex really helps speed things up. There are HTML to Markdown converters available, so if you have a lot of posts to convert, it might be advisable to take a look at those.

 

Set up Wintersmith

Wintersmith is an NPM module, so you will need Node.js in order to install it.

Instructions for setting up Node.js can be found at nodejs.org, or if your operating system uses a Package Manager, then use that. For me, because I’m on a Mac I just use brew.

With Node.js in your environment, you will also have NPM.

We’re also going to use Bootstrap for this, so for me its helpful to have bower installed.

$ npm install -g bower

To install Wintersmith, in a commandline program issue:

$ npm install -g wintersmith

This globally installs Wintersmith in your development environment.

Still on your commandline, navigate to a convenient location and then you can start up a new application with wintersmith new <path>

$ cd ~/Projects/wintersmith-projects
$ wintersmith new blog
$ cd blog
$ tree -L 2
.
├── config.json
├── contents
│   ├── about.md
│   ├── archive.json
│   ├── articles
│   ├── authors
│   ├── css
│   └── feed.json
├── node_modules
│   ├── moment
│   ├── typogr
│   └── underscore
├── package.json
├── plugins
│   └── paginator.coffee
├── readme.md
└── templates
    ├── archive.pug
    ├── article.pug
    ├── author.pug
    ├── feed.pug
    ├── index.pug
    └── layout.pug

To make sure that all of this worked, you can issue wintersmith preview on the commandline and point your web browser at http://localhost:8080. You now see the default wintersmith blog. If there is an error this will appear as a message in your terminal.

To this I did the following:

$ npm install --save wintersmith-less
$ npm install --save wintersmith-robots
$ npm install --save wintersmith-tag
$ bower init
<just accept defaults>
$ bower install --save bootstrap
$ cd contents/css
$ rm main.css
$ mkdir style script fonts images
$ cd script
$ ln -s ../../bower_components/bootstrap/dist/js/bootstrap.min.js .
$ ln -s ../../bower_components/jquery/dist/jquery.min.js .
$ cd ../style
$ touch main.less

In contents/style/main.less add the following line (to pull in the bootstrap css)

@import "../../bower_components/bootstrap/less/bootstrap.less";

Copy all the bootstrap fonts from bower_components/boostrap/fonts/ to contents/fonts/

Update the config.json file with the following, changing the , and to appropriate values.

{
  "locals": {
    "url": "http://localhost:8080",
    "name": "<Blog Name>",
    "owner": "<Owner Name>",
    "description": "<Site Description>",
    "sitemap": "sitemap.xml",
    "noindex": false
  },
  "plugins": [
    "wintersmith-less",
    "./plugins/paginator.coffee",
    "wintersmith-contents",
    "wintersmith-robots",
    "wintersmith-tag"
  ],
  "require": {
    "moment": "moment",
    "_": "underscore",
    "typogr": "typogr"
  },
  "jade": {
    "pretty": true
  },
  "markdown": {
    "smartLists": true,
    "smartypants": true
  },
  "paginator": {
    "perPage": 5
  },
  "tag": {
      "template": "index.pug",
      "perPage": 5
  },
  "ignore": [
    "vendor/**/*.less"
  ]
}

With this stuff in place you’re now ready to start building templates

 

Building templates

Templates are built in Jade and kept in /templates/.

Use the templates that are already present to help structure your blog.

One thing to note is that the wintersmith-less plugin auto-generates the css on build/preview. This means that you need to link to /style/main.css

link(rel='stylesheet', href='/style/main.css')

When building templates I tend to go for large numbers of small dedicated templates, its not like they’re being pushed out for rendering to a client.

As an example of this, below are a selection of templates that I have put together for this blog

### layout.pug ###

doctype html
block vars
  - var bodyclass = "";
  - var sidebarwidth = 'col-md-3'
html(lang='en')
  include html_header.pug
  body(class=bodyclass)
    include header.pug
    block header
    .container
      .row
        block content

        include sidebar

      include footer
    include scripts.pug
    include googleAnalytics.pug

### html_header.pug ###

head
  block head
    include meta.pug
    title
      block title
        = locals.name
    include styles.pug

### styles.pug ###

link(rel='stylesheet', href='/style/main.css')
link(rel='stylesheet', href='/css/font-awesome.min.css')

### index.pug ###


extends layout

block content
  include author

  .col-sm-9
    main
      each article in articles
        - var tags = env.helpers.getTagsFromArticle(article)
        - var tagCount = tags.length
        article.post
          header
            h2
              a(href=article.url)= article.title
            p.blog-post-meta
              | Posted on 
              span= moment.utc(article.date).format('MMMM DD, YYYY') + ' '
              | by 
              mixin author(article.metadata.author)
              if tagCount > 0 
                |  in 
                each tag in tags
                  - tagCount = tagCount - 1
                  a(href=env.helpers.getTagHome(tag).url)= tag
                  if tagCount > 0
                    | , 

          .post-content
            if article.intro.length > 0
              != typogr(article.intro).typogrify()
            if article.hasMore
              p.more
                a(href=article.url) Read more...

block prepend footer
  div.nav.col-sm-8
    .col-sm-6
      if prevPage
        a(href=prevPage.url) « Newer
      else
        a(href='/archive.html') « Archives
    .col-sm-6.text-right
      if nextPage
        a(href=nextPage.url) Next page »

As you can see, none of these are particularly long or difficult to understand.

Important templates to have in place are index.pug, article.pug, archive.pug, author.pug and layout.pug, although it does depend on how you configure your articles. The only template that is absolutely required is index.pug

Once your templates are built you can start to add your own content.

Reading content from a content file is acheived using the typogr(page).typogrify() function.

Remember that you can always check on how your build looks by previewing using wintersmith preview.

 

Adding authors

Each Article requires an author.

The authors file is a JSON file in the following format

### clive.json ###
{
  "name": "Clive",
  "email": "clive@distortedthinking.agency",
  "bio": "Collector of obscure stuff"
}

The name that you give this file is to be the same name as that used in the page meta data author element.

 

Adding Your Content

Content goes into the /contents folder. If you’re writing a blog post then to help organise your content, there is a /contents/articles/ folder. I have found it easiest to create a folder with the post name, lowercased and spaces hyphened as follows:

### File name ###
switching-from-wordpress-to-wintersmith

This forms the URL of the page.

In this folder add an index.md file

This file has two parts - a header and a body. The header consists and is set up in the following manner:

---
title: Switching from Wordpress to Wintersmith
author: clive
date: 2016-02-03
template: article.pug
---

The title gets displayed as the HTML title.

The author is linked to the author file.

The date helps wintersmith sort the posts into the correct order.

The template tells wintersmith which template to apply to the content.

You can add more elements to this and they can be accessed using page.metadata in your template file.

The content that you want the page to display needs to be placed in the *.md files body. This content is written in Markdown.

In the end the content file looks something like

---
title: Switching from Wordpress to Wintersmith
author: clive
date: 2016-02-03
template: article.pug
meta: wordpress, wintersmith, blogging, coffeescript, jade, markdown
tags: Wintersmith
---

I recently read an article in Web Designer magazine that got me thinking...

<span class="more"></span>

&nbsp;
## Why I switched from Wordpress to Wintersmith...
For those that don't know what [Wintersmith](https://github.com/jnordberg/wintersmith) is, it's a static site generator.

Wintersmith takes a set of text files (containing [Markdown](https://help.github.com/articles/basic-writing-and-formatting-syntax/) content), some plugins written in [CoffeeScript](http://coffeescript.org/), templates written in [Jade](http://jade-lang.com/) and style definitions written in [Less](http://lesscss.org/) and munges them together and spits out HTML, CSS and JavaScript that can be hosted cheaply on any web server, anywhere.

The <span class="more"></span> is used to display the ‘More…’ element on the index page for each article.

 

The site has content, what next?

Ok, so you’ve built all the templates and written your content, so now what?

Once you’re happy with your site in preview mode, its time to build it

$ wintersmith build

If it so happens that you’ve built a post that you’ve since deleted and no longer want to deploy then use the following to clean the folder

$ wintersmith build --clean

Alternatively, you can just delete the /build folder.

This creates your site in static HTML, CSS and Javascript in /build. The contents in this folder can be hosted on any web host that uses a traditional webserver like Apache or IIS. For PaaS’s like Heroku, there are build packs available that will build and deploy site automatically on git push.

And thats it.