There are many ways to organize templates – you can re-use existing ones or you can use one template at a time.

Re-using sub-templates

To avoid repeating lots of code, you can put different building blocks of your website together in templates. You can re-use different parts to make template building less redundant.

Templates can include other templates. This allows you to define page elements like HTML-head metadata or headers and footers in one central file. The following code shows how include parts of a page into one page, so that HTML-head metadata and a footer are defined in a separate file:

First of all, we create a new include-htmlhead.vm file and add some meta info and static resource imports:

include-htmlhead.vm

<meta name="Description" content="$page.description">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<link href="${theme.baseUrl}/css/main.css" rel="stylesheet" media="all" type="text/css">

<title>$page.title - Company Name</title>
HTML/XML

Secondly, we create a new include-footer.vm file for defining the content of a footer. As content, we simply create a link to the homepage of the TEST space:

include-footer.vm

<footer>
	<a href="$link.to.space("TEST")">Link_to_TEST_Space</a>
</footer>
HTML/XML

Finally, we can include the newly created files in our page.vm file

Modified default.vm

<!DOCTYPE html>
<html>
	<head>
		<title>$page.title</title>

		$include.template("include-htmlhead.vm")
	</head>
	<body>
		$page.content

		$include.template("include-footer.vm")
	</body>
</html>
HTML/XML

Using a main layout with include templates depending on page properties

This is what we do on the k15t.com website. To avoid repeating the same HTML boilerplate over and over again, you can use one template – page.vm – as the main layout for other pages. Elements like header, navigation, styles and metadata will be coded only once and populated using content/page properties.

page.vm

<!DOCTYPE html>
<html lang="en">
<head>
    <title>$page.title</title>
</head>
<body>
    <header>
		<span class="title">K15t Software</span>
	</header>
	<main>
		#if ($isError)
            $include.template("templates/common/error.vm")
        #else
            #if($isBlogOverview)
                $include.template("templates/blog/overview.vm")
            #elseif($page.properties.contentTemplate)
                $include.template($page.properties.contentTemplate.asText)
            #elseif($isPage)
                $include.template("templates/content.vm")
            #end
        #end
	</main>	
</body>
</html>
XML

As you can see above in the code, we use $page.properties.contentTemplate to decide what template to include. This requires a page property macro with a table, which contains a row with contentTemplate filled in. The table can be used as key-value storage you can access in your velocity files.

This typically looks like this, if correctly implemented:

Of course you can also store other data there.

As you can see in the elseif($isPage) block, we include a generic content.vm which will output the page title and the $page.content if no contentTemplate is present.

content.vm

<article>
    <header>
        <h1>$page.title</h1>    
        <span class="author-info">Written by $page.creator.username</span>
    </header>
    $page.content
</article>
XML

Related recipes

The error template can be used to display errors, while the blog overview is used to show a list of articles if the blog setting is enabled.