Creating Posts, Custom Metadata, and Data in Wintersmith

Share this article

In the first part of this mini-series I’ve introduced you to Wintersmith, one of the best Node.js-based static site generators in my opinion. I covered how to install and get started with Wintersmith and also discussed some features of Jade, its default templating system.

In this second installment, I’ll teach you how to create posts using the Markdown format, how to set custom Metadata, and also how to generate and deploy your static website.

Creating Posts

In the first part of this series, we’ve built our templates with Jade. Now it’s time to create some content for the site. By default, posts are written in Markdown rendered by Marked, though other renders are available as plugins.

Most developers seem to be familiar with Markdown, but if you aren’t, it’s very easy to learn. Many code editors either support it by default or via free extensions. There are many standalone Markdown editors out there, for example I use Mou on OSX and there is MarkdownPad on Windows. This post won’t go into the details of the specifics of Markdown but in case you need a place to start, I suggest you to take a look at this page.

Posts are placed in the contents/articles folder. Each post is given its own directory which will be its SEO-friendly URL. For instance, our post for the Season 6 episode of Adventure Time! named “Breezy” was placed in a directory named articles/season-6-breezy. Inside that directory there is our Markdown file for the post named index.md.

Post Metadata

Each Markdown post can have metadata on top using the YAML format, similar to Jekyll’s Front Matter. No metadata is required but template, title, and date. template is the template that should be used to render the post, title is the title of the post, and date is the date it was posted. If template isn’t specified, the post will not be rendered (which likely isn’t what you want). If title and date are unspecified, their values will receive defaults.

We are free to add any other metadata we want to. We’ll discuss this further in the custom metadata section below.

Wintersmith also allows us to specify metadata for posts using the JSON format via a JSON file in the contents directory. For more details on that, check the documentation.

Customizing Excerpts

Wintersmith lets us specify where it will end the excerpt within a post. This ensure that the excerpt does not exceed a specific length or ends in a logical spot. In order to specify the end of the excerpt, we have to place the following code within our Markdown post:

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

If we don’t specify this span, Wintersmith will look for the first instance of an <h2> or <hr>. If none of these are present, the excerpt will contain the full HTML of the post which is not what you want. The excerpt is available via the intro property on a page, as in our templates/partials/homepagemiddle.jade file:

| !{ typogr(article.intro).typogrify() }

If we wanted to check that an excerpt was specified, we can use the hasMore property of the page. You can learn more about how this works by examining the code of the page plugin.

Custom Metadata

Frequently, you’ll need to set your own metadata, either global to the site or local to a post/page. Let’s look at how this is done in Wintersmith.

Global Metadata

We can set any arbitrary metadata inside the config.json file under the locals object. For example, we can set a site name, description, and banner image in our sample site.

{
  "locals": {
    "url": "http://localhost:8080",
    "name": "Adventure Time!",
    "owner": "Brian Rinaldi",
    "description": "Adventure Time is an American animated television series created by Pendleton Ward for Cartoon Network. The series follows the adventures of Finn, a human boy, and his best friend and adoptive brother Jake, a dog with magical powers to change shape and grow and shrink at will. Finn and Jake live in the post-apocalyptic Land of Ooo. Along the way, they interact with the other main characters of the show: Princess Bubblegum, The Ice King, and Marceline the Vampire Queen.",
  "banner": "/assets/images/about.jpg"
},
...

These values are available anywhere in our site templates under a locals object. For example, we use the values above within templates/partials/footer.jade:

div(class="4u")
    section
        header
            h2 What's this all about?
        a(href="#",class="image featured")
            img(src= locals.banner)
        p= locals.description

It should be noted that these could also be referenced as banner and description without the locals and it would work as well.

Per Post Metadata

As we discussed earlier, every post should have metadata set. This metadata can contain whatever arbitrary values we choose. For example, here’s the metadata for one of our articles (contents/articles/season-6-breezy/index.md) where we set a shortdesc and a banner value.

---
title:  "Breezy (Season 6)"
date:   2014-06-05 10:33:56
template: article.jade
shortdesc: Finn decides to get back into the dating game to help his wilting arm flower.
banner: /assets/images/breezy.jpg
---

We can access the shortdesc value using the metadata object within the page object. Here we’re using it inside a loop on templates/partials/footer.jade:

- var i=0
- var articles = env.helpers.getArticles(contents);
each article in articles
    -i++
    if (i>2) && (i<8)
        li
            span(class="date")
                !=moment.utc(article.date).format('MMM')
                strong= moment.utc(article.date).format('DD')
            h3
                a(href=article.url)= article.title
            p= article.metadata.shortdesc

Of course, we can also access these within our page output, as we do within contents/templates/article.jade:

header
    h2= page.title
    p= page.metadata.shortdesc

Custom Data

Not everything in our site is going to be a post or metadata. Often we’ll have other types of data collections. For example, in our sample site, we have a collection of Adventure Time! characters with names, descriptions, and images. Rather than hardcode these values on a page, creating them as data allows us to reuse them throughout the site wherever we need and make their display flexible. Let’s see how this works.

Data in Wintersmith works similar to Jekyll collections in that it is file-based. Rather than placing a single JSON file into a predetermined folder, each object has its own file within whatever folder you choose under the contents folder.

For example, in our sample site, contents/characters contains a series of files, each with JSON data representing a character. Below is the contents of contents/characters/lsp.json:

{
  "description": "Lumpy Space Princess (LSP) acts like a bratty, apathetic, sassy, attention-seeking and willfully ignorant teenager, often texting on her phone.",
  "image": "/assets/images/lsp.jpg",
  "name": "Lumpy Space Princess"
}

This data is automatically read via the contents object based upon the name of the folder, with each file becoming an object within the array. Each property within the file is available under the metadata object. In our sample, we use this to output a list of characters on the home page:

each character in contents.characters
    div(class="4u")
        section(class="box")
            span(class="image featured")
                img(src= character.metadata.image)
            header
                h3= character.metadata.name
            p= character.metadata.description

Generating and Deploying

Now that we’ve completed our project, it’s time to deploy it. But first we need to generate the static files that we have to upload to our server. To build our site, execute the following command:

$ wintersmith build

By default, this command will generate the files into a build directory. However, we can specify a different path by using the -o option. We can also force the clean of the build directory before building by using the -X option. For a full list of build options you can use the command wintersmith build --help.

Conclusion

I think it’s pretty clear that Wintersmith offers a full feature set for a static site generator, allowing us to build complex static sites within the Node.js/npm ecosystem. Unfortunately, many of the topics discussed in detail here are not well covered in the limited project documentation.

The good news is that the source is all CoffeeScript, which is pretty easy to comprehend if you are a JavaScript developer. So, many of the details of how the project works can be learned by looking at the source code. In addition, there is a showcase of sites built with Wintersmith, many including source code, that can help you see how others have solved common tasks using the tool. While these are no replacement for a solid documentation, it should be able to get you where you need to go.

For additional samples of popular static site engines, check out my project on GitHub which includes not only this Wintersmith sample, but the same sample site built with Jekyll, Harp, and Middleman.

Brian RinaldiBrian Rinaldi
View Author

Brian Rinaldi is the Developer Content Manager on the Developer Relations team at Telerik. A large part of Brian’s work focuses on ensuring top notch content for the web development community on the Telerik Developer Network. Brian has been a web developer for over fifteen years. Recently, Brian founded a popular developer site called Flippin’ Awesome (now Modern Web) and serves as co-editor of Mobile Web Weekly. Brian writes regularly and also tweets the best articles, tutorials and new projects he finds @remotesynth.

AurelioDjadeNode-JS-Toolsnode.jsstatic site generatortemplating language
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week