Introduction

The principle reason for using templates to build web sites is to achieve a clear separation of concerns between the basic content for a site (i.e. the words and pictures) and the way it is presented.

This article describes why this is such a good thing and shows how the use of Cascading Style Sheets (CSS) is a (very large) step in the right direction. It then looks at the use of the Template Toolkit which takes this principle even further, allowing you to build a web site in a modular fashion that can be easily extended, modified and customised.

Smell Fresh, Look Fresh

Top Close Open

So what's the big deal about keeping your content separate from the way it's presented?

The two main benefits are these. First, you or whoever is responsible for creating and managing your content (the important part) can do so without having to worry too much about how it will ultimately be presented (the pretty part) on a web site. Let's not forget that content is king. You should be updating your content regularly if you want to keep your web site smelling fresh. That becomes a lot easier when you don't have to think about adding or updating standard headers, footers, menus, breadcrumb trails and other common page elements.

The second important benefit is that you (or your web designers) can concentrate on making your content look beautiful, without having to worry too much about what the content actually is. Not only does this make the initial design process easier in the short term, it also has important ramifactions for the long term future of your site. When you want to update the look and feel of the web site a few years down the line, it's a relatively simple matter of coming up with a new design and writing some templates to apply it to your existing content. Thus, you can also keep your web site looking fresh.

In my experience, the single biggest problem that afflicts most web sites is that they're difficult to maintain. Anyone who knows how to "point and click" can build a web site using one of the wide range of desktop applications available these days, and anyone with a reasonable sense of design can build one that also looks half decent.

However, designing and building a web site should just be the first stages of many in the overall life-cycle of a web site. Far too often the basic site content is inextricably tied into whatever presentation style is chosen at the time. Giving the site even a minor face-lift at some point in the future effectively means a complete re-write of the site. All of your valuable content must then be updated, a process which becomes ever more laborious and error prone as your web site grows.

Cascading Style Sheets

Top Close Open

The use of CSS goes a long way to alleviate the problem. It allows us to create our content using semantic markup where tags embedded in the document indicate what the words are describing in "human terms" (e.g. this is the name of a product) rather than how the words should be displayed (e.g. black 14 point Helvetica font).

Semantic HTML Markup

Top Close Open

Here's an example of some HTML that uses semantic markup tags.

<div class="product">
  <h1 class="name">Deep Frobulator Widget</h1>
  <h2 class="code">XYZ123</h2>
  <div class="info">
    The XYZ123 Deep Frobulator Widget is the most powerful
    Frobulator available today!
  </div>
<div>

You don't need to be an expert in HTML to at least have a guess at what some of the the above means. The <div>...</div> blocks indicate where the content is sub-divided into component parts. Here we have a product division (div) containing two headings (h1 and h2) and a further division. The class="..." attributes that appear in the tags tell us that we're looking at a product with a name, code and an informative description.

When a web browser goes to display the page, it uses the CSS stylesheet declarations to figure out how to display each item. It is through CSS that we provide the mapping from semantic terms like "product name" to particular presentation styles.

Mapping Semantics to Style

Top Close Open

Here's a simple example of a style sheet that defines how the basic HTML from our previous example should be displayed.

div.product {
    margin: 4px;
    border: 1px solid #ddd;
}

div.product h1.name {
    font: bold 16px Arial, Verdana, Helvetica, sans-serif;
    margin: 4px 2;
}

div.product h2.code {
    font: bold 14px Arial, Verdana, Helvetica, sans-serif;
}

div.product div.info {
    font: bold 12px Arial, Verdana, Helvetica, sans-serif;
    margin: 0 10px;
}

There are plenty of tutorials and references on the web for learning more about CSS if you're interested in doing so. For now, all you really need to know is that the above stylesheet defines a series of rules that conform to the following format:

what-to-display {
    how-to-display-it
}

The what-to-display is typically something like div.product h1.name which selects any <h1 class="name">...</h1> tags inside a <div class="product">...</div> tag.

The how-to-display-it breaks down into a series of property: value; declarations such as font: bold 16px Arial, Verdana, Helvetica, sans-serif; to set the font weight, size and typeface, or margin: 4px 2px; to set a 4 pixel vertical margin above and below the item and a 2 pixel horizontal margin on either side.

The good news is that support for CSS in web browsers in now very good. The bad news is that the CSS functionality in the most widely used browser, Microsoft's Internet Explorer, is badly broken. However we do know how to work around most of the problems using various special "fixes" to cope with the fact that IE disregards the standards that the rest of us follow and instead does its own thing.

But the best news of all is that you can download Firefox, a far superior and entirely free web browser and start using it right away. It's available for a wide range of platforms (Windows, Mac, Linux, etc) and is fully standards compliant, as well as having a number of cool features that IE lacks.

The Template Toolkit

Top Close Open

As wonderful as CSS is in liberating web designers from table based layouts and markup peppered with <font> tags, it is still only part of the solution. You still need to add the relevant semantic markup for headers, footer, menus and other user interface components to each of your pages. The process of writing the markup itself may have been simplified by CSS, but you still have to go and modify each page if you want to add a new item to the main menu, change the copyright message, or perform any other kind of regular maintenance.

The Template Toolkit (TT), and more generally the template-driven approach that it employs, provides a solution to this problem. It allows you to keep the files that make up the basic content for your web site entirely separate from the templates that present it in the style of your choosing, complete with the usual array of headers, footers, menus, and other bits that make up the user interface. These chunks of markup can be separated into reusable components that allow you to build your web site up rather like a jigsaw puzzle. You can change any piece of the puzzle at any time (assuming that you have another metaphorical piece of the right shape) without needing to paint the whole picture again from scratch.

Template Components

Top Close Open

Here's an example of what a template looks like.

<div class="product">
  <h1 class="name">[% name %]</h1>
  <h2 class="code">[% code %]</h2>
  <div class="info">
    [% info %]
  </div>
<div>

Does it look familiar? It should - it's the same HTML fragment we used in the earlier example. The only different is that we've replaced the specific values for the product name, code and description with generic tags that we can later define to be anything we like.

We can use this template component (which we'll assume is called product_info) to insert the details of a particular product into a web page. Like so:

[% INCLUDE product_info
     name = "Deep Frobulator Widget"
     code = "XYZ123"
     info = "The XYZ123 Deep Frobulator Widget 
             is the most powerful Frobulator 
             available today!"
%]

The great thing is that you can use it over and over again for different products. If you ever want to change the way a product is displayed, say by adding the price to the displayed details, then you just need to change that one template.

Don't Repeat Yourself

Top Close Open

The same principle can be applied to almost every part of your web site. Wherever you have something that is used in more than one place, move it into a separate template component and INCLUDE it into the different places where it is required.

For example, instead of repeating the site menu on every page, put it in a separate menu template and INCLUDE it into every page that uses it.

[% INCLUDE menu %]

<p>
  Your content here...
</p>

Now if you need to add a new item to the menu, you only need to do it in one place - in the menu template component file.

The Don't Repeat Yourself principle doesn't only apply to large chunks of markup that you can move into separate reusuable template components. The use of variables (those generic tags like [% name %] that we mentioned earlier) inside the template allow you to "soft-code" anything that you might want to change at a later date.

Here's another example where we replace the font declarations in the CSS file with Template Toolkit variables.

[% size = 14
   face = 'Arial, Verdana, Helvetica, sans-serif'
%]

div.product {
    margin: 4px;
    border: 1px solid #ddd;
}

div.product h1.name {
    font: bold [% size + 4 %]px [% face %];
}

div.product h2.code {
    font: bold [% size + 2 %]px [% face %];
}

div.product div.info {
    font: bold [% size %]px [% face %];
}

Where this approach really comes into its own is when you want to customise the way the content is presented to account for branding, localisation, user preferences, and so on. You can take the same basic content and turn it into a dozen different versions of the same web site. All you need to do is set the appropriate variable or tweak the relevant template to change that part of the jigsaw puzzle.

Keep Simple Things Simple

Top Close Open

In our earlier example we created a menu component which we can reuse by loading it into any web page with an INCLUDE directive.

The chances are that you'll want more than just a menu at the top of each page so you'll probably want to create a header and footer template to use like so:

[% INCLUDE header %]

<p>
  Your content here...
</p>

[% INCLUDE footer %]

Within the header template you can add whatever markup you like, and insert the approriate INCLUDE directive to load the menu into place. Templates can call on other templates which can call on other templates and so on. This allows you to build your web site in an entirely modular fashion.

An alternative to having separate header and footer files is to combine the two into a wrapper template and use the content variable to indicate where you want to core content to go. For example:

<html>
  <head>
    <title>[% title %]</title>
  </head>
  <body>
    <div id="header">
      [% INCLUDE header %]
    </div>

    <div id="content">
      [% content %]
    </div>

    <div id="footer">
      [% INCLUDE footer %]
    </div>
  </body>
</html>

Note how we're combining this with the use of semantic div elements so that we can style the header, content and footer element accordingly using CSS.

The Template Toolkit allows you to specify a standard set of headers, footers or wrappers that get added to every page. If we tell it to automatically wrap each page with our wrapper template then we can reduce our source pages to containing the core content only.

<p>
  Your content here...
</p>

This kind of approach allows you to keep your core web site content files blissfully free of any additional markup required to add the various user interface components to the pages. Simply point TT at your content directory and tell it to build your web site with all the shiny bits added on. If you change the content or one of the shiny bits then simply have TT do it again while you site back and take a slurp of coffee. The ttree tool (part of the TT distribution) is your friend here:

$  ttree --src=/path/to/content --lib=/path/to/components --dest=/output/path --wrapper=template --verbose

Web Applications

Top Close Open

You can also tie the Template Toolkit engine into a web site that generates its pages on-the-fly (or dynamically as we say in the business, in contrast to static pages that are served up exactly the same to everyone). This allows you to generate web pages from records in a database, or as the front-end to a web application framework like Catalyst. This makes it ideal for product catalogues, e-commerce solutions, and any kind of web application where a high degree of flexibility is required in terms of how easily pages can be adapted and customised when displayed.

Once again, a clear separation of concerns is important. Our application framework handles the server requests and responses. Our application business logic performs whatever processing tasks are required. The data abstraction layer hideas away the messy details of talking to the database, mapping database records to application objects and back again. Finally, our presentation layer (i.e. the Template Toolkit) takes the results of whatever processing occured and turns it into a pretty HTML page.

In the Web Application Framework world, you'll often hear this described as the Model-View-Controller (MVC) pattern, but I personally think it goes a little deeper than that.

The Inventor's Paradox

Top Close Open

I hope this article has given you some insight into why achieving a clear separation of concerns is about much more than keeping up with the latest fad. It's not about using CSS or TT or any other technology in particular. It's more to do with the architecture of your site and the way you go about building it than the particular tools or materials you employ.

The essential thing is to split the big issue of designing, developing and maintaining a web site into a series of smaller, simpler issues that fit together neatly. Your content is one thing. Your presentation style is another. If you're using a database or web applications, then they're different things too. Keep them as separate things and treat them as separate things.

This is the essence of the Inventor's Paradox. It's usually easier to solve three small problems than one big one. Break a complex system into a series of simple systems and tackle each in isolation. It might sound like more work to maintain three systems instead of one, but trust me, you'll save yourself a lot of time and effort in the long run.