Server-Side Handlebars in AEM

There are many reasons you might need to use handlebars in Adobe Experience Manager. You might have a developer who is well versed in handlebars and wants to develop AEM components using handlebars. You might be migrating a site that was written in handlebars and don’t want to convert your scripts to Sightly just yet. You might have multiple teams running different CMS platforms but want to unify the HTML across all these platforms. You could write each of your components once in handlebars and distribute the handlebars script files to the different teams and you need AEM to support handlebars for your components. Whatever your reason, this article describes one way to accomplish using handlebars as the basis for your Adobe Experience Manager components.

The handlebars supertype
To get started, create a new AEM component that will serve as the supertype of all other handlebars components. In the Sightly .html file for this base component, simply use a data-sly-use attribute to instantiate a Java class in the OSGi container. This Java class will handle all of the hbs (hbs is the file extension type for handlebars) script resolution and compilation and expose the rendered HTML through a getter method in the class. A sample of the Sightly file could look something like this.

${dataProvider.html @ context='html'}

The nice thing about this approach is that there is nothing in the .html file that is specific to an individual component. As long as the Java class data provider can resolve a handlebars script that is specific to a component, this base .html file remains generic so that all Adobe Experience Manager components that use this base as their supertype won’t have to specify their own .html file.

Compiling handlebar scripts
Now that we have a base AEM component in Sightly, let’s move our focus to the main issue of handlebars script compilation. Rather than writing your own handlebars script parser from scratch, you can grab the latest version of the jknack project. jknack is a Java implementation of a handlebars compiler and licensed under Apache License 2.0. While the code from the Git repository isn’t OSGi-ready, you can either make it OSGi-ready or simply include the code directly in the OSGi bundle you are using for the Sightly data provider.


The code in the data provider class needs to resolve the correct hbs script template, compile it, construct a context object for jknack to resolve hbs variables in the script, and finally apply that context object to the compiled script to get the resulting HTML. Sample Java code in the data provider for the getHtml method could be:

ValueMap properties = getProperties();  // All of these getter methods come from the WCMUse class which this class is extending
ResourceResolver resourceResolver = getResourceResolver();
Component component = getComponent();

AEMTemplateLoader aemTemplateLoader = new AEMTemplateLoader(resourceResolver);

Handlebars handlebars = new Handlebars(aemTemplateLoader);

String hbsTemplateAsString = Utils.getHBSTemplateForComponent(component, resourceResolver);

Map dataStore = new HashMap();

// Add all properties of the current node for the handlebars script to consume
for (String propertyName : properties.keySet()) {
   dataStore.put(propertyName, properties.get(propertyName));

Template template = handlebars.compileInline(hbsTemplateAsString);

return template.apply(dataStore);

AEMTemplateLoader class
There are a couple lines in the above Java code that require a little further explanation. First, let’s discuss the AEMTemplateLoader class. If any of your hbs scripts use partials, jknack doesn’t know how to resolve the location of the partial script. AEMTemplateLoader is a helper class you’ll need to write that implements the TemplateLoadefr interface. Its only responsibility is resolving a script and getting its source based on the location in the parent hbs script. This can be done in many different ways, but one way is to pass the resource resolver from the Sightly WCMUse getResourceResolver method to the constructor of the AEMTemplateLoader so that the AEMTemplateLoader has access to the JCR and can resolve the partial script in the JCR.

The getHBSTemplateForComponent utility method
Next is the getHBSTemplateForComponent utility method. This particular implementation takes the component JCR node as well as the resource resolver to locate and load the hbs script template. A simple approach could be to look for a file in the JCR that is a child of the component node whose name matches the name of the component with a .hbs extension. Or you could have a property on the component node that specifies a path to the .hbs file. There are even more ways it can be done, but you should set it however makes the most sense for what you need. Once you have the JCR resource of the script file, you can read the contents of the file by adapting the resource to an InputStream by calling the adaptTo method on the resource and reading the data from the input stream.

Everything else in the sample Java class above should be fairly straightforward. By making this Java class generic as well, it allows the same Sightly .html file as well as the same data provider to be used by all handlebars components. For each Adobe Experience Manager component you create, you only need to place the hbs script template specific to that component in a location that the getHBSTemplateForComponent method knows where to look.

You might want to add additional things to this Java code such as design dialog properties to the data store object. You might have properties stored in subnodes in the JCR that the hbs script will need access to that you need to add to the data store object. There may be images or other complex data types that need special processing in the Java file, and you can add the modified, processed data to the data store before applying it to the template. You might want to move this code to the activate method and save the resulting HTML in a variable that the getHtml method simply returns. This is just a starting point of what you might want, but you get the idea.

That pretty much wraps it up. Clearly there are many points for additions and customization’s, but this should get you up and running with a base compiler for handlebars scripts. Have a question about server-side handlebars in Adobe Experience Manager? Drop us a line at or Twitter @axis41.