Building our own Plone 3 Theme Add-on Product

6 min read

(For more resources on Plone, see here.)

We can build our own theme add-on product from scratch. It can be done easily with PasteScript. Just type this on our command line from the root of our buildout:

$ cd src
$ paster create -t plone3_theme plonetheme.myintranet

Answer all the questions with the default option except for:

  • Skin Name: A human facing name for the theme, added to portal_skins, for example, MyIntranetTheme.
  • Skin Base: Name of the theme from which this is copied. By default, it is Plone Default. Answer the default option here.
  • Empty Styles?: If true, it will override default public stylesheets with empty ones. Answer False.
  • Include documentation?: If true, the generated theme will include auto- explanatory documentation, desirable for beginners.

The resultant theme add-on product will be generated in the src buildout folder. This add-on is completely usable right now, but it’s innocuous. Once installed, it will replace the original Plone default theme with the one in this package.

Installing the product

Just proceed as any other add-on product. However, since we are developing the product, we should specify it in our buildout by filling the develop directive in the buildout section and the eggs directive in the instance section in our buildout.cfg file:

develop = src/plonetheme.myintranet
eggs = plonetheme.myintranet

Go to the package folder, src/plonetheme.myintranet/plonetheme/myintranet, and edit the configure.zcml file. As we don’t want to define an i18n folder, delete the following line if it exists:

<i18n:registerTranslations directory="locales" />

And then, rerun buildout.cfg:

$ ./bin/buildout
$ ./bin/instance fg

Now, go to the Add-on Products control panel configlet and install it.

If we browse our site, we will notice that nothing has changed, because we’ve chosen to inherit the default theme in our new one. But, now the theme defined in our theme add-on product is in use in our site. Check it out in portal_skins:

Building our own Plone 3 Theme Add-on Product

Notice three things in the previous screenshot: the Default skin is our recently created skin and three additional Plone skin layers have been added to the top of the layer’s precedence order list. These three layers will contain the resources we may need for our new theme. These layers represent three folders inside our package structure; to be more precise, those inside skins folder:

Name of the layer/folder



It will contain our theme images.


It will contain our theme custom templates.


It will contain our theme styles.

In fact, this layer organization is merely for convenience, as all the layers can contain any type of resources.

Customizing Plone skin layer resources

As our theme product is positioning the new layers on the top of the precedence order, the elements we place in these folders will override those in layers with less precedence. Just place our custom resource in any of the layers defined by our product and name it as the original one. Our custom resource will override the default one. We can also place other resources we may use, such as our custom templates, images, and styles as well.

Enabling CSS debug mode

By default, the changes made to our product will not be available until we restart our instance. For the changes to take effect immediately, we should enable CSS debug mode in CSS resource registry. We will find this setting at the top of the portal_css ZMI view.

In debug/development mode, stylesheets are not merged to composites, and caching and compression of CSS is disabled. The registry also sends HTTP headers to prevent browsers from caching the stylesheets. It’s recommended to enable this mode during CSS-related development. Remember to turn it off again when we finish CSS modifications, as debug mode affects site performance.

Customizing the site logo

Plone renders the site logo combining two kinds of resources—the viewlet plone. logo provides the HTML structure needed and a Plone skin layer image. Let’s say we want to change the site logo and add an additional logo of our company containing a link to the corporate web besides it. We need to customize the original logo with the logo of our intranet and add the required HTML structure to add the new company logo besides the original one. We will need to customize the original logo and the plone.logo viewlet. Later, we will need to add our company logo as a new Plone skin layer image.

Customizing the logo image and adding a new one

We should override the original logo image with our customized one. In order to accomplish this, we should rename the image we’ve chosen to use as our site logo with the same name as the original one. The original logo image is called logo.jpg and it is located in the plone_images skin layer. We override it by simply placing our customized image inside skins/plonetheme_myintranet_custom_images and naming it exactly the same as the original one. Place the image for the second logo here too, and name it as company-logo.png.

Customizing the plone.logo viewlet

Customizing a viewlet is a little trickier than overriding skin layer resources. We will need to tell Zope that we want to override the original viewlet declaration by creating an overrides.zcml file in the plonetheme/myintranet folder of our custom add-on product, and add the attribute that tells Zope where to find the new template associated to this viewlet:


<!-- The new logo viewlet declaration -->
permission="zope2.View" />

Then place this Zope page template called in the browser folder of our add-on product:

<a id="portal-logo-company"
tal_attributes="href string:">
<img src="company-logo.png"
alt=" logo"
title=" logo"/></a>
<a metal:define-macro="portal_logo"
tal_attributes="href view/navigation_root_url"
<img src="logo.jpg" alt=""
tal_replace="structure view/logo_tag" /></a>

We leave the original logo template at the end of the file and add a new link tag with the structure for the new logo and the reference to the new Plone skin layer image (company-logo.png).

Restart our instance to see the changes applied. This is needed because we have overridden a viewlet defining an additional ZCML file.


Please enter your comment!
Please enter your name here