Skip to main content

Templates & Policies

Templates define the structure and behavior of pages. Policies control which components authors can use and how they behave. Together, they create a governed authoring experience - authors have freedom within boundaries.

Editable templates

AEM uses editable templates - templates that can be created and configured in the authoring UI (not just in code). They live in /conf/mysite/settings/wcm/templates/.

ConceptStored inManaged by
Template Type/conf/mysite/settings/wcm/template-types/Developers + template admins
Editable Template/conf/mysite/settings/wcm/templates/Template authors (UI)
Page/content/mysite/Content authors (UI)

Static vs editable templates

Older AEM projects used static templates (stored under /apps/.../templates, edited only in code). Modern projects -- and everything on AEM as a Cloud Service -- should use editable templates. The difference matters when you inherit or migrate a project:

Static templateEditable template
Stored in/apps (code)/conf (configuration)
Who edits structureDevelopers onlyTemplate authors, in the UI
Changes propagate to existing pagesNo (structure copied at create time)Yes (structure + locked content stay live)
Policies / Style SystemNot supportedSupported
Recommended for new workNoYes

If you find cq:template pointing at an /apps/... path with a cq:Template node, you are looking at a static template. New components and chapters in this guide assume editable templates throughout. See Adobe's Page Templates -- Editable and Creating Page Templates.

Template Types

A template type is the blueprint for editable templates. It defines:

  • Which page component renders the page
  • The initial structure (locked components that every page gets)
  • The initial content (default content for new pages)
  • The initial policies (default component policies)

Template types live under your site configuration in /conf (often seeded by code packages and then managed in the UI):

conf/mysite/settings/wcm/template-types/
└── page/
├── .content.xml # Template type definition
├── structure/
│ └── .content.xml # Structure (locked layout)
├── initial/
│ └── .content.xml # Initial content
└── policies/
└── .content.xml # Default policies

Creating an editable template

  1. Go to Tools > General > Templates
  2. Select your configuration folder (My Site)
  3. Click Create
  4. Choose a template type (e.g., Page)
  5. Enter a title (e.g., Article Page)

Template editor modes

The template editor has three modes:

ModePurpose
StructureDefine locked layout containers and components. Authors cannot change these
Initial ContentSet default content for new pages. Authors can modify this
PoliciesConfigure component policies - allowed components, styles, behavior

Structure mode

In Structure mode, you define the skeleton of the page:

  • Add layout containers (responsive grid)
  • Lock components that must appear on every page (e.g., header, footer)
  • Define which areas are editable

Locked components have a lock icon - authors cannot move, delete, or configure them.

Initial content mode

In Initial Content mode, you pre-fill content for new pages. For example:

  • A default title component with placeholder text
  • An empty image component ready for the author to fill
  • A pre-configured list component

Authors can modify all initial content after creating a page.

The page component

Every page in AEM is rendered by a page component. This is the top-level component that produces the HTML document:

<!-- apps/mysite/components/page/page.html -->
<!DOCTYPE html>
<html lang="${currentPage.language}"
data-sly-use.page="com.mysite.core.models.PageModel">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>${page.title}</title>
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
<sly data-sly-call="${clientlib.css @ categories='mysite.base'}"/>
</sly>
</head>
<body class="page ${page.cssClass}">
<div data-sly-resource="${'header' @ resourceType='mysite/components/header'}"></div>

<main>
<div data-sly-resource="${'root' @ resourceType='core/wcm/components/container/v1/container'}"></div>
</main>

<div data-sly-resource="${'footer' @ resourceType='mysite/components/footer'}"></div>

<sly data-sly-call="${clientlib.js @ categories='mysite.base'}"/>
</body>
</html>

Key elements:

  • Head - meta tags, CSS includes
  • Header/Footer - included as fixed components (using data-sly-resource)
  • Main content area - a responsive grid where authors place components
  • Client libraries - CSS loaded in head, JS before closing body

Proxy page component

Your project's page component typically extends the Core Components page:

<!-- apps/mysite/components/page/.content.xml -->
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
jcr:primaryType="cq:Component"
jcr:title="Page"
sling:resourceSuperType="core/wcm/components/page/v3/page"/>

Then you customize by overriding specific HTL files (like customheaderlibs.html and customfooterlibs.html) rather than rewriting the entire page.

Overriding customheaderlibs and customfooterlibs

The Core Components page component provides extension points for injecting custom CSS and JS. Create these files in your page component to add your own includes:

<!-- apps/mysite/components/page/customheaderlibs.html -->
<!-- Loaded in the <head> -- use for CSS and critical resources -->
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
<sly data-sly-call="${clientlib.css @ categories='mysite.site'}"/>
</sly>

<!-- Custom meta tags, preconnects, etc. -->
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<!-- apps/mysite/components/page/customfooterlibs.html -->
<!-- Loaded before </body> -- use for JS -->
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
<sly data-sly-call="${clientlib.js @ categories='mysite.site'}"/>
</sly>

The Core Components page component uses data-sly-include to look for these files in your page component's resource type path (e.g., apps/mysite/components/page/). Because your proxy component sets sling:resourceSuperType="core/wcm/components/page/v3/page", Sling's script resolution checks your component first, then falls back to the Core Component. This means placing customheaderlibs.html in your page component folder is all you need - the Core Component includes it automatically if it exists.

This approach is preferred because you only override the extension points, while the Core Components page component handles the full HTML structure, SEO meta tags, and other boilerplate.

Templates as code (persisting /conf)

Templates, template types, and policies all live under /conf in the JCR. Changes you make in the UI exist only on that environment until you export them into your codebase. Treat template setup as configuration-as-code:

  1. In CRXDE Lite or via Package Manager, build a content package whose filter targets your template/policy paths, for example:
ui.content/.../META-INF/vault/filter.xml
<filter root="/conf/mysite/settings/wcm/templates"/>
<filter root="/conf/mysite/settings/wcm/template-types"/>
<filter root="/conf/mysite/settings/wcm/policies"/>
  1. Commit the exported XML into your ui.content (or a dedicated ui.conf) module so it deploys with the rest of the project.
  2. Redeploy on Dev/Stage/Prod through Cloud Manager - the templates arrive identically everywhere.

Without this step, UI-only changes are lost on the next deployment that overwrites /conf, and your environments drift apart. See Style System and Templates documentation.

Component policies

Policies control how components behave within a template. They are configured per template, per container. Policies are stored in the JCR under /conf/mysite/settings/wcm/policies/ - this is useful to know when debugging or exporting template configurations.

Setting allowed components

The most common policy setting - which components can authors add to a container:

  1. In the template editor, switch to Structure mode
  2. Click a layout container
  3. Click the policy icon (wrench)
  4. Under Allowed Components, select which component groups and individual components are permitted

This prevents authors from placing inappropriate components - for example, blocking the Hero component from appearing inside a sidebar container.

Design dialog policies

Some components have a design dialog (also called a policy dialog) that configures component-level defaults for a specific template context:

  • Text component - default rich text formatting options
  • Image component - allowed image widths, lazy loading default
  • Container - layout options, background colors

These values are accessible in the component via the currentStyle object:

@Model(adaptables = SlingHttpServletRequest.class)
public class ImageModel {

@ScriptVariable
private Style currentStyle;

public int getMaxWidth() {
return currentStyle.get("maxWidth", 1200);
}
}

Style System

The Style System lets you define CSS classes that authors can apply to components without developer intervention:

  1. In the template editor, select a component
  2. Open its policy
  3. Under Styles, add style groups:
Style groupOptions
SizeSmall, Medium, Large
ThemeLight, Dark
SpacingCompact, Comfortable

Each option maps to a CSS class (e.g., cmp-hero--large, cmp-hero--dark). Authors select styles in the component toolbar without touching code.

Remember, any changes you make via the browser UI will need to be exported and persisted in the git repository. Otherwise, they will be lost on redeploy.

Responsive grid (layout container)

The responsive container/grid is the main layout mechanism. It provides:

  • Drag-and-drop component placement
  • 12-column grid for responsive layout
  • Column resizing in the authoring UI
  • Breakpoints for responsive behavior

Authors use the layout mode (ruler icon) to resize component columns per breakpoint:

BreakpointDefault width
Phone< 768px
Tablet768px - 1024px
Desktop> 1024px

Breakpoints are configured in the responsive grid's policy (in the template editor, select the layout container, open its policy, and edit the breakpoint widths). You can also define custom breakpoints in the wcm/foundation/components/responsivegrid policy node in your /conf configuration.

Proxy components

In your project, most components are proxy components that inherit from Core Components:

<!-- apps/mysite/components/text/.content.xml -->
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
jcr:primaryType="cq:Component"
jcr:title="Text"
componentGroup="My Site - Content"
sling:resourceSuperType="core/wcm/components/text/v2/text"/>

The Maven archetype generates these automatically. Benefits:

  • Reuse - get all Core Component functionality for free
  • Customization - override any part (dialog, HTL, model) in your proxy
  • Versioning - update Core Components without breaking your overrides

Enabling templates for a site

Templates must be enabled for a specific site configuration:

  1. Go to Tools > General > Templates
  2. Select your configuration folder
  3. Templates created here are available to pages under /content/mysite/

The link between a site and its templates is in the site's jcr:content:

/content/mysite/jcr:content
├── cq:conf = "/conf/mysite" # Points to the configuration
├── cq:allowedTemplates = [ # Regex(es) for templates authors may use here
│ "/conf/mysite/settings/wcm/templates/.*"
│ ]

cq:allowedTemplates is a multi-value property of regex patterns set on a content root (often the site root or a section folder). A template only appears in the Create Page dialog if its path matches one of these patterns and the template is Enabled. If authors report "no templates available", check this property first, then the template's enabled/published status. You can set it in the UI via the page's Properties > Advanced > Template Settings (Allowed Templates).

Page creation flow

When an author creates a page:

For advanced template patterns, see the Templates and Policies reference. For customizing the responsive grid layout, see Extending the Responsive Grid.

Summary

You learned:

  • Editable templates are configured in the authoring UI, backed by template types in code
  • Template editor has three modes: Structure, Initial Content, and Policies
  • The page component renders the HTML document (<html>, <head>, <body>)
  • Component policies control allowed components, default settings, and style options
  • The Style System lets authors apply CSS classes without code changes
  • The responsive grid provides 12-column layout with breakpoints
  • Proxy components inherit from Core Components for easy customization
  • Templates are linked to sites via cq:conf, and gated by cq:allowedTemplates

Official Documentation

Next up: Client Libraries - CSS and JS management, clientlib categories, dependencies, embedding, proxy serving, and integration with the page component.