For AI agents: the complete documentation index is available at https://nhanbe.id.vn/llms.txt, the full documentation bundle is available at https://nhanbe.id.vn/llms-full.txt, and this page is available as Markdown at https://nhanbe.id.vn/aem/foundation/templates-and-policies.md.

**Template**: determines **page structure*and **authoring regions**. **Policy**: determines **allowed components*+ **default/design options*+

Templates & Policies

Summary

  • Template: determines page structure and authoring regions.
  • Policy: determines allowed components + default/design options + Style System.
  • Together they create a governed authoring experience — authors have freedom within boundaries.

Main Storage:

ConceptPath (JCR)Managed By
Template Type/conf/<site>/settings/wcm/template-types/Dev + template admin
Editable Template/conf/<site>/settings/wcm/templates/Template author (UI)
Page/content/<site>/...Content author (UI)
Policies/conf/<site>/settings/wcm/policies/Template author / admin

Static vs Editable Templates

StaticEditable
Stored in/apps (code)/conf (configuration)
Who edits structureDevs onlyTemplate authors (UI)
Changes propagate to existing pagesNo (structure copied at creation time)Yes (structure + locked content remain live)
Policies / Style SystemNot supportedSupported
Recommended for new workNoYes
[Detect static template]

cq:template points to /apps/... path with cq:Template node → using static template. New projects — and all of AEMaaCS — must use editable templates.


Template Type

Template type = blueprint for editable templates. It defines:

  • Which page component renders the page
  • Initial structure (locked components every page gets)
  • Initial content (default content for new pages)
  • Initial policies (default component policies)
/conf/mysite/settings/wcm/template-types/
└── page/
    ├── .content.xml        # Template type definition
    ├── structure/
    │   └── .content.xml    # Locked layout
    ├── initial/
    │   └── .content.xml    # Initial content
    └── policies/
        └── .content.xml    # Default policies (seed)

Usually seeded via code packages and then managed in the UI.


Creating an Editable Template (UI)

Tools → General → Templates:

  1. Select config folder (/conf/<site>)
  2. Create → select Template Type (e.g. Page)
  3. Set title (e.g. Article Page) + name
  4. Open Template Editor → configure 3 modes

3 Modes in Template Editor

ModeWhat you editConsequence
Structurelocked layout + containers + mandatory componentsAuthors cannot move/delete/override locked items
Initial Contentdefault content for new pagesAuthors can edit after page creation
Policiesallowed components + design/style defaultsGoverns authoring

Checklist:

  • Structure
    • Layout container (responsive grid) for main region
    • Header/footer locked (if used)
    • Allowed components (via policy) for appropriate regions
  • Initial
    • Placeholder components (title, empty hero, pre-configured list…)
  • Policies
    • Allowed components per container
    • Style System groups (theme/spacing/size…)
    • Design dialog/policy fields of components (if applicable)
[Locked components]

Locked components show a lock icon — authors cannot move/delete/configure them.


Page Component (top-level renderer)

Every page in AEM is rendered by a page component — generating complete HTML documents.

/apps/<site>/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 (data-sly-resource)
  • Main content area — responsive grid where authors drop components
  • Client libraries — CSS in head, JS before </body>

Inherit Core Components page instead of rewriting everything.

/apps/<site>/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"/>

Override using extension points instead of rewriting the entire page:

/apps/<site>/components/page/customheaderlibs.html
<!-- Loaded inside <head> - used 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, ... -->
<link rel="preconnect" href="https://fonts.googleapis.com"/>
/apps/<site>/components/page/customfooterlibs.html
<!-- Loaded before </body> - used for JS -->
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
  <sly data-sly-call="${clientlib.js @ categories='mysite.site'}"/>
</sly>

Core Components page uses data-sly-include to look for these files in the resource type path. Since proxy component sets sling:resourceSuperType, Sling script resolution checks your component first then falls back to Core Component — placing files in your page component folder is sufficient.

Tip

Only override extension points while Core Components page handles HTML structure, SEO meta tags, and boilerplate.


Templates as Code (persist /conf)

Templates, template types, and policies reside under /conf. UI changes only exist on that environment until exported to the codebase.

  1. Build content package with filters pointing to template/policy paths:
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 exported XML into ui.content (or separate ui.conf module).
  2. Redeploy Dev/Stage/Prod — templates stay identical across all environments.
[Env drift]

Failure to persist → UI-only changes are lost on subsequent deployments (if /conf is overwritten), causing environments to drift.


Component Policies

Policies configure component behavior in templates. Per template, per container. Stored at /conf/&lt;site&gt;/settings/wcm/policies/ — useful for debugging or export.

Allowed Components

  1. Template editor → Structure mode
  2. Click layout container
  3. Click policy icon (wrench)
  4. Allowed Components — select allowed component groups/individual components

Prevents components from being placed in wrong regions — e.g. Hero not placed in sidebar.

Design Dialog (Policy) Values — currentStyle

Some components have design dialogs (policy dialogs) configuring default settings per template context:

  • Text — default rich text formatting options
  • Image — allowed image widths, lazy loading defaults
  • Container — layout options, background colors
ImageModel.java
@Model(adaptables = SlingHttpServletRequest.class)
public class ImageModel {

  @ScriptVariable
  private Style currentStyle;

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

Style System

Allows authors to apply CSS classes to components without developer intervention.

  1. Template editor → select component
  2. Open policy
  3. Styles → add style groups:
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 component toolbars — no code changes needed.

[Persistence]

All changes made via browser UI must be exported + persisted into git repository; otherwise they will be lost on redeploy.


Responsive Grid (Layout Container)

Primary layout mechanism:

  • Drag-and-drop placement
  • 12-column grid
  • Column resizing in authoring UI (Layout mode — ruler icon)
  • Breakpoints for responsive behavior
BreakpointWidth
Phone< 768px
Tablet768px - 1024px
Desktop> 1024px

Breakpoints configured in responsive grid policy (template editor → layout container → policy → breakpoint widths). Custom breakpoints can be defined in policy node wcm/foundation/components/responsivegrid under /conf.


Proxy Components

Most components in a project are proxy components inheriting Core Components — generated automatically by Maven archetype:

/apps/<site>/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"/>

Benefits:

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

Linking Site ↔ Templates

Templates must be enabled for site config (/conf/&lt;site&gt;):

  • Tool: Tools → General → Templates
  • Templates created here are available for pages under /content/mysite/
  • Sites and templates connect via jcr:content of site root:
/content/mysite/jcr:content
├── cq:conf = "/conf/mysite"             # Points to configuration folder
├── cq:allowedTemplates = [              # Regex(es) allowing templates here
│     "/conf/mysite/settings/wcm/templates/.*"
│   ]
  • cq:conf — connects site to config folder containing templates/policies.
  • cq:allowedTemplates — multi-value property regex patterns set on content root (typically site root or section folder).
[Troubleshoot "no templates available"]

Template only appears in Create Page dialog if path matches pattern and template is Enabled. "No templates available" → check cq:allowedTemplates first, then check template enabled/published status.

Set via UI: Page Properties → Advanced → Template Settings (Allowed Templates).


Page Creation Flow

When an author creates a page:


Quick Debug (JCR paths)

IssueQuick Check
Template doesn't applycq:template on page + cq:conf on site
"No templates available"cq:allowedTemplates site root + template enabled
Allowed components incorrectpolicy of exact container in template
Style option missingcomponent policy has Style System enabled
Default policy mismatchseed in template-types/&lt;type&gt;/policies vs policy override in editable template
UI changes lost after deploytemplate/policy not exported to ui.content

Official Documentation