The timeless repository

Building a Website with Webby

Written by Magnus Holm.

My previous blog was generated by Webby, a neat micro-CMS built by Tim Pease. It’s a lovely piece of Ruby which was a perfect fit for my blog:

Editing

With Webby you decide how you would write your site. Since everything is just plain text files, you can use Vim, Emacs, TextMate or even Notepad. At the top of each page you can define some metadata:


title:      Building a Website with Webby
created_at: 2008-02-25 22:45:43.134435 +01:00
filter:
  - fn
  - uv
  - textile

The title and created_at is only used by me, while Webby uses the filters to format the content. The Textile-filter is bundled with Webby, while the uv and fn filters are written by me.

Speed of Light

Since Webby simply generates static files, they will be served directly by Apache by the speed of light! After a simple webby deploy, the blog is getting rebuilt and deployed to the server (using rsync). Simple and efficient.

Hacks!

However, the best thing about Webby is probably that it’s dead simple to extend. You can easily create new filters and thanks to Ruby, you can also easily monkey patch anything. Webby automatically includes all the files in the lib-folder, so there’s no need to edit the source directly.

For instance, I wasn’t satisfied with the way Textile showed the footnotes, so I added my own footnote-filter like this:

Webby::Filters.register :fn do |input|
  # If you add `fn` to filters, Webby will run this piece of code where
  # `input` contains the content and the return value is what it will
  # be replaced with.
  input.gsub!(/fn(\d+)\. ([^\n]+)/) do |s|
    "<li id=\"fn#{$1}\"><sup>#{$1}</sup> #{$2}</li>"
  end
  li = '<li id="fn\d+.*?</li>'
  input.sub(/#{li}([\n\040]+#{li})*/, '<ul class="footnotes">\0</ul>')
end

I also wanted to use Ultraviolet for syntax highlighting:

Webby::Filters.register :uv do |input|
  input.gsub(%r{<syntax( lang="(\w+)")?>(.*?)</syntax>}m) do |s|
    if $2
     "<notextile>" + Uv.parse($3, "xhtml", $2, false, "sunburst") + "</notextile>"
    else 
      "<pre>#{$3}</pre>"
    end 
  end
end

index.txt

After you’ve mastered the editing, and maybe even created some nifty filters, you want to create an index page. Webby makes this very easy: the variable @pages returns an instance of Webby::PagesDB and @pages.find makes it dead simple to find the pages you want:


filter:
  - erb

<% pages = @pages.find(:limit => :all,
                       :in_directory => 'posts',
                       :sort_by => 'created_at').reverse
   # I want to show the first page differently:
   first = pages.shift %>

<h2 id="first"><a href="<%= first.url %>"><%= first.title %></a></h2>
<%= first.render %>

<% pages.each do |page| %>
  <h2><a href="<%= page.url %>"><%= page.title %></a></h2>
<% end %>

Feedalicious

In these busy days you can’t run a blog without providing a feed. Since a feed is basically just a XML-file (just like your blog posts are just a HTML-file), we can use Webby’s ERB-filter to find the pages and just generate it just the way we generated the index page.

Have a look at my atom feed if you need something to build upon.

Conclusion

Webby is still my favourite blog engine; the reason I built Timeless was because I no longer wanted a traditional blog. That said, it should be mentioned that it’s been a while since the latest release of Webby, and maybe Nanoc is a better solution for you.