15 September 2009

Merging categories and articles

When I first started writing Nesta I wanted a CMS that would allow me to:

  1. Write articles that would be published in an XML feed, and
  2. Collect my articles on topic specific category pages that would introduce each topic and link to relevant articles (see my Ruby on Rails page for an example).

Articles and categories are a great way to organise a blog; they’re user friendly and search engines love them. So nothing’s changed there; I still want articles and categories. However, I’ve been using Nesta on e-commerce sites recently and have been finding that Nesta, as a general purpose CMS, didn’t quite cut it.

Update: The work described below was originally carried out on a separate unification branch. As of 7 October 2009 the changes described below have been merged into the main code base.

The problem

I made a list of the things that I thought were holding Nesta back:

The solution

After mulling it over for a while I concluded that the only thing that makes articles different from any other page is that I want them to appear in my atom feed. I’ve also noticed that only the pages that appear in the feed need a date.

If articles are just pages, what’s the difference between a category page and a generic web page? A page only becomes a category page when you’ve got other pages with related content, and declare them to belong to that category.

If you’ve ever browsed the Nesta code you might have noticed that an Article and a Category were slightly different beasts, and yet we’ve just concluded that they’re both just web pages with different metadata. Whoops – that’s a design flaw.

I’ve refactored Nesta, merging the Article and Category model classes into a new Page class. You can see it (and try it) in the unification branch.

A typical content folder might now look like this:

menu.txt
pages/
  |
  +---- articles/
  |       |
  |       +---- things.mdown
  |       +---- more-things.mdown
  +---- topic.mdown
  +---- topic/
  |       |
  |       +---- stuff.mdown
  |       +---- more-stuff.mdown
  +---- about.mdown
  +---- contact.mdown
attachments/
  |
  +---- foo.png
  +---- bar.png

Note that categories/ and articles/ have been replaced with pages/, and that there’s nothing special about the new pages/articles/ directory; I just want to serve some pages with /articles in the URL. You could serve things.mdown from /cabbages/things if you like; just rename the directory. You can create URLs like /foo/bar/baz simply by nesting directories.

This seems like the way forward to me. I’m planning on waiting a couple of weeks to give people a chance to try it out and give me some feedback, before merging the unification branch into master.

As an added bonus the code is now simpler, runs faster, and uses fewer resources.

Trying it out

If you’re not already running a copy of Nesta you can check out a fresh copy and get started straight away with the new unification branch (you’ll need to install the relevant dependencies first – see the “Quick Start” section on the main page):

$ git clone git://github.com/gma/nesta.git
$ cd nesta
$ git checkout -b unification origin/unification
$ cp config/config.yml.sample config/config.yml
$ rake setup:sample_content
$ shotgun app.rb  # point your browser at http://localhost:9393

If you’re already running Nesta you can get yourself a local copy of the unification branch like this:

$ git fetch origin unification
$ git checkout -b unification origin/unification

If you’ve got some existing content then we’ll need to shuffle it around a bit. I’ve written a migration script to do it for you. Run it from within your Nesta directory:

$ ./scripts/unification-migration

The script automates the following:

  1. Makes a menu file (<content>/menu.txt) from your old category pages.
  2. Moves <content>/categories/* to <content>/pages.
  3. Moves <content>/articles/* to <content>/pages.
  4. Removes “Parent: …” metadata declarations, which are no longer used.

If your content is stored in a git repository the script will stage the changes for you, but will leave the task of committing the changes to you.

If you like the new layout of the content directory you can try merging the new Nesta code into your own site. If, for example, you had your own design changes stored in a branch called mysite you could merge the two together like this:

$ cd nesta
$ git checkout mysite
$ git merge unification
# Review the changes, resolve any conflicts...
$ git commit -m "Merged the unification branch."

After resolving any conflicts that might occur (I only had one when I updated effectif.com which I fixed by removing the category.haml file – page.haml has replaced it) you should find that your site looks just as it did before, but that it’s suddenly a whole lot more flexible…

I’d love to know how you get on. You can get in touch via Twitter or on GitHub. Or just drop me an email at graham@effectif.com.

Categories: Nesta, a Ruby CMS