Loading...
Loading...
Build, extend, and configure AEM components end-to-end. Covers component node structure (cq:Component), Touch UI dialogs (cq:dialog with Granite UI), Sling Models, client libraries, edit configuration (cq:editConfig), and content templates. Use when creating new AEM components, adding or modifying component dialogs, wiring Sling Models, setting up clientlibs, extending Core Components, configuring edit behavior, or troubleshooting component rendering. Also activate when the user mentions cq:Component, cq:dialog, componentGroup, Granite UI widgets, or AEM component architecture.
npx skill4agent add headwirecom/aem-agent-skills aem-component-developmentcq:Component.htmlcq:dialogcq:editConfightl-scriptingui.apps/src/main/content/jcr_root/apps/<project>/components/<component-name>/
├── .content.xml ← cq:Component definition (title, group, supertype)
├── <component-name>.html ← HTL rendering script
├── _cq_dialog/
│ └── .content.xml ← Touch UI dialog (Granite UI)
├── _cq_editConfig/
│ └── .content.xml ← Edit behavior config
├── _cq_template/
│ └── .content.xml ← Default content on drag-and-drop
├── _cq_design_dialog/
│ └── .content.xml ← Policy/design dialog
└── clientlib/ ← Optional co-located clientlib
├── .content.xml
├── css.txt
├── js.txt
├── css/
└── js/
core/src/main/java/<package>/models/
└── <ComponentName>Model.java ← Sling Model_cq_dialogcq:dialog.content.xml<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Component"
jcr:title="My Component"
jcr:description="A description for authors"
componentGroup="My Project - Content"
sling:resourceSuperType="core/wcm/components/text/v2/text"/>| Property | Purpose |
|---|---|
| Display name in component browser |
| Tooltip in component browser |
| Grouping in component browser. Use |
| Inherit from another component (rendering, dialog, edit config) |
| |
| Coral UI icon name for the component browser |
| 2-char abbreviation if no icon |
.content.xmljcr:primaryType="cq:Component"sling:resourceSuperTypecore/@Model(adaptables = SlingHttpServletRequest.class,
adapters = MyComponent.class,
resourceType = "myproject/components/mycomponent",
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class MyComponentImpl implements MyComponent {
@ValueMapValue
private String title;
@ValueMapValue
private String description;
@Override
public String getTitle() { return title; }
@Override
public String getDescription() { return description; }
}<sly data-sly-use.model="com.myproject.core.models.MyComponent"/>
<div class="cmp-mycomponent"
data-sly-test="${model.title || model.description}">
<h2 class="cmp-mycomponent__title"
data-sly-test="${model.title}">${model.title}</h2>
<div class="cmp-mycomponent__description"
data-sly-test="${model.description}">
${model.description @ context='html'}
</div>
</div>
<sly data-sly-test="${!model.title && !model.description && (wcmmode.edit || wcmmode.preview)}">
<div class="cq-placeholder" data-emptytext="My Component"></div>
</sly><?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:cq="http://www.day.com/jcr/cq/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="My Component"
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">
<properties jcr:primaryType="nt:unstructured"
jcr:title="Properties"
sling:resourceType="granite/ui/components/coral/foundation/container"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<columns jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<column jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<title jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Title"
name="./title"/>
<description jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Description"
name="./description"/>
</items>
</column>
</items>
</columns>
</items>
</properties>
</items>
</tabs>
</items>
</content>
</jcr:root><?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:EditConfig"
cq:actions="[edit,delete,insert,copymove]"
cq:layout="editbar"
cq:dialogMode="floating">
<cq:listeners jcr:primaryType="cq:EditListenersConfig"
afteredit="REFRESH_PAGE"
afterinsert="REFRESH_PAGE"/>
</jcr:root>sling:resourceSuperType<jcr:root ...
jcr:primaryType="cq:Component"
jcr:title="Custom Text"
sling:resourceSuperType="core/wcm/components/text/v2/text"
componentGroup="My Project"/>_cq_dialog/sling:resourceSuperTypecmp-<name>__<element>--<modifier>core/wcm/components/text/v2/textcore/wcm/components/image/v3/imagecore/wcm/components/title/v3/titlecore/wcm/components/teaser/v2/teasercore/wcm/components/list/v4/listcore/wcm/components/container/v1/containercore/wcm/components/page/v3/page<!--/* Reusable Core Components placeholder template */-->
<sly data-sly-use.template="core/wcm/components/commons/v1/templates.html"
data-sly-call="${template.placeholder @ isEmpty=!model.hasContent}"/><div class="cq-placeholder" data-emptytext="${component.properties.jcr:title}"
data-sly-test="${(wcmmode.edit || wcmmode.preview) && isEmpty}"></div>_cq_template/<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="nt:unstructured"
title="Default Title"
description="Edit this component"/>sling:resourceTypesling:resourceType = "myproject/components/hero"/apps/myproject/components/hero/hero.htmlsling:resourceSuperType/libs/myproject/components/herohero.htmlhtml.htmlGET.htmlsling:resourceSuperTypecq:dialogWCMUsePojo/libs/appscmp-<component>__<element>--<modifier>componentGroup./namename="./title"/appsallowProxy=true/etc.clientlibs/