WordPress is a good blogging engine and I was satisfied with it until a moment when I decided to have my own theme applied uniformly across the site. And here I decided to try something new, for example static site generation.

One is the most popular static site generators is Jekyll. It is a Ruby-based tool that accepts markdown text files and transforms them into HTML pages through liquid templating engine. As a result of running Jekyll on your local system you will have a fully generated site composed from static HTML pages that can be hosted in any environment. Such site does not require powerful system to be executed, can be easily migrated from host to host and is version control friendly.

If .NET environment is more familiar for you, you can try Pretzel – a C#-based project inspired by Jekyll. Pretzel is a command line utility that can prepare a site skeleton, compiles it and helps you to test the site before uploading it to the host.

First what you need to do for the new site is to prepare site structure. Pretzel supports two templating engines – liquid and Razor – and, for example, to create a site that will use Razor you need to execute

Pretzel.exe create site_name -t=razor

It will create a default site with sample data. For the default site Pretzel generates four folders and five files:

If you will open any generated post or any page file, in the beginning of all these files you will see a similar section. This is a YAML front matter block – it is used to initialize predefined variables or to pass your custom data to the templating engine.

One of the most important variables is a layout – it defines what layout should be used to generate this page. Pretzel is trying to stay compatible with Jekyll and you can check Jekyll documentation to see what additional variables are available.

Now you can compile the site with

Pretzel.exe bake site_name

During compilation Pretzel goes through all the files in your site folder and transforms them. First all .md files are translated into HTML. After that Pretzel combines all HTML files with layouts to get the pages. And finally it copies all non-transformable files like images or CSS into the output folder. If you already tried to compile the site you will see _site folder – this is a compiled representation of your site. And now is time to test the newly created site

Pretzel.exe taste site_name -p=7878

Migration WordPress blog to Pretzel

Site generated by Pretzel is fully static and if you use standard WP commenting system you will need to switch to some third party commenting engine. It could be IntenseDebate, Disqus or Facebook plugin – it’s up to you. Switching to Disquis is easy and painful, just install WP Disqus plugin and follow the instructions and all the comments will automatically migrated.

Next you need to export your current blog posts from WordPress dashboard. Use generated file to import the posts to you new site:

Pretzel.exe import -i=wordpress -d=site_name -f=WPExport.xml

Import function does not create site – you need to create a site and import the post afterwards. After that you can create your layouts and associate them with the posts.

Tips & tricks

Partial views

Razor template engine supports partial views. You can put .cshtml or .html files in _includes folder and reuse them with help of @@Include("include_name")


Most likely you want to keep your post’s and page’s URLs. The default schema is different from the one used by WordPress but you can control it using permalink parameter in YAML front matter. For example

permalink: /blog/:year/:month/:day/:title/index.html in 2012-04-19-atdd.md

will instruct Pretzel to generate /blog/2012/04/19/atdd/index.html that is identical to post’s URL in WordPress.

Permalink parameter can be applied to any page, not only blog posts. For example to my RSS feed is linked to /blog/feed/index.html.


Pretzel generates a template for your blog feed but it should be tuned – you need to setup domain name and author name. Also Pretzel does not track posts’ publication time and if you will use RSS template as is, after the site publication your subscribers will see all previous posts in the feed. It can be avoided by adding a pub time variable to each post and by using this variable in the RSS template. Unfortunately for me, I made a mistake in time format and ended with the repopulated RSS feed.

Tags and categories

Pretzel does not generate tag clouds and any archive pages, as well as sitemap – it is your responsibility.

To display list of the categories for the post I use the following code:

@@foreach(var category in post.Categories)
   <a href="/blog/category/@@Filter.Slugify(category)" class="tag">@@category</a>

If you will check Pretzel sources (at least at a publication date) you will not see Filter.Slugify function – this change request is not yet accepted and if you’d like to see how it work please look my fork of Pretzel.

Here is the code to list all the categories

@@foreach(var category in Model.Site.Categories)
      <a href="/blog/category/@@Filter.Slugify(category.Name)">@@category.Name (@@category.Posts.Count())</a>

And again, Pretzel does not create categories pages for you – you need to do it manually.


You can paginate blog index page to show, for example 10 post per page, and this behavior is also controlled in front matter:

paginate: 10
paginate_link: /blog/page/:page/index.html

This instructs Pretzel to split posts into pages by 10 and to generate index pages as /blog/page/2, /blog/page/3 and so on.

Inside of the layout you can iterate through the posts available for the current page:

@@foreach(var post in Model.Paginator.Posts)

For navigation all the pages can be linked together

   <a href="@@Filter.PrettifyUrl(Model.Paginator.NextPageUrl)">previous posts</a>

So, as you can see, Pretzel is not a full featured CMS solution that can be used out-of-the box by everybody. It requires some programming skills and tuning efforts.

Pretzel is still in development and there are many things that can be added in the future but even in the current state it is stable and useful in the field.

blog comments powered by Disqus