SilverStripe 2.4: Creating our Own Theme


SilverStripe 2.4 Module Extension, Themes, and Widgets: Beginner's Guide

SilverStripe 2.4 Module Extension, Themes, and Widgets: Beginner's Guide

Create smashing SilverStripe applications by extending modules, creating themes, and adding widgets

        Read more about this book      

(For more resources on this subject, see here.)

We assume a good understanding of HTML/XHTML and CSS as well as a basic knowledge of JavaScript and image editing. A solid understanding of PHP with a focus on object-orientation is also highly recommended.

If you want to improve on your PHP and object-orientation coding, you might want to take a look at Hasin Hayder's book Object-Oriented Programming with PHP5 (published by Packt Publishing, ISBN 1847192564).

Time for action - files and folders for a new theme

We could start off from scratch, but let's not make it more complicated than necessary:

  1. Simply copy the BlackCandy theme to a new folder in the same directory. We'll just call it bar as the page should be for a bar business.
  2. Now reload the CMS backend and you should be able to switch to the new bar theme.
  3. As we won't use any of the available images we can delete all image files, but leave the folder intact—we'll add our own pictures later on.

Basic layout

Next, we'll create our page's general layout. Time to put our template skills into action!

Here's the basic layout we want to create:

So far it's a pretty basic page. We'll take a good look at the templates and basic structure but won't spend much time on the HTML and CSS specifics. Do, however pay attention on how to set up the different CSS files to make the most out of them.

We won't list every line of code involved. If you'd prefer, you can simply copy the missing parts from the code provided here (Ch:2)

File themes/bar/templates/

This page is pretty empty. We'll later add an intro page with a different structure, so the code these templates will share is rather limited.

Time for action - the base page

Add the following code to the file themes/bar/templates/

<!doctype html>
<html lang="$ContentLocale">
<meta charset="utf-8"/>
<% base_tag %>
<% if MetaTitle %>
<% else %>
<% end_if %>

<link rel="shortcut icon" href="favicon.ico"/>
<!--[if lt IE 9]>
<script src="">
<b>Please activate JavaScript.</b><br/>
Otherwise you won't be able to use all available functions

What just happened?

The highlighted parts are SilverStripe specific:

  • First, we set the language of our content. Depending on what you've selected during the installation process this can vary. By default, it will be:

    <html lang="en-US">

  • Setting the page's base; this can be useful when referencing images and external files. Depending on how you set up your system this will vary.
  • Setting the title just like in the BlackCandy theme.
  • Next, adding meta tags without the title element. These are only set if you actually enter them in the CMS on the Metadata tab on the desired page's Content tab. Empty fields are simply left out in the output. Only the SilverStripe note is set in any case.
  • Finally, including the page's specific layout.

The JavaScript we include for Internet Explorer versions before 9 fixes their inability to correctly render HTML5 tags. To learn more about the specific code, head over to

Why HTML5?
The motivation behind it isn't to stay buzz-word compliant. While HTML5 is not a finished standard yet, it already adds new features and makes the development a little easier. Take a look at the doctype declaration for example: that's much shorter than XHTML. Now there's a real chance of actually remembering it and not needing to copy it every time you start from scratch. New features include some very handy tags, but we'll come to those in the next code sample.

The output on the final HTML page for the second and third elements (we've already taken a look at the first) in the header looks like the following listing. Which part in the template is responsible for which line or lines?

<meta name="generator"
content="SilverStripe -" />
<meta http-equiv="Content-type"
content="text/html; charset=utf-8" />
<meta name="keywords" content="some keyword" />
<meta name="description"
content="the description of this page" />

Did you notice that there is no reference to a CSS file and the styling is still applied? Remember that CSS files are automagically included if you stick to the naming convention we've already discussed.

File themes/bar/templates/Layout/

Now let's move beyond the basics and do something a bit more interesting.

Time for action - the layout page

Add the following code to the file themes/bar/templates/Layout/

<img src="$ThemeDir/images/background.jpg" alt="Background"
<section id="content" class="transparent rounded shadow">
<aside id="top">
<% include BasicInfo %>
<% include Menu %>
<section class="typography">
<% include Footer %>

We rely on just three includes which are very easy to reuse on different pages.

We then reference the page's content and possible forms (no comments will be required).

The only template part we've not yet covered is the $ThemeDir. This is replaced by the path to our theme, in our case themes/bar/. So you don't need to worry about hard-coded paths when copying template files between different themes. You only need to take care of paths in the CSS files as they are not processed by the template engine.

The includes:,, and

In the previous code segment, we've referenced three includes. Let's not forget to create them.

Time for action - the includes

The includes we're yet to explore are,, and

  1. The menu is very simple, we only include the first level, highlighting the currently active item, as we won't have more subpages:

    <nav id="menu">
    <% control Menu(1) %>
    <li class="$Linkingmode">
    <a href="$Link">$MenuTitle</a>
    <% end_control %>

  2. only contains the $ThemeDir placeholder besides good old HTML:

    <a href="home">
    <img src="$ThemeDir/images/logo.png" alt="Logo" id="logo"/>
    <ul id="details-first">
    <li>Phone: <b>01 23456789</b></li>
    <li>Contact: <a href="contact"></a></li>
    <li>Address: <a href="location">Bar Street 123</a></li>
    <div id="details-second">
    <div class="left">Opening hours:</div>
    <div class="right"><p>
    <b>Mon - Thu 2pm to 2am</b><br/>
    <b>Fri - Sat 2pm to 4am</b>
    <a href="">
    <img src="$ThemeDir/images/facebook.png" alt="Facebook"

    Be sure to replace with your own domain. However, using it here is quite fitting because we're making a page for a bar and is only a placeholder itself. It's derived from foobar or foo bar, a placeholder name often used in computer programming. But take a look at the site yourself for more information.

  3. Finally, the footer makes use of the $Now placeholder and the date formatter .Year to retrieve the current year:

    <span><a href="imprint">Imprint</a></span>
    <span>&copy; Bar $Now.Year</span>

Have a go hero - create the layout and pages

Now that we've gone over all of the content, it's time to build the page. Feel free to copy some code as we're not a typing class, but take careful note of every SilverStripe specific part, so you understand what you're doing.

We use three includes, so create these files and remove the rest still available from BlackCandy as well as the unused templates/Layout/

And don't forget to flush the cache by appending ?flush=all to the page's URL! When working with includes it will save you a lot of trouble.

We've hardcoded some links to different pages in the template files. Make sure you add all necessary pages including the imprint, but don't add it to the menu.

        Read more about this book      

(For more resources on this subject, see here.)

What's next?

Now that we've created our general content page, we can already do quite a lot using the CMS:

  • Write an interesting Home and About Us page
  • Provide all the necessary information for the Imprint and how to Contact Us
  • Advertise the program and daily specials of your bar
  • List all your drinks and cocktails in a table

Let your creativity run free and start working with our project!

Not finding the #*?~^ error?

When you are creating your own theme, you're bound to make mistakes so don't panic.

For example, if you write <%control Menu(1) %> in your template (note the missing space before control), your error message will look something like this:

While it clearly points to the correct file, the } and line number are puzzling as templates/Layout/ does not contain any curly braces nor is it anything like 52 lines long.

Remember that the template engine replaces the control code with plain PHP. So if there is an error in the template, the resulting PHP code is not correct. The web server, trying to interpret it, spits out this error message relating to the PHP code.

In order to see the PHP code generated from the template, attach ?isDev=1&showtemplate=1 to the current URL. If you're not already logged in, you'll be prompted to do so. This is a quick helper like flushing the cache. It forces the page into development mode and shows the generated template code:

By taking a quick look at the result you'll see multiple SSVIEWER replacements representing the interwoven PHP statements and in our specific case:

35 <ul>
36 <%control Menu(1) %>
37 <li class="

So there's a control structure which hasn't been replaced. There must be something wrong here!

The actual error is caused by the closing { on line 52 (being the replacement for the <% end_control %>) as the opening } doesn't exist. This should make it easy to figure out the problem.

So for debugging ?isDev=1&showtemplate=1 is your best friend, use it before poking in the dark.

Adding interactive features

While we've created the basic layout, the site is a bit static. To make it a little more interactive, we'll allow visitors to easily share a link to our page on Facebook and Twitter. There are JavaScript libraries for easy integration, but without scripting enabled they don't work at all. Additionally, we don't want to rely too much on external code. So for full control we had better roll our own sharing service.

Twitter and Facebook both follow a rather simple schema for sharing content: link to a specific page of the social network, provide the current URL as a parameter, and that's it. Once a user clicks on such a link, they must log into their social network's account and can then share the URL, optionally adding more text at their liberty.

Time for action - let users share our page on Facebook and Twitter

Let's integrate these links into our templates. We'll use another include for optimal flexibility:

  1. Create a new include template called (Don't forget that includes are located in themes/bar/templates/Includes/):

    <aside id="share" class="rounded">
    <a href="{$AbsoluteLink}"
    class="twitter" target="_blank">Twitter</a>
    <a href="{$AbsoluteLink}"
    class="facebook" target="_blank">Facebook</a>

  2. Reference it in the themes/bar/templates/Layout/ file just below the menu. That's also where we want to place it in the final layout, on the left-hand side in the content area's bottom left corner:

    <div><img src="$ThemeDir/images/background.jpg" alt="Background"
    <section id="content" class="transparent rounded shadow">
    <aside id="top">
    <% include BasicInfo %>
    <% include Menu %>
    <% include Share %>
    <section class="typography">
    <% include Footer %>

  3. Flush the page (?flush=all but you know that already) and you should now see a new element on your page. For the screenshot, some CSS has been added along with images to pep it up a little, but regular text links will accomplish just the same.

    SilverStripe 2.4: Creating our Own Theme

The only remaining question is, in which file should you add the CSS and into which folder should you save the images? We'll cover that right in the next section.

What just happened?

Without going into too much detail on the Twitter and Facebook APIs: is the address for sharing content on Twitter. Using the status parameter you can add some text to the message, in our case the URL. But we need the complete address, including the http:// for the services to know what we mean. And that's exactly what $AbsoluteLink provides. So the raw output of our include could be:

<aside id="share" class="rounded">
<a href="
contactus/" class="twitter" target="_blank">&nbsp;</a>
<a href="
contact-us/" class="facebook" target="_blank">&nbsp;</a>

The curly braces in the template are not strictly needed in this case and are automatically removed as they delimit a placeholder. They only help the template engine to determine where the placeholder really starts and ends. In order to avoid confusion, you should always use them when a placeholder isn't delimited by spaces.

Assume you have a placeholder $Filename that gets you a filename, but as the extension is always PNG you simply add that in the template, leaving you with $Filename.png. In this case the curly braces will be mandatory as the template engine would think you have an object Filename and want to access its attribute png. {$Filename}.png will be the solution in this case. Don't save on curly braces, they do no harm and improve readability for yourself and SilverStripe.

Coming back to our earlier questions:

  • layout.css is the right CSS file to use for this styling as it's used in the general layout and is not needed in the CMS
  • Images should be added to themes/bar/images/ or possibly a subfolder


        Read more about this book      

(For more resources on this subject, see here.)

Taking care of search engines

Now that we can create dazzling layouts, it's time to consider how users can find our page. We'll only cover aspects concerning SilverStripe—if you're interested in every detail of the topic, get a book dedicated to search engine optimization (SEO).

The most important rule for getting good results in search results is that content is king. Focusing on the substance of your page gives you a strong base to build upon. After that, you can further improve it.

Semantic HTML

The structure of your content is important. Use the right tags to give the correct meaning (semantics) to your information. This enables machines, specifically search engines, to easily understand it. For example, use <h1> for the main heading of your page, <h2> for subheadings, and so on. Don't leave a level out or build your own formatting rules with <div class="h1">. SilverStripe's WYSIWYG editor makes it easy to use the right markup.

How does the CMS know how to style our headings? By adding that information to typography.css we've automagically added it to the CMS as well. If you put all your styling information into layout.css, you won't be able to benefit from that convention.

Meaningful URLs

Use human-readable URLs, for example, /contact instead of /index.php?pageid=12. On the one hand search engines value the word "contact", so if someone searches for a contact page and your brand, you have a better chance of being found. On the other hand you might be penalized for using URL parameters as you can provide the same content only with different advertising or layout.

If your web server's configuration permits it, SilverStripe will always default to using human-readable URLs, using the page's title to generate a unique URL, but you can of course change it.

Broken links

Neither search engines nor users will appreciate it if you have broken links on your page.

If internal links within a WYSIWYG area are broken, SilverStripe will mark them with a red background. Additionally, you can use the broken links report of your installation under the URL /admin/reports/, to see if there are any.

If you link to external pages or use hardcoded links in your template (as we did before), you'll need to use an external tool such as

When you're using the built-in page selector for setting up internal links, you're not linking to a specific URL but actually to a page ID. So even if you manually change the URL of a page, links are automatically updated. You don't need to change them by hand.

Duplicate content

If you want to use the same page in multiple places of your site, use the page type Redirect Page or Virtual Page for actually mirroring it.

A redirect page returns a HTTP status code "301 Moved permanently" and should be the preferred method. This also frees you from making changes in multiple places.

Meta tags

Search engines won't pay too much attention to meta tags as they have been widely abused in the past. The most important one is the description as most search engines use it as the teaser text in the result list. If no description is found some text is grabbed from the page and used instead, producing varying results. Remember that you can enter this information in the CMS or place it in the template.


Your website should follow the specifications for the HTML5 and CSS3. This will help both the browsers to display your content correctly, and search engines to interpret it the way you intended. For example, if you don't close a heading, it must be guessed what should be included and what not. Don't leave a machine guessing at the right interpretation of your messy code.

SilverStripe enables you to write validating code. Regularly check it with a validator—for example, using or a browser plug-in.


A sitemap is an XML file, telling search engines which pages exist on your site, when they were last changed, and how important they are. This was first introduced by Google but more or less every other search engine has adopted the same system.

We've already discovered the Google sitemap module while taking a look at the file structure; it's included and activated by default. In order to view the XML data generated by it go to the page /sitemap.xml in your installation. Just like any other page in your system there is no concrete file for it, it's generated by the system on the fly. We'll discuss the details of that later.

To exclude a page from the index (a search engine will then completely ignore the page) or change the importance of a page, go to the Google Sitemap tab on the desired page's Content tab.


We've learned a lot in this article about templates:

  • Building our own theme which we can extend and hone—showing how easy that actually is with SilverStripe.
  • Debugging errors in templates—if you know how to do it, it's not really that hard.
  • How to enable users to interact with Facebook and Twitter on our page.
  • Finally, how to optimize your page for search engines.

We've also discussed some limitations and specific features of SilverStripe's template system.

Further resources on this subject:

You've been reading an excerpt of:

SilverStripe 2.4 Module Extension, Themes, and Widgets: Beginner's Guide

Explore Title