N
Naveenr.dev
Chapter 07
19 min read2026-06-21

Understanding AEM Component Architecture

Learn how all AEM concepts work together. Understand component authoring, component rendering, component anatomy, and why architects think about components as rendering pipelines. Discover the complete lifecycle from author to browser.

Content Objective

  • Understand how components work end-to-end
  • Learn the difference between authoring and rendering lifecycle
  • Discover component anatomy and internal structure
  • Understand how resourceType connects content to implementation
  • Learn component inheritance patterns
  • Master production troubleshooting strategies
  • See how all previous chapters fit together

The Journey So Far

In the previous chapters, we learned individual pieces of the AEM architecture:

  • Chapter 1: How requests flow through Dispatcher to AEM
  • Chapter 2: How ResourceResolver finds content
  • Chapter 3: How Components are resolved and scripts are located
  • Chapter 4: How request paths are decomposed (selectors, extensions, suffixes)
  • Chapter 5: How Sling Models adapt resources into Java objects
  • Chapter 6: How HTL generates the final HTML

You now understand every piece individually.

But how do they all work together?

This chapter ties everything together into a coherent picture of how AEM really works.

A Real Example: Adding a Title Component

Let's follow a simple scenario from start to finish.

Imagine an author opens a page in AEM:

  1. The author drags a Title component onto the page
  2. They enter: "Welcome To AEM"
  3. They click Save

A few seconds later the title appears on the page.

Simple.

But what actually happened?

  • Where was the content stored?
  • How did AEM know which component to render?
  • How did Sling Models get involved?
  • How did HTL generate the final HTML?

This simple example demonstrates the complete AEM rendering pipeline.

What Really Happens When a Component Is Added

Almost any AEM website contains a collection of content blocks: header, navigation menu, hero banner, title, image, carousel, teaser, and footer.

To an end user, these appear to be part of a single web page.

However, AEM does not treat a page as one large piece of content.

Instead, AEM treats a page as a collection of smaller reusable building blocks called components.

Each component has a specific responsibility and can be reused across many pages.

This approach allows authors to build complex pages without requiring developers to create a new template for every business requirement.

The Authoring Phase

When an author saves a component to a page, AEM does not generate and store HTML.

Instead, AEM stores structured content inside the JCR repository.

A simplified example might look like this:

/content/site/en/home/jcr:content/root/title
│
├── sling:resourceType = project/components/title
└── title = Welcome To AEM

This is one of the most important concepts in AEM:

When authors create content, they are not creating web pages. They are creating content that is stored in the repository and can later be rendered in different ways.

Component vs Content

Many AEM developers confuse components and content.

Component = Code

/apps/project/components/title

Content = Data

/content/site/en/home/jcr:content/root/title

The component contains the implementation that knows how to render a title.

The content node contains the actual values entered by the author.

This separation is one of the reasons AEM scales effectively. A single Title component can be reused across thousands of pages, while each page stores its own content independently.

The Role of resourceType

Notice that the repository stores two important pieces of information:

  1. The author-entered value:

    title = Welcome To AEM
    
  2. The component reference:

    sling:resourceType = project/components/title
    

The title property stores the content.

The sling:resourceType property identifies which component should render that content.

The dialog itself does not store any data. Its responsibility is simply to collect input from the author and write that information into the repository.

The repository then becomes the source of truth for everything that appears on the page.

At this stage, nothing has been rendered yet. AEM has only stored content and information about which component should eventually render it.

A Component Is Not Just HTML

Although HTML is part of a component, it is only the final output.

A complete AEM component consists of multiple layers working together:

  • Content - Author-entered data stored in the repository
  • Configuration - How the component behaves in AEM
  • Business Logic - Typically implemented using Sling Models and services
  • Presentation - Generated through HTL
  • Styling - Provided through CSS delivered via Clientlibs
  • Client Behavior - JavaScript delivered via Clientlibs

Together, these pieces form a reusable component that can be authored, rendered, and maintained independently.

Component Anatomy: Inside a Real Component

Now that we understand how AEM locates and renders components, let's look inside an actual component.

Consider a simple Title component:

/apps/project/components/title

├── .content.xml
├── cq:dialog
├── title.html
├── _cq_editConfig.xml
└── clientlibs
    └── css
        └── title.css

Each piece has a specific responsibility:

  • cq:dialog - Collects author input
  • title.html - HTL script that generates markup
  • .content.xml - Component metadata and configuration
  • _cq_editConfig.xml - Edit configuration (edit bars, in-place editing)
  • clientlibs - CSS and JavaScript for the component

Note: The Sling Model is typically stored in the core module of the project rather than inside the component folder:

core/src/main/java/com/project/core/models/TitleModel.java

Dialog Is Only An Authoring Tool

One of the most common misconceptions among new AEM developers is that the dialog is the component.

In reality, the dialog is only an authoring interface.

Its responsibility is to collect input from authors and store that information in the repository.

When an author enters a title through a dialog and clicks Save, the dialog does not generate HTML and does not participate in rendering.

Its job ends once the content is written to the JCR.

The rendering process happens later when Sling reads the stored content and resolves the appropriate component implementation.

A simplified flow:

  • Author → Dialog → Repository (At this stage, no rendering has occurred)

Component Behavior: Author vs Publish

Before we look at the rendering process, understand that components behave slightly differently on Author and Publish environments.

The component itself remains the same.

The content remains the same.

The rendering process remains largely the same.

However, Author includes additional capabilities designed for content authors:

  • Edit bars
  • Component placeholders
  • Dialogs
  • WCM Mode functionality
  • Drag-and-drop editing

These features help authors create and manage content.

On Publish, these authoring capabilities are removed.

Visitors only receive the final rendered experience.

This distinction becomes important when troubleshooting issues that appear only on one environment.

A component may render correctly on Author but behave differently on Publish due to:

  • Permissions
  • Content replication
  • Client libraries
  • Environment-specific configurations

How Rendering Actually Happens

So far we have followed the authoring side of the journey.

Now let's look at what happens when a visitor requests the page.

Suppose a browser requests:

/content/site/en/home.html

At a high level, Sling performs the following steps:

How Rendering Actually Happens
How Rendering Actually Happens

Sling begins by locating the requested page resource.

It then traverses through the child resources that make up the page.

For each resource, Sling reads the sling:resourceType value and locates the corresponding component implementation.

If a Sling Model is associated with the component, the model is adapted and used to prepare data.

HTL then consumes that data and generates the final HTML output.

The browser never sees Sling Models, HTL files, or repository content.

It only receives the final HTML generated by the rendering process.

How AEM Builds a Complete Page

A real page rarely contains just one component.

A typical page might contain:

/content/site/en/home/jcr:content

├── header
├── navigation
├── hero
├── title
├── image
├── teaser
└── footer

During rendering, Sling processes each resource one by one:

  1. Locates the appropriate component implementation
  2. Executes the rendering logic
  3. Generates HTML for that component

The final HTML sent to the browser is the combined output of all these individual components.

This component-based rendering model is one of the reasons AEM can support highly flexible page layouts while still promoting component reuse across large websites.

How AEM Build Page
How AEM Build Page

Component Inheritance

Adobe Core Components are the most common example of component inheritance in modern AEM projects.

Not every component is built from scratch.

Many components inherit functionality from existing components using sling:resourceSuperType.

For example, a custom Title component might inherit from the Core Component Title implementation and only override specific behavior.

This reduces duplication and encourages consistency across large projects.

As discussed in Chapter 3, when Sling cannot find a script or configuration in the current component, it can continue searching through the resourceSuperType chain.

This allows developers to override only the functionality they need while reusing the rest of the implementation.

Real Example: Extending Core Components

A common pattern is extending the Core Component Title.

Instead of copying the entire implementation, a project creates its own Title component and sets the Core Component Title as its resourceSuperType.

The custom component can then override only the pieces it needs while continuing to inherit future improvements from the Core Component implementation.

Benefits:

  • Core updates automatically inherited
  • Only maintain customizations
  • Reduced maintenance burden
  • Better long-term sustainability

Why Clientlibs Exist

Rendering HTML alone is often not enough to create a complete user experience.

Consider a Carousel component.

The component may successfully generate HTML, but:

  • Without CSS, the carousel will not be styled correctly
  • Without JavaScript, it will not provide interactive behavior (sliding between items)

This is where Clientlibs become important.

Clientlibs allow components to package CSS and JavaScript alongside their rendering logic.

During page rendering, AEM can include the required client-side assets so that the component functions correctly in the browser.

This separation keeps presentation logic organized while allowing components to remain reusable and self-contained.

Complete Rendering Flow: Title Component

Let's revisit our Title component and follow its complete journey:

Author enters: "Welcome To AEM"
↓
Dialog stores value in repository
↓
Request arrives: GET /content/site/en/home.html
↓
Sling locates resource
↓
Sling reads resourceType = project/components/title
↓
Component resolver finds /apps/project/components/title
↓
Sling Model adapts resource to TitleModel
↓
Model retrieves title value from repository
↓
HTL receives model and generates: <h1>Welcome To AEM</h1>
↓
Browser receives HTML

This simple example demonstrates the complete flow integrating all concepts from Chapters 1-6.

Two Different Lifecycles

A useful architectural distinction is the difference between two separate lifecycles:

Authoring Lifecycle

Focuses on content creation:

  • Author → Dialog → Save Content

Rendering Lifecycle

Focuses on content delivery:

  • Request → Resource → resourceType → Sling Model → HTL → HTML

Although these lifecycles are related, they occur at different times and serve different purposes.

Separating them mentally makes many AEM concepts easier to understand.

Production Troubleshooting Strategy

When a component does not render correctly, experienced developers rarely start by inspecting HTL.

Instead, they validate each stage of the rendering pipeline.

A typical troubleshooting sequence:

  • Resource exists?

  • resourceType present?

  • Component path exists? (/apps/)

  • Model adapting correctly?

  • HTL executing?

  • Clientlibs loading?

By following the same order Sling uses internally, root causes can often be identified much faster.

Troubleshooting Checklist

CheckWhat to VerifyCommon Issues
Resource existsDid ResourceResolver find the content?Content not replicated to Publish
resourceType setDoes resource have sling:resourceType?Missing or typo in property
Component pathDoes /apps/{resourceType} exist?Not deployed; path mismatch
HTL scriptDoes title.html exist?Missing script file
Script resolutionDo selectors/extensions match request?Wrong request path; selector mismatch
Model adaptsDoes resource.adaptTo(Model.class) work?Required fields missing; annotations wrong
Injections workAre @ValueMapValue fields populated?Property names don't match
Clientlibs loadAre CSS/JS included on page?Missing clientlib categories
PermissionsDoes user have read access?Content only visible to certain users
LogsAre there errors in error.log?Check AEM logs for exceptions

Why Architects Think Differently

Architects rarely look at components as folders.

They look at them as rendering pipelines.

The Mental Model:

  • Content (Repository)

  • resourceType (Pointer)

  • Component Implementation (/apps)

  • Sling Model (Business Logic)

  • HTL (Presentation)

  • Clientlibs (Styling & Behavior)

  • HTML (Output)

Key insight: The repository does not store references to HTL files, Java classes, or client-side assets.

Instead, it stores a single sling:resourceType value.

That single property acts as a pointer that tells Sling which component should render the content.

This design keeps content independent from implementation details and allows components to evolve without modifying stored content.

The Troubleshooting Mindset

Experienced AEM architects rarely troubleshoot components by opening HTL first.

Instead they trace the rendering chain:

  1. Does the resource exist?
  2. Does it have a resourceType?
  3. Can Sling find the component implementation?
  4. Can the Sling Model adapt correctly?
  5. Is HTL executing without errors?
  6. Are clientlibs loading?

This approach makes root-cause analysis significantly faster because it follows the same sequence Sling uses internally.

Key Takeaways

  • Components are reusable building blocks, not monolithic pages
  • Content and code are separated — components implement; content stores data
  • sling:resourceType is the bridge between content and implementation
  • Authoring and rendering are separate lifecycles occurring at different times
  • Component anatomy includes dialog, HTL, Sling Model, clientlibs, and metadata
  • Dialog is only for authoring; rendering is completely independent
  • Author and Publish environments have different capabilities
  • Component inheritance through resourceSuperType reduces duplication
  • Clientlibs package CSS/JavaScript with components for complete functionality
  • Troubleshooting should follow the rendering pipeline, not jump to code
  • Architects think of components as rendering pipelines, not code folders

What Happens Next?

In this chapter, we tied together everything you've learned about request flow, resources, components, Sling Models, and HTL.

Now we're ready to explore how AEM scales for enterprise websites:

  • Chapter 8: Understanding AEM Templates — How page structures are defined and governance is enforced
  • Chapter 9: Custom Servlets and REST APIs — Building dynamic endpoints beyond traditional component rendering
  • Chapter 10: Workflows and Content Publishing — Automating content approval and distribution

The foundation is complete. Advanced topics will build naturally on what you've learned.

You now understand not just the individual pieces of AEM, but how they work together to deliver content at scale.