Component Basics

In this chapter we will explore the underlying technology of an Adobe Experience Manager (AEM) Sites Component through a simple HelloWorld example. Small modifications will be made to an existing component, covering topics of authoring, HTL, Sling Models, Client-side libraries.


Review the required tooling and instructions for setting up a local development environment.

The IDE used in the videos is Visual Studio Code and the VSCode AEM Sync plugin.


  1. Learn the role of HTL templates and Sling Models to dynamically render HTML.
  2. Understand how Dialogs are used to facilitate authoring of content.
  3. Learn the very basics of Client-side libraries to include CSS and JavaScript to support a component.

What you will build

In this chapter you will perform several modifications to a very simple HelloWorld component. In the process of making updates to the HelloWorld component you will learn about the key areas of AEM component development.

Chapter Starter Project

This chapter builds upon a generic project generated by the AEM Project Archetype. Watch the below video and review the prerequisites to get started!


If you successfully completed the previous chapter you can re-use the project and skip the steps for checking out the starter project.

Open a new command line terminal and perform the following actions.

  1. In an empty directory, clone the aem-guides-wknd repository:

    $ git clone --branch tutorial/component-basics-start --single-branch

    Optionally, you can continue using the project generated in the previous chapter, Project Setup.

  2. Navigate into the aem-guides-wknd folder.

    $ cd aem-guides-wknd
  3. Build and deploy the project to a local instance of AEM with the following command:

    $ mvn clean install -PautoInstallSinglePackage

    If using AEM 6.5 or 6.4, append the classic profile to any Maven commands.

    $ mvn clean install -PautoInstallSinglePackage -Pclassic
  4. Import the project into your preferred IDE by following the instructions to set up a local development environment.

Component Authoring

Components can be thought of as small modular building blocks of a web page. In order to re-use components, the components must be configurable. This is accomplished via the author dialog. Next we will author a simple component and inspect how values from the dialog are persisted in AEM.

Below are the high level steps performed in the above video.

  1. Create a new page named Component Basics beneath WKND Site > US > en.
  2. Add the Hello World Component to the newly created page.
  3. Open the dialog for the component and enter some text. Save the changes to see the message displayed on the page.
  4. Switch in to developer mode and view the Content Path in CRXDE-Lite and inspect the properties of the component instance.
  5. Use CRXDE-Lite to view the cq:dialog and helloworld.html script located at /apps/wknd/components/content/helloworld.

HTL (HTML Template Language) and Dialogs

HTML Template Language or HTL is a light-weight, server-side templating language used by AEM components to render content.

Dialogs define the configurations available that can be made for a component.

Next we will update the HelloWorld HTL script to display an additional greeting before the text message.

Below are the high level steps performed in the above video.

  1. Switch to the IDE and open the project to the ui.apps module.

  2. Open the helloworld.html file and make a change to the HTML Markup.

  3. Use the IDE tools like VSCode AEM Sync to synchronize the file change with the local AEM instance.

  4. Return to the browser and observe the component render has changed.

  5. Open the .content.xml file that defines the dialog for the HelloWorld component at:

  6. Update the dialog to add an additional textfield named Title with a name of ./title:

    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="" xmlns:cq="" xmlns:jcr="" xmlns:nt=""
            <items jcr:primaryType="nt:unstructured">
                    <items jcr:primaryType="nt:unstructured">
  7. Re-open the file helloworld.html, which represents the main HTL script responsible for rendering the HelloWorld component, located at:

  8. Update helloworld.html to render the value of the Greeting textfield as part of an H1 tag:

    <div class="cmp-helloworld" data-cmp-is="helloworld">
        <h1 class="cmp-helloworld__title">${properties.title}</h1>
  9. Deploy the changes to a local instance of AEM using the developer plugin or using your Maven skills.

Sling Models

Sling Models are annotation driven Java “POJO’s” (Plain Old Java Objects) that facilitate the mapping of data from the JCR to Java variables, and provide a number of other niceties when developing in the context of AEM.

Next, we will make some updates to the HelloWorldModel Sling Model in order to apply some business logic to the values stored in the JCR before outputting them to the page.

  1. Open the file, which is the Sling Model used with the HelloWorld component.

  2. Add the following import statements:

    import org.apache.commons.lang.StringUtils;
  3. Update the @Model annotation to use a DefaultInjectionStrategy:

    @Model(adaptables = Resource.class,
       defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
       public class HelloWorldModel {
  4. Add the following lines to the HelloWorldModel class to map the values of the component’s JCR properties title and text to Java variables:

    @Model(adaptables = Resource.class,
    defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
    public class HelloWorldModel {
        private String title;
        private String text;
        protected void init() {
  5. Add the following method getTitle() to the HelloWorldModel class, that returns the value of the property named title. This method adds the additional logic to return a String value of “Default Value here!” if the property title is null or blank:

    * @return the value of title, if null or blank returns "Default Value here!"
    public String getTitle() {
        return StringUtils.isNotBlank(title) ? title : "Default Value here!";
  6. Add the following method getText() to the HelloWorldModel class, that returns the value of the property named text. This method transforms the String to all uppercase characters.

        * @return All caps variation of the text value
    public String getText() {
        return StringUtils.isNotBlank(this.text) ? this.text.toUpperCase() : null;
  7. Build and deploy the bundle from the core module:

    $ cd core
    $ mvn clean install -PautoInstallBundle

    If using AEM 6.4/6.5 use mvn clean install -PautoInstallBundle -Pclassic

  8. Update the file helloworld.html at aem-guides-wknd.ui.apps/src/main/content/jcr_root/apps/wknd/components/content/helloworld/helloworld.html to use the newly created methods of the HelloWorld model:

    <div class="cmp-helloworld" data-cmp-is="helloworld"
        <h1 class="cmp-helloworld__title">${model.title}</h1>
        <div class="cmp-helloworld__item" data-sly-test="${properties.text}">
            <p class="cmp-helloworld__item-label">Text property:</p>
            <pre class="cmp-helloworld__item-output" data-cmp-hook-helloworld="property">${properties.text}</pre>
        <div class="cmp-helloworld__item" data-sly-test="${model.text}">
            <p class="cmp-helloworld__item-label">Sling Model getText() property:</p>
            <pre class="cmp-helloworld__item-output" data-cmp-hook-helloworld="property">${model.text}</pre>
        <div class="cmp-helloworld__item"  data-sly-test="${model.message}">
            <p class="cmp-helloworld__item-label">Model message:</p>
            <pre class="cmp-helloworld__item-output"data-cmp-hook-helloworld="model">${model.message}</pre>
  9. Deploy the changes to a local instance of AEM using the Eclipse Developer plugin or using your Maven skills.

Client-Side Libraries

Client-Side Libraries, clientlibs for short, provides a mechanism to organize and manage CSS and JavaScript files necessary for an AEM Sites implementation. Client-side libraries are the standard way to include CSS and JavaScript on a page in AEM.

Next, we will include some CSS styles for the HelloWorld component in order to understand the very basics of client-side libraries.

Below are the high level steps performed in the above video.

  1. beneath /aem-guides-wknd.ui.apps/src/main/content/jcr_root/apps/wknd/clientlibs create a new folder named clientlib-helloworld.

  2. Create a folder and file structure like the following beneath clientlibs

  3. Populate helloworld.css with the following:

    .cmp-helloworld .cmp-helloworld__title {
        color: red;
  4. Populate helloworld/clientlibs/css.txt with the following:

  5. Populate helloworld/clientlibs/js/helloworld.js with the following:

    console.log("Hello World from Javascript!");
  6. Populate helloworld/clientlibs/js.txt with the following:

  7. Update the clientlib-helloworld/.content.xml file to include the following properties:

    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:cq="" xmlns:jcr=""
        categories="[wknd.helloworld]" />
  8. Update the clientlibs/clientlib-base/.content.xml file to embed the wknd.helloworld category:

    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:cq="" xmlns:jcr=""
  9. Deploy the changes to a local instance of AEM using the developer plugin or using your Maven skills.


    CSS and JavaScript are frequently cached by the browser for performance reasons. If you do not immediately see the change for the client library perform a hard refresh and clear the browser’s cache. It may be helpful to use an incognito window to ensure a fresh cache.


Congratulations, you have just learned the basics of component development in Adobe Experience Manager!

Next Steps

Get familiar with Adobe Experience Manager pages and templates in the next chapter Pages and Templates. Understand how Core Components are proxied into the project and learn advanced policy configurations of editable templates to build out a well-structured Article Page template.

View the finished code on GitHub or review and deploy the code locally at on the Git branch tutorial/component-basics-solution.

On this page