Rocking and Rolling with Nanoc
When I began to design this website I decided that it should be a static site. The benefits of a static site are numerous:
- I can write my posts in any markup language I choose.
- I can write my posts offline using any text editor I choose.
- I can version control all of my posts using git.
- I can deploy the site using rsync.
Essentially, I can use the tools I use every day while programming to manage my blog which is very appealing.
I had a lot of options on choosing the framework to power my site and after I evaluated all of them, I settled on nanoc, a Ruby powered static site compiler. I selected nanoc over popular alternatives such as, jekyll and octopress because nanoc gives me a high degree of customizability. For something that is personal as my blog I preferred something that allowed me to customize everything.
By adopting nanoc I was able to get a static site where I can name and layout however I want. I can also create files in any format that I want. Currently I have all of my blog posts written in pandoc inside content/posts
with arbitrary file names like blog-post-about-nanoc.pandoc
. I didn’t have to adopt a foreign convention or monkey patch anything to get what I wanted. Other features that I have:
- Non-Blog pages in HAML.
- Layouts in HAML.
- Stylesheets in SASS and using the Compass framework.
- Résumé written in LaTeX and compiled to a pdf.
- Writing dynamic elements in CoffeeScript.
I was able to do this in nanoc because it is extremely easy to extend and ships with a large set of features.
Details on Nanoc
Nanoc is definitely one of the best maintained static site compilers I could find. The author, Denis Defreyne, uses it for his personal website and regularly answers questions on the mailing list and IRC channel. It also has very comprehensive documentation, something that many other alternatives lack.
Nanoc Terminology
A nanoc site is composed of the following key folder’s and files:
content/
- Your posts, images, etc end up in here.layouts/
- Layouts for content.lib/
- Ruby code to extend nanoc.output/
- The resulting site is placed here after compilation.config.yaml
- Configuration options for nanoc.Rules
- Rules for compiling, naming and applying a layout.
The core of my site is writing blog posts in pandoc and adding syntax highlighting to those posts using pygments. I am going to show the code which results in this to show how easy it is to customize nanoc.
Compile Rule
For this blog I had to define multiple compile steps in order to get HAML -> HTML, Pandoc -> HTML, SASS -> CSS, CoffeeScript -> JavaScript and LaTeX -> PDF transformations. These transformations are a result of the filters that nanoc ships with or filters that I wrote.
The compile rule for blog posts:
This rule operates on all the files that are in the content/posts/
and for each item I pass it through two filters, the pandoc filter and the pygments filter. The first transforms the post in to HTML, and the second adds syntax highlighting to the code bocks in the post. At the end I just apply the default layout to the item. This produces the final HTML of the page.
Filters
In the above rule I used two filters that did not ship with Nanoc. I had to create them because Nanoc does not ship with a Pandoc filter and I had to then create my own syntax highlighting filter because I could not get the built-in one to work. Lets look at the pandoc filter first:
Nanoc filters are stupidly easy to write. All you need to do is create a class that inherits from Nanoc3::Filter
, give it a unique identifier and define a run
method which takes in a string for you to transform. You just need to return the result of the transformation. To write my pandoc filter I used the pandoc-ruby gem which wraps around the pandoc executable.
Of course not all filters are going to be this simple. Adding syntax highlighting was significantly more complex. My pygments filter:
This filter assumes that the input is produced by my pandoc filter. It simply tries to find code blocks with a class of ruby and pipe the portion though pygments. It would be pretty easy to add support all languages that pygments supports.
Routing Rules
After compiling items the next rule applied is the route
rules. The route
rules define where an item should be placed in the output directory and what filename it should have. Since the Rules
file is pure Ruby you can leverage all of ruby to create the URL scheme required. Here is the route
rule:
This rule simply returns the desired path and filename of the item in the output directory. Here I use the to_slug gem to help me generate a slug in the URL from the post title. Of course if I change my post title, the slug changes so I have to be careful not to break links to my site.
Conclusion
Using nanoc has let me customize my blog to my liking with a little bit of work. I would not have been able to achieve this kind of setup with more popular solutions. If you like having this kind of control over your site then you should check nanoc out.
Like this post? Follow me on Twitter.