Composum Blog

various aspects of the Composum world

The power of the ‚Themes‘

'Themes' allow partial redesign of existing components and content without changing data

Components consist of server-side logic (model implementations, render templates) and client-side functions (Javascript) and style. The implementation is done on the server side as Sling components and on the client side via client libraries.

Each Sling component implemented in this way defines a resource type that is referenced by the content elements, i.e. the content resources. This data of the CMS thus receives its respective function. In order to adapt this function to changing requirements without always having to create new components and modify the content, a 'theme' can be used to partially or completely change the implementation of a set of components without having to change the content of the CMS. A 'Theme' can also be assigned to an area in the page hierarchy that wants to implement the same components differently.

Ralf Wunsch
17.06.2021

The 'book' theme of the Pages Components will serve us as an example of a theme implementation. This simple theme implementation adds an additional navigation bar on the left side of a standard content page like the table of contents of a book - here the table of contents of the area of a website configured with the 'book' theme.

The theme resource

Like a component, a theme is a resource in the search path of the resource resolver. As with components, themes can have their implementation in /libs overlaid by paths of the same name in /apps.

A theme itself consists of sets of overlays for

  • resource types
  • page templates
  • clientlib categories

which are defined below the theme resource. The theme resource itself as the root element of the theme is of node type 'cpp:Theme'. Components, client libraries and page templates are arranged in a freely selectable structure below it.

In our example, the 'Book' theme, there are overlays below the theme resource

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cpp="http://sling.composum.com/pages/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="cpp:Theme" jcr:title="Composum Pages Components Book Theme" jcr:description="a theme to navigate through a more complex set of content pages"> </jcr:root>

for the 'content' page component and the default client library of the Pages Components.

The ‚book‘ Page-Component

The page component of the 'book' theme

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:sling="http://sling.apache.org/jcr/sling/1.0" jcr:primaryType="sling:Folder" sling:resourceSuperType="composum/pages/components/page" overlays="[^.*/components/page(/home)?$]"> </jcr:root>

overlays the default page component and the homepage component of the Pages Components and is itself derived from the default page component. The overlay is specified by the regular expression for the resource type to be overlaid in the 'overlays' property (Multi-value).

The resource types overlaid in this way are replaced dynamically during rendering by the resource type from the theme for the content areas to which the 'book' theme is assigned. The content elements themselves continue to refer to the original resource type, so they remain unchanged.

By deriving the theme component from the standard page component, it is sufficient here to merely adjust the rendering of the page content

and thus provide for the additional rendering of the navigation on the left side ('book' table of contents). At the same time, the request attribute 'NARROW_MAIN' is used to provide all components with a hint that the content area of the page is narrower than usual in the context of the theme. The Row component from the Pages Components then adjusts the responsive rendering of the columns slightly.

The 'content.jsp' rendering template of the default content page is replaced by this implementation in the page component of the 'book' theme for each corresponding content page configured with the 'book' theme without modifying the resource type in the content itself.

The ‚book‘ Clientlib

The client-side implementation of the components can be customized in the theme by overlaying the corresponding default clientlibs of the pages to be changed.

In our example, the 'book' theme, only extensions to the styles for the additional navigation and related Javascript functions for the responsive behavior of the navigation elements are added.

A new clientlib is defined for the 'book' theme, which overlays and inherits the default view clientlib of the Pages Components.

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="sling:Folder" sling:resourceType="composum/nodes/commons/clientlib" jcr:description="the Components clientlib for the Book theme of the common components" category="[composum.pages.components.book]" overlays="[^composum\\.pages\\.components\\.view$]"> <css jcr:primaryType="nt:unstructured" depends="[category:composum.pages.components.view]" embed="[composum/pages/components/themes/book/components/page/css/page.css]"/> <js jcr:primaryType="nt:unstructured" depends="[category:composum.pages.components.view]" embed="[composum/pages/components/themes/book/components/page/js/page.js]"/> <link jcr:primaryType="nt:unstructured" depends="[category:composum.pages.components.view]"/> </jcr:root>

Analogous to the components, overlaying is done the regular expression for the clientlib categories to be overlaid in the 'overlays' property (multi-value). The different aspects of the clientlib (css, js, link) derive with 'depends' from the overlaid clientlib and add the assets of the 'book' clientlib in the respective 'embed' property.

Overlaying templates is also possible in a theme. In our example, there was no use for it.

Powerful and useful

Any aspect of a component (render templates, edit dialog, toolbar, tile,...) can be customized by the overlaying component in the theme. A theme can be a separate project with any number of overlays of components, templates and clientlibs.

A theme can be used to efficiently modify the functionality, appearance and structure of existing content components. One and the same component can thus behave completely differently. The edited content remains completely unchanged.

Each content page can reference such a theme.

These references are inherited by subpages. In this way, individual areas of a website can be given completely different properties with basically the same content.