Static Site Generator Assemble

The advantages of having a static site-generator integrated in one and the same build-tool (that you may already be using) is huge: Assemble itself is a Grunt- (also Yeoman and Node, and soon to be Gulp-) plugin. At the same time, Assemble assumes very little about “what it is that you are trying to do”; making it fun to use (if you are also the kind of person that tends to want to make things their own …).

For an example with the alpha version of Assemble 6.0, using Gulp ISO Grunt, go to this repo

Static Site Generator

One of the first problems to solve, when wanting to generate a website from flat files (without a database), is to come up with a flexible solution for site-wide navigation. In Assemble this could be tackled like this in a “partial” handlebars file, here nav.hbs:


<nav class="nav" id="nav">
  <ul>
    {{#withSort pages 'data.sortOrder'}}
      <li><a href="{{autolink}}" {{isActive}}>{{data.title}}</a></li>
    {{/withSort}}
  </ul>
</nav>

HTML mixed with handlebars’ template tags, spitting out 1 a complete “ordered” unordered list of the content folder files in the HTML-output. In the markup are references to these two handlebar-helper plugins: “handlebars-helper-autolink” and “handlebars-helper-isActive”. The sort-order of the linked files can be set in the versatile Yaml front matter in the content-file itself. So when generating pages from markdown, let’s say index.md, in the YFM 2, right in the head of the file, one can set these variables:

---
title:       Homepage
type:        home-page
sortOrder:   0
description: My Homepage
---

Built in variables can be used too.

Templating

Besides that you can put variables in the top of your content-files as YMF another way to get data into your templates is to store custom variables as “key-value-pairs” in an external file, for example a JSON or YML - file. The way to let the javascript rendering-engine know about this file, is to link it up (as a value for data) in the options-section for Assemble within the Gruntfile.

grunt.initConfig({
 pkg: grunt.file.readJSON('package.json'),
 assemble: {
  options: {
    data: 'src/data/*.json',
    assets: 'dist/static',
    layout: 'layout.hbs',
    partials: 'src/templates/partials/**/*.hbs',
    layoutdir: 'src/templates/layouts',
    helpers: ['handlebars-helper-autolink','handlebars-helper-isActive','src/helpers/**.js']
  },

So when I have a file called var.json in the src/data folder, then the variables within those files can be called with, for example in template partials files.


<!-- footer.hbs -->
<footer><small>by <a href="{{var.site-url}}">{{var.org}}</a> &middot; <a href="{{var.license-url}}">&copy; {{var.year}}</a></small></footer>

Alongside build in Handlebar-helpers 3, this becomes powerful templating at your disposal.

Make it your own

When I suffer from “horror vacui”, indecision or what not, from all these possibilities and options that can be set in tools like these, I like to fight this by baking a boilerplate 4: get a feeling for what it is like to, for example, use handlebar-templates, and partials with handlebar-tags within a small project.

At Assemble’s website you can find some very instructive boilerplates, and at the bottom of this article are some links to examples, but make sure to also look at implementations in Github repo’s made by Zurb’s Foundation, and the Gruntfile for h5bp-Effeckt.css, which may have even more minimal and up to date implementations.

Optimization

To be able to have the minified CSS within style-tags in the head of your HTML, for optimization, one can use the grunt-plugin grunt-contrib-copy to automate the hard work. Copy the contents of a minified CSS-file to a handlebars-file as a Grunt-task …

copy: {
  main: {
    src: 'dist/static/prefixed/home.min.css',
    dest: 'src/templates/partials/homeheadstyles.hbs',
    flatten: true,
    filter: 'isFile',
  },
},

… can do conditional tags as well in the base-layout template:


{{#is type "home" }}<style>{{> homeheadstyles}}</style>{{/is}}

Nice!

Publishing

Grunt-plugin grunt-gh-pages makes a gh-pages branch and commits and pushes the output of the dist folder to a remote gh-pages branch on Github. Still find it magical how that works from this command in the terminal: grunt gh-pages.

Styleguides

When you have read the next quote, (from the Javascript Jabber podcast featuring the creators of Assemble; Brian Woodward and Jon Schlinkert), it will not come as a suprise that there is also a converted implementation of Brad Frost’s Patternlab (originally in PHP), made with Assemble. Creating live styleguides on top of boilerplates like this are one of those things static site generators are made for.

We built a bunch of models and lorem ipsum type things for the buttons and for placeholder text with all the different components. And Assemble can just essentially iterate over all of those components and build the actual final components. But at the same time, it can also build all of the pages for demoing the components. So, you could for instance build a website with Assemble that is mostly text, like a blog or a regular website. But also then have a component showcase where you’re taking all of the partials or includes that you’ve created for the site and just create another destination path essentially for Assemble to build all of those components individually to showcase them. So, in one build you can build a component showcase and use those same components in the actual site …

Notes

  1. on the grunt build command, depending on the existing files in your src/content folder _(or whatever the name of that folder is: can be anything you like), also: can have subfolders too, it’s smart about that)_
  2. YAML-front-matter
  3. The build in handlebar helpers; there is if, unless, each, with and lookup. For an example of each, checkout the tutorial on maddesigns (in german).
  4. By “boilerplate”, I mean a complete folder structure with a Gruntfile.js and package.json files. With this being a Grunt-plugin, this also means a git-repo, (you can do yourself a big favor by making yourself familiar with that as well, if you haven't already). In the .gitignore file (in the root of the project-folder) you can add the output-folder, often called dist, to the list there: no need to keep this in the repo.

Examples

Resources

This article was also published on Codepen