Apache VCL logo Apache Software Foundation logo



Custom themes can be created in VCL for each affiliation. This allows a multi-site installation of VCL to have themes that match each affiliation's primary web site theme. When a user logs in, the site will be displayed using the theme specified for that user's affiliation. Additionally, when using LDAP authentication, the login page for the affiliation will be displayed with the theme matching that affiliation.

File system structure

The themes are in a themes directory in the web code. If you installed your web frontend under a directory named vcl, you would look in vcl/themes. Each VCL release comes with a default theme, which you should see at vcl/themes/default. Typically, you would set up the following directory structure for a new theme:

The page.php file and css directory are the only ones that are required. After creating the directory structure, you will need to go to the themes directory and run the copydojocss.sh script, passing it the name of the directory containing your new theme as an argument:

cd vcl/themes
./copydojocss.sh mynewtheme

VCL HTML generation

There are a few parts to how VCL generates the HTML for any given page. There are some important functions of which to be aware. The first two must be in the page.php file:

These are functions that exist in utils.php that are available to be called from getHeader and getFooter:

Understanding page.php

As noted above, this file must contain getHeader and getFooter. getHeader must contain these elements, all of which can be seen in the default theme's page.php file:

getFooter must contain these elements:

Path references

There are a few things to keep in mind with respect to path references. From a web browser's perspective, all HTML generated by getHeader and getFooter will be part of the vcl/index.php file. So, any paths referenced in getHeader and getFooter need to be relative to that - example: <img src="themes/mynewtheme/images/someimage.png">. Any files referenced in css files in the theme's css directory will be relative to that css file. So, if you were to include a reference to an image in the theme's image directory in a css file in the css directory, you would reference it relative to the css directory - example: url(../images/someimage.png)

Example: bare minimal theme

This example shows the bare minimum that must be included. For a more detailed example, look at the default theme include in each release. We'll call the theme "minimal". First, we create a directory under the themes directory for it:

mkdir vcl/themes/minimal

Next, we create a css directory and run the copydojocss.sh script:

mkdir vcl/themes/minimal/css
cd vcl/themes
./copydojocss.sh minimal

Now, we create vcl/themes/minimal/page.php with this content:

function getHeader($refresh) {
    global $user, $mode, $authed, $locale, $VCLversion;
    $rt  = "<!DOCTYPE html>\n";
    $rt .= "<html>\n";
    $rt .= "<head>\n";
    $rt .= "<title>VCL</title>\n";
    $rt .= "<link rel=stylesheet type=\"text/css\" href=\"css/vcl.css\">\n";
    $rt .= "<link rel=stylesheet type=\"text/css\" href=\"themes/minimal/css/minimal.css\">\n";
    $rt .= "<script src=\"js/code.js\" type=\"text/javascript\"></script>\n";
    $rt .= "<script type=\"text/javascript\">\n";
    $rt .= "var cookiedomain = '" . COOKIEDOMAIN . "';\n";
    $rt .= "</script>\n";
    $rt .= getDojoHTML($refresh);
    $extracss = getExtraCSS();
    foreach($extracss as $file)
        $rt .= "<link rel=stylesheet type=\"text/css\" href=\"css/$file\">\n";
    $rt .= "</head>\n\n";
    $rt .= "<body class=minimal>\n\n";
    $rt .= "<div id=menulist>\n";
    if($authed) {
        $rt .= "<ul>\n";
        $rt .= getNavMenu(1, 1);
        $rt .= "</ul>\n";
    $rt .= "</div>\n";
    $rt .= "<div id=content>\n";
    return $rt;

function getFooter() {
    $year = date("Y");
    $rt  = "</div>\n";
    $rt .= "</body>\n";
    $rt .= "</html>\n";
    return $rt;

Finally, we create a basic css file at vcl/themes/minimal/css/minimal.css:

#menulist {
    float: left;

#content {
    margin-left: 15em;

Using a new theme

Themes are assigned on a per-affiliation basis in the affiliation table. This must be done directly in the database by setting the affiliation.theme field for an affiliation to the name of a theme in the themes directory. For example, to use our new minimal theme, you would set affiliation.theme to minimal for the desired affiliation.

Tips and Tricks

The VCL web site has some administrative pages that can generate very large tables. If you want them to be completely wrapped in your theme, you will probably need to use tables as part of you main layout instead of just using div elements and css. (Hopefully, all of those large tables will be converted to dojo grids like the Manage Groups page by the 2.4 release.)

Mobile themes - If you would like to use a modified theme for mobile devices, you can add a section of code to the top of getHeader and getFooter that detects mobile devices based on $_SERVER['HTTP_USER_AGENT']. If a mobile browser is detected, you can then call a different function that generates mobile specific HTML and returns it to the calling function. Here is an example that could be used in getHeader:

if(array_key_exists('HTTP_USER_AGENT', $_SERVER) &&
     (eregi('iphone', $_SERVER['HTTP_USER_AGENT']) ||
     eregi('android', $_SERVER['HTTP_USER_AGENT'])))
   return mobileHeader($refresh);

mobileHeader would still need to meet all of the requirements of getHeader, but it would just generate mobile specific HTML. A similar block of code would then be added to getFooter, calling a function named something like mobileFooter.