Assembly Time Navigation Includes

Solution Overview:

Note : Make sure you update to patch 20171007 for this feature and if using with a previous patch check the configuration on the Include Content List that has changed.

The solution is designed to improve the overall publishing performance in Rhythmyx implementation by breaking out repetitive content blocks (such as Navigation) from their main Publishing Editions, into more focused publishing editions.   These Navigation Editions will publish to the local disk on the Percussion Server.  

A specialized velocity template extension will perform the Include at Assembly time on the Rhythmyx server effectively delivering a complete assembled HTML file to the web server with no need for SSI directives.   This will avoid the overhead and security concerns when using SSI on the Web Server.

Assembly Time Nav Design

The diagram above outlines the solution design.  


  • Navigation can be published independent of general content changes.  This will improve performance as common navigation elements that rarely change only need to be assembled once.
  • The performance improvements will be the same as the SSI approach without actually utilizing SSI on the production web server.


  • More Editions to manage.
  • Navigation editions must be run before full or incremental editions if Navigation changes have been made.
  • More disk space will be taken up on the Rhythmyx server to house the Navigation snippets.  This should not be significant as there are a fixed number of Nav elements and they are textual.


Create a new Local Template for rffNavon and rffNavTree to publish the includes e.g. (rffNavonIncludes, rffNavTreeIncludes) NOTE (change from previous instructions): rffNavonIncludes template must be assigned as a shared template to both rffNavon and rffNavTree.  rffNavTreeIncludes is only assigned as an allowed template to rffNavTree.

Set Output as Text Page, publish to Never and set Global Template to None. In the sites tab of the template add the allowed sites.

These templates just contain a list of #renderInclude Macro calls referencing the navigation templates that are to be used in includes.  These should be on separate lines

If a nav template produces html that is the same for the whole site it only needs to be included on the NavTree template.  The Navon template is generated per folder.

Make sure these imports are on separate lines and do not add # comment character to the end of the line

This mechanism publishes a single file per folder with all the includes combined with a separator that can be parsed.


Setup Publishing

To Publish the includes you should set up a new Edition for your site containing a single include content list.  First there are some server properties that need to be set up to say where to publish the includes.  

Context variables

For each site using includes you need to set up the include_navon_template,  include_navtree_template and include_path

The include_path is relative to the Published Path value.  

Create a new "Site_Folder_Assembly" and "Publish" location scheme for The new NavTree (e.g and Navon Templates (e.g. ) .  Note the file name should be different between the NavTreeInclude location scheme and the NavonInclude (This is a change from previous instructions). 

Content List:

Create a new Content List.  The Delivery Type should be filesystem even if you are using ftp for your main publishing.  You should also use the template expander.

Select only the rffNavon and rffNavTree Types.  e.g. for Enterprise Investments the generator query looks like this:

select rx:sys_contentid, rx:sys_folderid from rx:rffNavon,rffNavTree where jcr:path like '//Sites/EnterpriseInvestments%'

Use the public filter so that includes are created for all folders containing Navon items regardless of state.  The assembly_filter=public parameter will make sure that the contents are the includes are assembled as if they are being published with the public filter and links to pages and Navons will not be filtered out if they are not public.  This option is only available since patch 732_20171007 


Create your new include edition that uses the content type you have created.  Select Behavior as Unpublish Then publish.

You should now be able to publish your new edition and check that the include files are published to the configured location.

Configuring Templates to use includes

In your templates  just modify any navigation slot references to use the new #percNavInclude macro

e.g. Change

#slot("rffNav" "" "" "" "" "template=rffSnNavPreload")



This should make no difference in preview, the original rendering will be used.  When published The include file will be searched for and will be used if it exists.

If the include file does not exists the code will fall back to assembling the navigation inline and will look the same but will not have the performance benefit.  If you view the source of the page a comment will be placed

That contains the text "Cannot locate include" which will show the error.  


Timing and Debuging

Some new functionality has been added that can help to diagnose issues in the performance or errors in the template

You can start and stop timers in the page assembly and then report the times at the end of the page.  Here is an example 

Using the #timers_output() macro you can output a table of all the timers that have been added and the time associated with them.  The timers will continue to the end of assembly unless #timer_stop is called.  You probably only want to add this tag during debugging you could choose to only display in a staging publish or to include in a html comment so it is not normally visible as below.  Individual times can also be accessed.


Here you also see the #sys_log macro can be used to write a message to the server log.  Use this wisely to not throw too many log messages during publishing which will slow down and create large log files.  The macro also appends the content id and template to the message to aid in debugging

Note Due to the order that assembly is processed, timers created in a page template are visible in the global template but not the other way around.  The full page body is assembled before being inserted into the global template.  Adding #timers_output to the end of the global template therefore should pickup timers created in both the global and local templates.

Adding timers to the velocity will not find issues with performance in the page templates bindings.  If required you can also call the new jexl functions directly to start and stop timers in the template bindings.

 $rx.asmhelper.timerStart($sys.assemblyItem, $name)

$rx.asmhelper.timerStop($sys.assemblyItem, $name)

$rx.asmhelper.timerElapsed($sys.assemblyItem, $name)

$timersMap = $rx.asmhelper.timerOutput($sys.assemblyItem)  (timers map has a key of the timer name and value as the time when this function is called,  the time in timersMap does not changed, calling timerOutput again can be used to get updated values.