Editable Templates, Policies and the Style System in AEM as a Cloud Service

If you learned AEM on CQ5 or early AEM 6.x, you probably built templates the old way: a cq:Template node under /apps, an allowedPaths regex, and a design dialog whose settings were stored in a design under /etc/designs. I wrote about that approach years ago in Create a Template in Adobe CQ5, and that post still gets a lot of readers.

On AEM as a Cloud Service (AEMaaCS) that approach hits a wall. /apps is immutable at runtime, so the design of a static template cannot be edited from the UI, and Adobe recommends editable templates instead. Editable templates, their structure and their content policies live in /conf, which is mutable content. Template authors change them in the Template Editor without a code deployment, and the Style System lets page authors pick a visual variation of a component without you building a new component for every look.

In this tutorial I will show how templates, policies and the Style System fit together, where each piece lives in the repository, and how to give your own component a Styles tab. Let’s see it step by step.

Table of contents


Why this matters

Adobe’s list of AEMaaCS changes is direct about static templates: “Static Template design information that is stored in /apps can’t be edited by way of the UI.” It recommends editable templates, and adds that if static templates are still required, “configuration information must come from Git”. So every design change on a static template becomes a code change and a full Cloud Manager pipeline run.

Editable templates fix three practical problems:

  • Speed: template authors add an allowed component or change a default without waiting for a release.
  • Fewer components: with the Style System one Teaser can have “Dark” and “Featured” variants instead of three copies of the same component.
  • Clear roles: developers own template types, components and CSS; template authors own templates and policies; content authors own pages.

Who should read this

This post is for AEM developers moving a project from static templates and design mode to AEMaaCS, for architects who define how templates are governed across environments, and for template authors who want to understand what happens in the repository when they click around in the Template Editor.

Prerequisites

Static templates in AEM 6.x vs editable templates in AEMaaCS

Before we touch the Template Editor, here is the difference in one table. Keep it in mind when you read old code in a migrated project.

AspectStatic template (AEM 6.x)Editable template (AEMaaCS)
Location/apps/<project>/templates/conf/<site>/settings/wcm/templates
Who changes itDeveloper, through a code deploymentTemplate author, in the Template Editor
Component settingsDesign mode, stored in a design (/etc/designs)Content policies under /conf/<site>/settings/wcm/policies
Allowed componentsDesign mode on the paragraph systemPolicy of the Layout Container
Link to existing pagesCopied when the page is createdStructure changes are reflected on pages that use the template
Status on AEMaaCSDesign can’t be edited in the UI; configuration must come from GitRecommended by Adobe

Where templates and policies live in /conf

Everything for a site sits under one configuration folder. This is the layout Adobe documents, filled with what the archetype generates for mysite:

/conf/mysite                          (sling:Folder)
└── settings                          (sling:Folder)
    └── wcm                           (cq:Page)
        ├── template-types            (template types for this site)
        │   ├── page
        │   └── xf
        ├── templates                 (cq:Page)
        │   ├── page-content          (cq:Template, title "Content Page")
        │   │   ├── jcr:content       (status = enabled)
        │   │   ├── structure         (locked layout + cq:responsive breakpoints)
        │   │   ├── initial           (content copied into every new page)
        │   │   ├── policies          (which policy each component uses)
        │   │   └── thumbnail.png
        │   └── xf-web-variation      (Experience Fragment template)
        └── policies                  (cq:Page)
            └── mysite/components/... (policies, grouped by component resource type)

A few details that matter in real projects:

  • Template types are the blueprints that templates are created from. Adobe ships some in /libs/settings/wcm/template-types (never change /libs); your own go in /conf/<site>/settings/wcm/template-types or /apps/settings/wcm/template-types.
  • status on the template’s jcr:content is draft, enabled or disabled. Authors can only create pages from enabled templates.
  • policies inside a template does not hold design values. It holds references, for example policies/jcr:content/root@cq:policy, which points to the policy of the page’s root container.
  • Lookup order: template types and policies are resolved from the current folder, then parent folders, then /conf/global, then /apps, then /libs. If the same entry exists in two places, the one closest to the current folder wins.

Binding a site to its templates

Two properties connect a site to its configuration folder and decide which templates authors see in the Create Page wizard.

1. The configuration folder and cq:conf

For a new site, create the folder under Tools > General > Configuration Browser > Create and tick Editable Templates. Be careful: Adobe notes that you cannot unselect a feature once the configuration has been created. The archetype already creates /conf/mysite with templates and policies, so you only need the Configuration Browser for additional folders.

The site is bound to that folder with cq:conf on the jcr:content node of the site root. The archetype writes this for you, together with the allowed templates rule:

<!-- ui.content/src/main/content/jcr_root/content/mysite/.content.xml (excerpt) -->
<jcr:content
    jcr:primaryType="cq:PageContent"
    cq:conf="/conf/mysite"
    sling:configRef="/conf/mysite"
    cq:allowedTemplates="[/conf/mysite/settings/wcm/templates/(?!xf-).*]"/>

2. Allowed templates

AEM uses the first non-empty cq:allowedTemplates property it finds while walking up the page tree. Templates can also carry allowedPaths, allowedParents and allowedChildren, but Adobe recommends using only cq:allowedTemplates, and only on the site root. The regex above allows every template in /conf/mysite except the Experience Fragment ones, which start with xf-. Authors can change the list in the Advanced tab of Page Properties.

Note:- Do not enable editable templates on /conf/global just because it is quicker. Adobe calls it not recommended. Keep one configuration folder per site or brand, so a template change for one site cannot surprise another.

Template Editor: Structure, Initial Content and Layout

Open a template from Tools > General > Templates. The editor has three modes, and each one writes to a different node of the template:

  • Structure writes to structure. Components added here appear on every page and cannot be changed by page authors. If you unlock a component (usually a container), AEM sets editable=true on it and page authors can add content inside it. Policies are assigned in this mode.
  • Initial Content writes to initial. This is the starting content of a new page, which authors can change or delete. Policies are never defined in this mode.
  • Layout sets the responsive layout of components per breakpoint.

The big win compared to static templates: changes to the structure are reflected on the pages already created from the template. Initial content is only copied when a page is created, so changing it later affects new pages only.

Content policies

A content policy is a reusable piece of design configuration: which components a container allows, which heading sizes a Title offers, which styles a Teaser has. A policy is stored once under /conf/<site>/settings/wcm/policies and can be referenced by many templates. There are two kinds you will use every day:

  • Page policy: opened from Page Information > Page Policy in the Template Editor. With the Core Components Page v3 component this is where the page client libraries are set.
  • Component policy: set on a component in Structure mode. A policy is mandatory for container components. The Layout Container policy has the tabs Allowed Components, Default Components and Responsive Settings.

For the Page v3 component, the page policy dialog maps to these properties:

Field in the page policyPropertyArchetype value
Client Librariesclientlibsmysite.dependencies, mysite.site
Client Libraries JavaScript Page HeadclientlibsJsHeadmysite.dependencies
Load JavaScript Libraries asynchronouslyclientlibsAsyncnot set
Web Resources Client LibraryappResourcesClientlibnot set

Note:- Policies are shared. If two templates point to the same Layout Container policy and you add a component to it, both templates get the component. When a template needs different rules, create a new policy for it instead of editing the shared one.

The Style System

The Style System lets a template author define named styles in a component policy, and a page author pick them from the paintbrush icon in the component toolbar. Each style is just one or more CSS classes. In the policy dialog you work with four fields: Group Name, Style Name, CSS Classes and Styles can be combined, which allows several styles of the same group to be selected at once.

Behind the dialog the policy stores the styles like this (the property names come from the StyleConstants class in the AEM SDK):

<!-- /conf/mysite/settings/wcm/policies/mysite/components/teaser/policy_teaser_card -->
<policy_teaser_card
    jcr:primaryType="nt:unstructured"
    jcr:title="Teaser - Card"
    sling:resourceType="wcm/core/components/policy/policy">
    <jcr:content jcr:primaryType="nt:unstructured"/>
    <cq:styleGroups jcr:primaryType="nt:unstructured">
        <item0
            jcr:primaryType="nt:unstructured"
            cq:styleGroupLabel="Theme"
            cq:styleGroupMultiple="{Boolean}false">
            <cq:styles jcr:primaryType="nt:unstructured">
                <item0
                    jcr:primaryType="nt:unstructured"
                    cq:styleId="1731200000001"
                    cq:styleLabel="Dark"
                    cq:styleClasses="cmp-teaser--dark"/>
                <item1
                    jcr:primaryType="nt:unstructured"
                    cq:styleId="1731200000002"
                    cq:styleLabel="Featured"
                    cq:styleClasses="cmp-teaser--featured"/>
            </cq:styles>
        </item0>
    </cq:styleGroups>
</policy_teaser_card>

When an author applies a style, the component node stores the selected IDs in cq:styleIds, not the class names. That is why you should keep cq:styleId values unique and stable: you can later change the CSS class of a style in the policy, and every page that uses it picks up the new class.

Where the class ends up in the HTML

Adobe’s documentation says the style class “is inserted on the decoration wrapper element of the component”. The wrapper is the element AEM puts around your component’s own markup. Rendered on a page it looks roughly like this (layout grid classes left out):

<div class="teaser cmp-teaser--dark">
    <div class="cmp-teaser">
        <!-- the component's own markup -->
    </div>
</div>

So write your CSS against the wrapper class and the component’s own block class, and ship it in a client library that the page policy loads:

/* style classes sit on the wrapper, the BEM block sits inside it */
.cmp-teaser--dark .cmp-teaser {
    background: #1f2937;
    color: #ffffff;
}
.cmp-teaser--featured .cmp-teaser__title {
    font-size: 2rem;
}

Two more rules from the documentation are worth knowing. You can let a style change the wrapper element by listing allowed names in cq:styleElements on the component, for example [div,section,span], but Adobe advises not to set element names for styles that can be combined. And the Style System “only applies to pages created with the Page Editor”.


Hands-on: build an Article Page template step by step

We will create an Article Page template for mysite, limit its components, give the Teaser two styles, and add a Styles tab to a custom component. Start your local SDK and deploy the project once with mvn clean install -PautoInstallSinglePackage.

Step 1 : Check what the archetype created

Open CRXDE Lite at http://localhost:4502/crx/de and look at three places:

  • /conf/mysite/settings/wcm/templates/page-content: the Content Page template. Check that jcr:content@status is enabled.
  • /conf/mysite/settings/wcm/policies: the page policy and the container policies.
  • /content/mysite/jcr:content: cq:conf and cq:allowedTemplates, as shown earlier.

Step 2 : Create the template

Go to Tools > General > Templates, open the MySite folder and click Create. Select the Page template type, click Next, enter the title Article Page and a short description, then click Create and Open. The new template is created in draft status.

Step 3 : Define the structure

In Structure mode, keep everything that every article shares locked, such as the header and footer Experience Fragments. Select the main container and click the lock icon to unlock it. From now on page authors can add components inside that container, and nothing else on the page.

AEM Template Editor in Structure mode for the Article Page template: locked header and footer Experience Fragments, an unlocked container with Policy and lock buttons, and Page Information menu
Structure mode of the Article Page template. Header and footer stay locked; authors can only add content inside the unlocked container.

Step 4 : Limit the allowed components

Select the unlocked container and click the policy icon. Create a new policy called Article - Main. On the Allowed Components tab, open the MySite – Content group and tick only Title, Text, Image, Teaser and List. Click Done. I always create a new policy here; reusing the archetype’s container policy would also change the Content Page template.

Layout Container policy dialog with the new Article - Main policy and the Allowed Components tab: Image, List, Teaser, Text and Title ticked in the MySite - Content group
A new Article – Main policy for the container. Only the ticked components appear in the side panel for this template.

Step 5 : Add initial content

Switch to Initial Content mode. Add a Title and a Text component to the unlocked container with placeholder text such as “Write the article summary here”. Every new article starts with these two components, and authors can change or remove them.

Step 6 : Check the page policy and enable the template

Open Page Information > Page Policy and select the existing page policy, so the template loads mysite.dependencies and mysite.site like the rest of the site. Then go back to the Templates console, select Article Page and click Enable. Because its name does not start with xf-, the site root regex already allows it.

CRXDE Lite showing /conf/mysite/settings/wcm/templates/article-page with initial, jcr:content, policies, structure and thumbnail.png, and jcr:content properties status enabled and cq:templateType
The finished template is content in /conf. After you click Enable, status on jcr:content is enabled.

Step 7 : Add Style System styles to the Teaser

Back in the template, in Structure mode, select a Teaser inside the container (add one temporarily if needed) and open its policy. Create a policy Teaser - Card. On the Styles tab add a group Theme with the styles Dark (cmp-teaser--dark) and Featured (cmp-teaser--featured). Leave “Styles can be combined” unticked, because a teaser should not be dark and featured at the same time. Add the CSS from the previous section to your ui.frontend styles and redeploy.

Now create a page from Article Page, add a Teaser, and pick Dark from the paintbrush icon. In CRXDE you will see cq:styleIds on the teaser node.

Teaser - Card policy, Styles tab with group Theme, Styles can be combined unticked, styles Dark cmp-teaser--dark and Featured cmp-teaser--featured, plus the paintbrush menu authors see in the page editor
Style System styles in the Teaser policy, and the paintbrush menu page authors see. Each style is just CSS classes.

Step 8 : Give a custom component a Styles tab

Core Components from v2 onwards need no extra configuration for the Style System. Your own components do: they need a design dialog that includes Adobe’s style tab. For a custom hero component create _cq_design_dialog/.content.xml next to the component definition:

<?xml version="1.0" encoding="UTF-8"?>
<!-- ui.apps/src/main/content/jcr_root/apps/mysite/components/hero/_cq_design_dialog/.content.xml -->
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
          xmlns:jcr="http://www.jcp.org/jcr/1.0"
          xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
    jcr:primaryType="nt:unstructured"
    jcr:title="Hero"
    sling:resourceType="cq/gui/components/authoring/dialog">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/container">
        <items jcr:primaryType="nt:unstructured">
            <tabs
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/tabs"
                maximized="{Boolean}true">
                <items jcr:primaryType="nt:unstructured">
                    <styletab
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/include"
                        path="/mnt/overlay/cq/gui/components/authoring/dialog/style/tab_design/styletab"/>
                </items>
            </tabs>
        </items>
    </content>
</jcr:root>

Deploy, open the policy of the hero component in the Template Editor, and the Styles tab is there. If you are building that component from scratch, the companion post Build a Custom Component in AEM as a Cloud Service walks through the HTL, Sling Model and edit dialog.

Step 9 : Put the template and policies into Git

What you built lives only in your local repository. Adobe’s WKND tutorial recommends to “persist configurations, like templates and related content policies, to source control”. Pull /conf/mysite/settings/wcm/templates/article-page and the new policies into ui.content with the AEM sync feature of your IDE or the repo tool, then commit.

Now look at the archetype’s ui.content filter:

<!-- ui.content/src/main/content/META-INF/vault/filter.xml (excerpt) -->
<filter root="/conf/mysite" mode="merge"/>

merge means existing content is not modified; only new content is added. That is exactly what you want for templates that authors edit on the environment, but it has a side effect that catches every team once: if you change a template in Git after it was first deployed, the change does not reach environments where the template already exists.

Who owns templates on production?

Adobe gives you the building blocks but no single rule here. What the documentation does say: content packages deploy to all environment types, content that is specific to one environment must be installed manually with Package Manager, and there is no mechanism to roll back mutable content package changes. From my experience, decide on one source of truth per site and write it down:

  • Git owns template types, components, CSS and the first version of each template and policy. New templates reach every environment through the pipeline.
  • Template authors own changes to existing templates and policies on production. If a lower environment needs the same change, copy it down with a content package, not the other way round.
  • Keep the number of templates small. Adobe’s templates guide suggests staying under 100; in practice a site rarely needs more than ten.

Personally I prefer this split, because it never asks a developer to overwrite something an author changed on production last week.

Which feature for which job

You want to…UseStored in
Fix a header and footer on every pageLocked components in Structure modeTemplate structure
Control which components authors can addLayout Container policy, Allowed Components/conf/…/policies
Pre-fill new pagesInitial Content modeTemplate initial
Load site CSS and JSPage policy (client libraries)/conf/…/policies
Offer visual variants of a componentStyle System styles in the component policycq:styleGroups in the policy, cq:styleIds on the content
Limit templates per sitecq:allowedTemplates on the site root/content/<site>/jcr:content

Common mistakes and troubleshooting

SymptomLikely causeFix
The template is not offered in the Create Page wizardTemplate still in draft, or the cq:allowedTemplates regex does not match its pathEnable the template; check the regex on the site root
No templates at all for a new sitecq:conf missing on the site root jcr:contentSet cq:conf to the configuration folder
A component is missing from the side panelIt is not allowed in the Layout Container policy, or its componentGroup starts with a dot (hidden)Allow it in the policy; use a visible group
No Styles tab on a custom componentNo _cq_design_dialog with the style tab includeAdd the design dialog from Step 8
A style is selected but nothing changesCSS not in a client library loaded by the page policy, or the selector targets the inner element onlyLoad the clientlib; write .cmp-x--style .cmp-x
A template change in Git never reaches Stagemode="merge" on /conf/mysiteChange it in the Template Editor on the environment or install a content package
Editing one policy changed several templatesThe policy is sharedCreate a separate policy for the template that needs different rules

Hands-on challenge

Create a Landing Page template that allows only Teaser, Title and Button in its main container. Add a style group Spacing to the Teaser with two combinable styles, Large top margin and Large bottom margin. Apply both on a page and confirm in CRXDE that the teaser node stores two IDs in cq:styleIds. Success means the Article Page template still offers its original components, because you created new policies instead of editing shared ones.

Key takeaways

  • Static template designs can’t be edited in the UI on AEMaaCS; Adobe recommends editable templates.
  • Templates, template types and policies live under /conf/<site>/settings/wcm, which is mutable content.
  • Bind the site with cq:conf and control templates with cq:allowedTemplates on the site root only.
  • Structure changes reach existing pages; initial content only affects new pages.
  • The Style System adds CSS classes to the component wrapper; custom components need the style tab in a design dialog.
  • The archetype deploys /conf in merge mode, so decide who owns template changes after the first deployment.

Knowledge check

1. Where does AEMaaCS store the policies of the site mysite?

Under /conf/mysite/settings/wcm/policies, grouped by component resource type.

2. A template author changes a locked header in Structure mode. Which pages show the change?

All pages created from that template, including existing ones, because structure is dynamically linked.

3. What does a page store when an author applies a style?

The IDs of the selected styles, in cq:styleIds on the component node.

4. Which property should you use to limit templates per site, and where?

cq:allowedTemplates, only on the site root, as Adobe recommends.

5. Why does a template change committed to Git not appear on an environment where the template already exists?

The archetype’s ui.content filter uses mode="merge" for /conf/mysite, so existing nodes are not overwritten.

Frequently asked questions

Can I still use static templates on AEM as a Cloud Service?

Existing static templates can still render pages, but their design can’t be edited in the UI and the configuration must come from Git. Adobe recommends moving to editable templates.

What is the difference between site templates and page templates?

Adobe says site templates “should not be confused with page templates”. A site template defines the overall structure of a new site and is used for quick site creation; a page template (editable template) defines the structure and initial content of one page.

Do Core Components need anything extra for the Style System?

No. Core Components v2 and later need no additional configuration. Only your own components need the style tab in a design dialog.

Can I move templates between environments with Package Manager?

Yes, /conf is mutable, so content packages with templates and policies can be installed. Remember that there is no rollback for mutable content, so take a backup package first.

Should I put templates in /conf/global so every site can use them?

Adobe calls enabling editable templates on the global folder not recommended. Use one folder per site or brand, and share only what really is common.

Continue your learning

References

Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.