Reminder - Digital Publishing Suite (DPS) will End of Life on August 31st, 2019. 
Prerequisite knowledge
User level: Intermediate
Required products (retail)
Sample files
By downloading software from the Adobe Web site you agree to the terms of our license agreement. Please read it before downloading.
Note: If you have questions about this article, use the DPS forum. Please don’t contact technical support with questions about Adobe Developer Connection articles.


A lot goes into creating a DPS magazine when you create it with AEM. Out of the box you have everything you need to get up and running, but if you want to push it further there are a few things you’ll need to know. This article will cover some more advanced concepts such as AEM content sync and using HTMLResources, clear up some confusion with terms, and explore what actually happens when Folios and .folios are created with AEM. You’ll gain insight into advanced magazine creation that I learned from using AEM to publish the app, a digital magazine for marketing professionals.

Overview of common terms and how they relate

I’m going to cover a few of the common terms, how they relate to each other, and the high level layout of a magazine issue.
‘Folios’ vs ‘.folio’
‘Folios’, which I call ‘capital F folios,’ can be described as the issue of the magazine. ‘Folios’ contain one or more ‘Articles’ and an file. However, in order to have an ‘Article’ ready to be included in a ‘Folio’, it needs to be packaged up, which results in a package with a ‘.folio’ extension for that ‘Article.’  This does not come up often, but you may find yourself occasionally trying to debug ‘Articles’ and they will have a ‘.folio’ extension after being packaged. This distinction will be handy later on in this article.
Content Sync Framework
The Content Sync Framework is a service in AEM. Media Publisher for AEM provides  the Content Sync configurations that are required for packaging your Articles. Out of the box these will work for most cases, and they are responsible for packaging each individual ‘Article’ into a .folio package, complete with metadata and assets as well as the
Clientlibs and HTMLResources
Clientlibs – also known as Client-Side Libraries – are the JS/CSS libraries that you’ll want included in your page. There are some additional properties you’ll have to specify if you’re using component level Clienlibs (covered in the next section) and in the Content Sync configuration.
HTMLResources is an additional .zip package that gets uploaded and packaged with the ‘Folio’ that all ‘Articles’ have access to.

Configuring your Content Sync template and Clientlibs

Of the  provided Content Sync configurations,  there are two that are important for customizing: the .folio packaging configuration and the HTMLResources packaging configuration.
Media Publisher for AEM will use the  template specified on the ‘dps-Issue’, in the sample code this would be ‘/apps/aaa/dps-sample/templates/issue’ and the property is ‘dps-exportTemplate
HTMLResources configuration
If you look under the /etc/contentsync/templates/aem-dps-sample/ you’ll notice a dps-HTMLResources node and some child nodes after this with a set of properties. When AEM creates the HTMLResources .zip it looks to this node to get the required files to include. Each sub node under the dps-HTMLResources node represents a Content Sync configuration, this configuration is passed to a Content Sync framework which executes the appropriate handler based on the ‘type’ property of that node. The handler then specifies what to add to the HTMLResources package. There are two main ones that we need to worry about – ‘clientlib’ and ‘copy’ (in the next section I’ll go over how to create your own).
‘copy’ is straightforward. You specify the path and optionally the extension, and everything in that path will be copied – with the full path – to If you specified the path as ‘/content/dam/magazinestuff/’ then everything under that path would be copied with the destination as ‘/HTMLResources/content/dam/magazinestuff/
‘clientlib’ works a little differently. You specify the clientlib that you want to include and the section (JS or CSS) of that clientlib that you want. For example, if articles in my magazine used the jQuery clientlibs, then I would add in two sub nodes:
<foundation-jquery-js jcr:primaryType="nt:unstructured" extension="js" path="/etc/clientlibs/foundation/jquery" type="clientlib"/> <foundation-jquery-css jcr:primaryType="nt:unstructured" extension="css" path="/etc/clientlibs/foundation/jquery" type="clientlib"/>
This will tell the content sync framework to include the jQeury clientlib in the HTMLResources package.
Note: I’m fairly certain an enhancement that will let you leave out the extension property for the clientlib type is in the works, but for the meantime you need to specify two clientlib nodes: one for JS, and one for CSS, if you want both to be included.
I like to use component level clientlibs to help keep code organized and keep components contained to aid reuseability. Each component has their own clientlib, usually following the naming convention of aaa.projectName.components.componentName. If I wanted to use this convention, I would have to add in two content sync configurations for each separate component that I wanted to include in each article. To eliviate this, I add in an additional common category to each of my component clientlibs. For example, I would add the additional category of ‘aaa.projectName.mag.components’ resulting in ‘aaa.projectName.components.componentName,aaa.projectName.mag.components’ on each component clientlibs I create.
This allows me to create a global clientlib, which I stick in the design path for organization purposes, and to have that global clientlib, called ‘aaa.projectName.mag.components-all’ embed the ‘aaa.projectName.mag.components’ clientlib. This way I just need to maintain one pair of entries in the content sync configuration:
<aaa-projectName-mag-components-all-js jcr:primaryType="nt:unstructured" extension="js" path="/etc/designs/projectName/clientlibs-all " type="clientlib"/> <aaa-projectName-mag-components-all-css jcr:primaryType="nt:unstructured" extension="css" path="/etc/designs/projectName/clientlibs-all " type="clientlib"/>
This might seem a little confusing, but there is a practical example of this in the sample code. Also, this will combine all your component clientlibs together, so as a best practice you might want to namespace your component styles so they don’t accidentally get overwritten.
When these content sync configuration nodes are passed to the content sync framework, it will resolve any additional embed clientlibs that are specified on the ‘clientlibs-all’. In this case, the ‘clientlibs-all’ has the category for ‘aaa.projectName.mag.components’ specified as an ‘embed’ property, which results in any clientlibs that have the category of ‘aaa.projectName.mag.components’ to be resolved and embed in the ‘clientlibs-all’. Therefore all of the component clientlibs will be merged together and included in
Folio configuration
There is also another node on the same level as the dps-HTMLResources node named ‘dps-folio’. This is the node that gets executed whenever a Article is packaged into a .folio. The vast majority of the time you won’t have to touch anything in here, and to be honest I am not 100% sure what all of the content sync update handlers do under the covers, but I can describe what I consider to be the important thing to know in this step:
It rewrites the src attributes for <script> tags and <img> tags to point to the new destinations. As I touched on earlier, JavaScript and CSS included in the clientlibs get packaged into The packager rewrites all of the includes in the .html from absolute paths on the server – for example /etc/content/designs/clientlibs.css – to their new path which would be ../HTMLResources/etc/content/designs/clientlibs.css. Images are included inside the .folio package and rewritten in a similar manner, making them relative to the article rather then to the server. For example an image referencing ‘/content/publications/magazine/article1/_jcr_content/article-image.img.png/1391657615025.png’ would be rewritten to ‘./article1/_jcr_content/article-image.img.png/1391797849453.png’. It then packages the image into the .folio with the same folder structure.
This is an important thing to note if you’re creating paths programmatically in JavaScript to load or reference an image. Or if you’re referencing images in CSS inside of component clientlibs. I recommend against this: if you’re going to reference images inside of CSS, stick the styles/images inside your main ‘Design’ path.

Creating a custom Content Sync Update Handler

When we were developing the components for our app we considered using the out of the box video component. However, I wanted a video component where I could configure the ‘poster image’. In reality this could have been easily done out of the box, but I also was looking for an opportunity to write my own Content Sync Update Handler and it seemed like an easy place to start.
In the sample code, there is a ‘CustomAEMDPSSampleContentSyncHandler’ Java class that shows how this is done. I grabbed this from one of the ‘Geometrixx’ example applications and configured a few lines to handle what I wanted it to do. I’ll touch on some of the inner workings, what happens, and where this is configured on the content sync template for the sample magazine.
The content sync for mobile documentation covers the general idea of content sync and I’ll try to fill in any gaps where it differs specifically for DPS.
Content Sync Handler Type
At the top of the class, you’ll see the following:
@Component( metatype = true, factory = "", inherit = true )
The important part to note here is the bolded section of ‘aem-dps-sample-video-update-handler’. This is the ‘type’ of content sync handler it is: the value specified in the configuration subnodes are matched against this value and handled appropriately.
In the sample code under /etc/contentsync/templates/aem-dps-example/dps-folio/.content.xml, the following subnode:
<custom jcr:primaryType="nt:unstructured" extension="html" path="\{page.path}" type="cmo-dps-video-update-handler"/>
would trigger our custom handler.
Determine package contents
Here is a general sequence of steps for what happens next as it runs through the custom content sync update handler. Since this is an add-on to the out-of-the-box handlers that already take care of most stuff, we really only need to worry if the article has a component of type ‘aaa/dps-sample/components/content/video’ – which is the resourceType of the custom video component I made – and then package the content in from there. You’ll notice this is specified in a static variable at the top of the class. There are other important properties as also defined here, namely ‘posterSource’, which is the property that the ‘poster image’ is referencing. These variables are basically the setup for what to package and when to package it.
The ‘updateCacheEntry’ method is the entry point into the handler and there are a few DPS helper methods in here to determine if the path being passed in from the ‘configEntry’ is the overall DPSFolio object or if it’s a DPSArticle; in our case, its going to be a DPSArticle. From there it will look at the components included on the page and compare the resourceTypes of the components to what we specified in our static variable at the top. If it finds a match, it downloads the source asset (the movie in this case) then it moves to the ‘addToExportCache’ function which resolves the original rendition (for the movie) and copies it with the full path to the current cache of assets waiting to be packaged (as identified by the ‘configCacheRoot’ property that got passed in back in the beginning.
Finally, if the ‘posterSource’ path is not blank, it passes it on to the inherited function ‘renderResource’ – I don’t know exactly what happens here, but I expect it renders the resource and copies it into the asset cache as well – since that is what ends up in the cache.

Where to go from here

This just scratches the surface of what you can do using AEM to publish to DPS. There are a lot of moving pieces when you package a magazine. For the most part, this article is meant to give you a peek under the covers and to give you an understanding of why things may not be working as you might expect in your implementation.

Comments are currently closed as we migrate to a new commenting system. In the interim, please provide any feedback using our feedback form. Thank you for your patience.