AEM Architect Skill
Enterprise-grade AEM solution design and implementation guidance.
Workflow Routing
Route to the appropriate workflow based on the request:
| Request Type | Workflow | Use When |
|---|---|---|
| Diagrams/Visualizations | workflows/AEMDiagrams.md | Architecture diagrams, flowcharts, sequence diagrams, ASCII art |
| Component Development | Main workflow below | Building new components, dialogs, HTL |
| Service/Backend | Main workflow below | OSGi services, Sling Models, servlets |
| Infrastructure | Main workflow below | Dispatcher, caching, CI/CD |
Diagram Request Detection
Use the AEMDiagrams workflow when the user mentions:
- •"diagram", "flowchart", "sequence diagram", "architecture diagram"
- •"visualize", "draw", "show me", "illustrate"
- •"mermaid", "ASCII art", "box diagram"
- •"component structure", "request flow", "cache flow"
- •"service dependencies", "class diagram", "state diagram"
Main Workflow
Follow this structured workflow for every AEM implementation request:
Phase 1: Requirements Gathering
Step 1.1: Ask for User Preference
First, ask the user:
"Would you like me to ask you some discovery questions to provide a more precise and tailored solution?
- •Yes - I'll ask targeted questions about your requirements
- •No - I'll proceed autonomously based on best practices and available context"
Step 1.2: Check for Attached Requirements
If the user has attached a file (.txt, .doc, .docx, or .md):
- •Read and analyze the file for requirements
- •Extract answers to the discovery questions below from the document
- •If user accepted questions in Step 1.1, ask additional precision questions for any gaps or ambiguities found
Step 1.3: Discovery Questions (if user accepted)
Ask relevant questions from these categories:
Component Architecture
- •Component type? (content, structural, container, navigation)
- •Extend AEM Core Components or fully custom?
- •Required dialog fields? (text, image, pathfield, multifield, nested)
- •Target environment? (author, publish, or both)
Performance & Caching
- •Expected traffic volume? (low, medium, high, enterprise-scale)
- •Caching strategy? (aggressive, moderate, dynamic)
- •CDN integration required?
Integration
- •Headless/hybrid JSON APIs required?
- •External service integrations?
- •GraphQL for Content Fragments?
- •SPA framework integration?
Phase 2: Analysis & Planning
Step 2.1: Present High-Level Overview
After gathering requirements (or analyzing autonomously), present:
Understanding Summary
Based on my analysis, here's what I understand about your requirements:
- •[Bullet points summarizing the project scope]
- •[Target environment and architecture]
- •[Key components and features needed]
- •[Performance and caching considerations]
- •[Integration points]
Step 2.2: Present TODO List
Create and present a numbered task list:
Implementation Plan
I will implement the following tasks:
- • Task 1: Description
- • Task 2: Description
- • Task 3: Description ...
Would you like to proceed with this plan, or do you have any changes to propose?
Step 2.3: Wait for User Approval
- •If user approves → Proceed to Phase 3
- •If user proposes changes → Update the plan and present again
- •Do NOT start implementation until user confirms
Phase 3: Implementation
Execute the approved TODO list:
- •Create component structure
- •Implement Sling Model with proper injectors
- •Design dialog using Granite UI patterns
- •Configure ClientLibs with bundling strategy
- •Set up Dispatcher rules
- •Provide testing guidance
Phase 4: Validation
Present completed work with:
- •Summary of what was implemented
- •File locations and structure
- •Testing recommendations
- •Cloud Manager quality gate considerations
Reference Documentation
Read the appropriate reference based on the task:
Workflows
| Workflow | File | Use When |
|---|---|---|
| AEM Diagrams | workflows/AEMDiagrams.md | Creating Mermaid or ASCII architecture diagrams |
Core References (in this skill)
| Topic | File | Use When |
|---|---|---|
| Architecture Patterns | references/architecture-deep-dive.md | Designing system architecture, scaling, MVC patterns |
| Cloud Service | references/cloud-service-guidelines.md | Developing for AEMaaCS, cluster-aware code, state management |
| Dialog Fields | references/dialog-field-types.md | Creating component dialogs with Granite UI |
| Dispatcher | references/dispatcher-configuration.md | Configuring filters, caching, load balancing |
| Performance | references/performance-optimization.md | Optimizing ClientLibs, Sling Models, caching |
| Sling Jobs | references/sling-jobs.md | Background task scheduling for Cloud Service |
| Testing Patterns | references/testing-patterns.md | Unit testing with AEM Mocks, JUnit 5 |
| Anti-Patterns | references/anti-patterns.md | Common mistakes and how to fix them |
| Code Snippets | references/code-snippets.md | Copy-paste ready code templates |
External Guides (in project root)
| Topic | File | Use When |
|---|---|---|
| Sling Models | aem-sling-models-guide.md | Model patterns, injectors, exporters |
| OSGi Services | aem-osgi-services-guide.md | Service design, dependency injection |
| Servlets | aem-servlets-guide.md | Endpoint patterns, security |
| Dialogs | aem-dialog-creation-guide.md | Granite UI, multifields, validation |
| ClientLibs | aem-clientlibs-guide.md | JS/CSS bundling, lazy loading |
| Dispatcher | aem-dispatcher-guide.md | Detailed cache configuration |
| Components | component-development.md | HTL, component structure |
| Best Practices | adobe-technical-practices.md | Adobe-recommended patterns |
Quick Reference: Component Creation
Component Structure
/apps/myproject/components/mycomponent/ ├── .content.xml # Component definition ├── _cq_dialog/.content.xml # Author dialog ├── _cq_editConfig.xml # Edit configuration ├── mycomponent.html # HTL template └── clientlib/ # Component CSS/JS
Component Definition
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
jcr:primaryType="cq:Component"
jcr:title="My Component"
jcr:description="Description"
componentGroup="My Project - Content"
sling:resourceSuperType="core/wcm/components/title/v3/title"/>
Sling Model Pattern
@Model(
adaptables = {Resource.class, SlingHttpServletRequest.class},
adapters = {MyComponent.class, ComponentExporter.class},
resourceType = MyComponentImpl.RESOURCE_TYPE,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME,
extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class MyComponentImpl implements MyComponent {
static final String RESOURCE_TYPE = "myproject/components/mycomponent";
@ValueMapValue
private String title;
@OSGiService
private MyService myService;
@Override
public String getTitle() { return title; }
}
Common Dialog Fields
| Field | Resource Type |
|---|---|
| Text | granite/ui/components/coral/foundation/form/textfield |
| Textarea | granite/ui/components/coral/foundation/form/textarea |
| Rich Text | cq/gui/components/authoring/dialog/richtext |
| Checkbox | granite/ui/components/coral/foundation/form/checkbox |
| Select | granite/ui/components/coral/foundation/form/select |
| Path | granite/ui/components/coral/foundation/form/pathfield |
| Image | cq/gui/components/authoring/dialog/fileupload |
| Multifield | granite/ui/components/coral/foundation/form/multifield |
For complete field examples, see references/dialog-field-types.md.
Caching Decision Tree
Is content personalized?
├── YES → No Dispatcher cache
│ └── Use client-side personalization or ESI
└── NO → Cache at Dispatcher
├── Static asset (JS/CSS/images)?
│ └── Long TTL (1 year) + content-hash
├── HTML content?
│ └── Moderate TTL (5-60 min) + statfileslevel
└── API/JSON?
├── Public → TTL based on freshness needs
└── Private → No Dispatcher cache
Statfileslevel Reference
| Structure | Level | Effect |
|---|---|---|
/content/site | 2 | Per-site invalidation |
/content/site/language | 3 | Per-language invalidation |
/content/site/region/country | 4 | Per-country invalidation |
Security Checklist
Dispatcher Filters (Default Deny)
/filter {
/0001 { /type "deny" /glob "*" }
/0100 { /type "allow" /method "GET" /url "/content/mysite/*" }
/0200 { /type "allow" /method "GET" /url "/etc.clientlibs/*" }
/0300 { /type "allow" /method "GET" /url "/content/dam/*" }
/0900 { /type "deny" /url "/bin/*" }
/0901 { /type "deny" /url "/system/*" }
/0902 { /type "deny" /url "*.infinity.json" }
}
Service User Pattern
try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(
Map.of(ResourceResolverFactory.SUBSERVICE, "myproject-service-user"))) {
// Minimal permissions operations
}
Cloud Service Specifics
When developing for AEMaaCS, always read references/cloud-service-guidelines.md for:
- •Cluster-aware code: Instances can stop anytime
- •No local state: Disk is ephemeral
- •Sling Jobs: For reliable background tasks
- •HTTP timeouts: Always set connect/read timeouts
- •Rate limiting: Handle 429 with exponential backoff
- •Touch UI only: No Classic UI support
- •Immutable repository:
/libsand/appsare read-only
CI/CD Quality Gates
| Gate | Checks | Action |
|---|---|---|
| Code Quality | SonarQube, code smells | Fix before merge |
| Security | Vulnerability scan | Immediate fix |
| Performance | Load test, response times | Review if fails |
Common Pitfalls
- •JCR queries in render path → Use content hierarchy traversal
- •Hardcoded paths → Use context-aware configuration
- •Unclosed ResourceResolvers → Use try-with-resources
- •Deep multifield nesting → Consider child nodes
- •Missing Dispatcher filters → Default-deny approach
- •Admin sessions in code → Use service users
- •Untested cache invalidation → Verify statfileslevel
- •Large inline dependencies → Lazy load heavy scripts
- •Skipping Core Components → Extend before building custom
- •Ignoring Cloud Manager gates → Fix locally first