zimki | all bloggers | admin login | recent entries for Stig Brautaset
 
Porting fotango.com to Zimki

Stig Brautaset on Wed Nov 01 2006 17:35:19 GMT+0000 (BST)

At Fotango we eat our own dogfood. For a while now we've been lamenting that our corporate site - fotango.com - wasn't running on Zimki. The combination of a static site and accompanying blosxom blog was just too painful to update. Last week I decided to bite the bullet and spend a couple of hours porting it across.

Initial naïve port

After I had created a new realm for my work, the first cut of the port consisted of just dumping the existing static pages into Zimki. I simply mounted Zimki using WebDAV with the OS X Finder and dragged the files in.

Files uploaded by WebDAV are immediately published to a path matching their path inside the 'files' folder. However, visiting a path with a trailing slash won't automatically serve index.cgi, index.htm, index.php or anything else. To solve this I added a redirect for the path '/' to '/index.htm'. Doing this in Zimki is easy; I simply put this somewhere in my server-side JavaScript:

zimki.publishPath('/', function () {
    return zimki.redirect(zimki.root + '/index.htm');
});

Introducing a Staging environment

I didn't want to break the existing site for the duration of the port, but opted to use a staging environment for my development. This allows us to test out new content before publishing it live.

Zimki has built-in support for creating a staging environment, which you can find if you go to the 'Realm List' entry in the portal. This page also allows you to take a backup of a realm at any point in time, and restore from such backups into an existing realm (replacing the content already there) or into a new realm.

Making the site URL agnostic

The staging environment naturally has a different url to the real site. However, we have to make sure that any internal links goes back to where we're currently served from. Looking at the CSS of the site I had just ported I found that it had lots of references to http://fotango.com, so I had to generate it dynamically. Handily, that's very simple with Zimki. I removed the '/css/main.css' file, then put its content in a template. I then replaced all the fully-qualified links with trimpath template snippets to build the links dynamically:

.right {
    background: url(${ zimki.root + '/img/right.jpg'}) repeat-y;
    width: 10px;
}

Of course, we now have to manually publish the CSS somewhere too. Also, while editing the CSS, I noticed that it had rather a lot of whitespace in it. That's fine for readability, but now that we generate the file anyway, we might as well compress it a bit as we're serving it:

/* publish the css, and compress whitespace at the same time. */
zimki.publishPath(/main\.css/, function() {
  var css = zimki.render.trimpath('main_css.tmpl');
  /* explicitly set the mimetype, lest FireFox gets a bit
     bitchy about asking it to view binary content */
  return { mimetype: 'text/css', content: css.replace(/\s+/g, " ") };
});

As it turns out, the CSS file was not the only file that contained fully-qualified links, so I ended up making similar changes to the rest of the static pages. Since I had to change the pages anyway, I went through a little extra pain and extracted a footer and header template, and created a separate template for the content part of each page. Then I created one big dispatch function to display each page:

/* publish all .htm & .html pages */
zimki.publishPath(/^(\w+).html?$/, function (args, path, match)
{
  var page = match[1]; /* grab the page name */
  var data = {};

  /* Page titles - the *actual* list has more... */
  data.title = {
    index: "Fotango",
    jobs: "Fotango :: About us :: Jobs",
  }[page];

  try {
    var content = '';
    content += zimki.render.trimpath('header.tmpl', data);
    content += zimki.render.trimpath(page + '_content.tmpl');
    content += zimki.render.trimpath('footer.tmpl');
    return content;
  }
  catch (e) {}
  
  /* we get here only if we couldn't find the requested page */
  return {
    content:render('404.html', { title:'page not found' }),
    status:404
  }; 
});

What about the blog?

Ah, yes. The blog. Turns Tom already wrote a multi-user blog in Zimki (namely, the one you're reading right now). It comes with downloadable source code so I pinched that, made it use the templates I'd already extracted, and tweaked the permalink urls a bit. Then I just added accounts and brought the content over: a purely manual job, as we didn't have enough entries for me to bother automating it.

In the interest of keeping old permalinks still working, I added the permalinks for each entry from the old blosxom site as an 'oldslug' attribute on each entry. All these ended in '.fotango', so it was easy to just redirect to the new urls:

/* For compatibility with the old blosxom-blog's rss feed url */
zimki.publishPath( 'index.cgi/index.rss', zimki.redirect(zimki.root + '/blog/rss') );

/* honour the old permalinks */
zimki.publishPath(/([^/]+)\.fotango$/, function(args, path, match) {
  try {
    var post = Post.get({ oldslug: match[1] });
    return zimki.redirect(post.url());
  }
  catch (e) { }
  return zimki.redirect('/');
});

Conclusion

The company site is now unified and therefore easier to update, load-balanced, we freed up some hardware resources, and my conscience is much clearer.

leave a comment

name
email
comment