Set up development tools set-up-development-tools

Adobe Experience Manager (AEM) development requires a minimal set of development tooling to be installed and set up on the developer machine. These tools support the development and building of AEM Projects.

Note that ~ is used as shorthand for the User’s Directory. In Windows, this is the equivalent of %HOMEPATH%.

Install Java

Experience Manager is a Java application, and thus requires the Java SDK to support the development and the AEM as a Cloud Service SDK.

  1. Download and install the latest release Java 11 SDK
  2. Verify Oracle Java 11 SDK is installed by running the command:
code language-shell
$ java --version
code language-shell
$ java -version
code language-shell
$ java --version


Install Homebrew

The use of Homebrew is optional, but recommended.

Homebrew is a open-source package manager for macOS, Windows and Linux. All the supporting tools can be installed separately, Homebrew provides a convenient way to install and update a variety of development tools required for Experience Manager development.

  1. Open your Terminal
  2. Check if Homebrew is already installed by running the command: brew --version.
  3. If Homebrew is not installed, install Homebrew

Homebrew on macOS requires Xcode or Command Line Tools, install-able via the command:

code language-shell
$ xcode-select --install
Install Homebrew on Windows 10
Install Homebrew on Linux
  1. Verify Homebrew is installed by running the command: brew --version


If you are using Homebrew, follow the Install using Homebrew instructions in the sections below. If you are not using Homebrew, install the tools using the OS-specific links.

Install Git

Git is the source control management system used by Adobe Cloud Manager, and thus is required for development.

Install Git using Homebrew
  1. Open your Terminal/Command Prompt

  2. Execute the command: $ brew install git

  3. Verify Git is installed, using the command: $ git --version

Download and install Git
  1. Download and install Git

  2. Open your Terminal/Command Prompt

  3. Verify Git is installed, using the command: $ git --version


Install Node.js (and npm) node-js

Node.js is a JavaScript runtime environment used to work with the front-end assets of an AEM project’s ui.frontend sub-project. Node.js is distributed with npm, is the defacto Node.js package manager, used to manage JavaScript dependencies.

Install Node.js using Homebrew
  1. Open your Terminal/Command Prompt

  2. Execute the command: $ brew install node

  3. Verify Node.js is installed, using the command: $ node -v

  4. Verify npm is installed, using the command: $ npm -v

Download and install Node.js
  1. Download and install Node.js

  2. Open your Terminal/Command Prompt

  3. Verify Node.js is installed, using the command: $ node -v

  4. Verify npm is installed, using the command: $ npm -v

Node.js and npm

AEM Project Archetype-based AEM Projects install an isolated version of Node.js at build time. It is good to keep the local development system’s version in sync (or close to) the Node.js and npm versions specified in your AEM Maven project’s Reactor pom.xml.
See this example AEM Project Reactor pom.xml for where to locate the Node.js and npm build versions.

Install Maven

Apache Maven is the open-source Java command-line tool used to build AEM Projects generated from the AEM Project Maven Archetype. All major IDE’s (IntelliJ IDEA, Visual Studio Code, Eclipse, etc.) have integrated Maven support.

Install Maven using Homebrew
  1. Open your Terminal/Command Prompt

  2. Execute the command: $ brew install maven

  3. Verify Maven is installed, using the command: $ mvn -v

Download and install Maven
  1. Download Maven

  2. Install Maven

  3. Open your Terminal/Command Prompt

  4. Verify Maven is installed, using the command: $ mvn -v


Set up Adobe I/O CLI aio-cli

The Adobe I/O CLI, or aio, provides command line access to a variety of Adobe services, including Cloud Manager and Asset Compute. The Adobe I/O CLI plays an integral role in development on AEM as a Cloud Service as it provides developers the ability to:

Install the Adobe I/O CLI

  1. Ensure Node.js is installed as the Adobe I/O CLI is an npm module
    • Run node --version to confirm
  2. Execute npm install -g @adobe/aio-cli to install the aio npm module globally

Set up the Adobe I/O CLI Cloud Manager plugin aio-cloud-manager

The Adobe I/O Cloud Manager plugin allows the aio CLI to interact with Adobe Cloud Manager via the aio cloudmanager command.

  1. Execute aio plugins:install @adobe/aio-cli-plugin-cloudmanager to install the aio Cloud Manager plug-in.

Set up the Adobe I/O CLI authentication

In order for the Adobe I/O CLI to communicate with Cloud Manager, a Cloud Manager integration must be created in Adobe I/O Console, and credentials must be obtained to successfully authenticate.

  1. Log in to

  2. Ensure your Organization that includes the Cloud Manager product to connect to is active in the Adobe Organization switcher

  3. Create a new or open an existing Adobe I/O program

    • Adobe I/O Console projects are simply organizational groupings of integrations, create or use and existing project based on how you want to manage your integrations.
    • If creating a new project, select “Empty Project” if prompted (vs. “Create from Template”)
    • Adobe I/O Console programs are different concepts to Cloud Manager programs
  4. Create a new Cloud Manager API integration

    • Select the deprecated “Service Account (JWT)” authentication type (OAuth is not supported for the CLI at this time).
    • Create or upload keys.
    • Select the “Developer - Cloud Service” product profile
  5. Obtain the Service Account (JWT) credentials needs to populate Adobe I/O CLI’s config.json

    code language-json
       "client_id": "Client ID from Service Account (JWT) credential",
       "client_secret": "Client Secret from Service Account (JWT) credential",
       "technical_account_id": "Technical Account ID from Service Account (JWT) credential",
       "ims_org_id": "Organization ID from Service Account (JWT) credential",
       "meta_scopes": [
  6. Load the config.json file into the Adobe I/O CLI

    • $ aio config:set ims.contexts.aio-cli-plugin-cloudmanager ./path/to/config.json --file --json
  7. Load the private.key file into the Adobe I/O CLI

    • $ aio config:set ims.contexts.aio-cli-plugin-cloudmanager.private_key ./path/to/private.key --file

Begin executing commands for Cloud Manager via the Adobe I/O CLI.

Set up the AEM Rapid Development Environment plugin rde

The AEM Rapid Development Environment plugin allows the aio CLI to interact with AEM as a Cloud Service Rapid Development Environments via the aio aem:rde command.

  1. Execute aio plugins:install @adobe/aio-cli-plugin-aem-rde to install the AEM Rapid Development Environments plugin.

Set up the Adobe I/O CLI Asset Compute plugin aio-asset-compute

The Adobe I/O Cloud Manager plugin allows the aio CLI to generate and run Asset Compute workers via the aio asset-compute command.

  1. Execute aio plugins:install @adobe/aio-cli-plugin-asset-compute to install the aio Asset Compute plug-in.

Set up the development IDE

AEM development primarily consists of Java and Front-end (JavaScript, CSS, etc) development and XML management. The following are the most popular IDEs for AEM development.

IntelliJ IDEA

IntelliJ IDEA is a powerful IDE for Java development. IntelliJ IDEA comes in two flavors, a free Community edition and a commercial (paid) Ultimate version. The free Community version is sufficient for AEM development, however the Ultimate expands its capability set.

In this video we’ll be taking a look at AEM development using the IntelliJ IDE. We’ll be using the Community Edition for this video. But if you have a license for the Ultimate, which is a commercial paid version, you can absolutely use that as well. So before we jump into IntelliJ, I’ll show you what I have setup here. So I am running an AEM instance on port 4502 that is a fresh install. So this only has the We.Retail site and no other custom installations. So in this video we’ll be using the wknd sites project as our code base and we’ll be building and installing that into our AEM instance. The last quick piece of setup that I want to go through is showing you how to update your settings at XML file for Maven to include the Adobe Public Repo. And the Adobe Public Repo contains all of the necessary libraries that you’re gonna need in order to build an AEM project. So at, it lists out the configuration needed for the Adobe Public Repo profile. So we can simply copy and paste this into our settings XML file. Open up the settings.xml. Mine is empty, I’ve actually just copied this from the Apache Maven website, so it has the bare-bone structure here. And what we’re gonna do is simply paste in the profile that we copied from So let’s go ahead and just set our Adobe public profile to be the active profile and save our changes. So let’s start up IntelliJ and load in the wknd project. I’ve already cloned the wknd project into my code folder. So here’s our AEM guides of wknd project, including all the sub and even projects as well. Let’s fire up IntelliJ. We’re going to import our project because it is not yet an IntelliJ project, so we can’t simply open it. We want to select the base project folder. So we’ll select AEM - guides - wknd which contains all of these sub projects. It’s important that you select import projects from an external model and you pick Maven. Because this is a multi-module Maven project, my IntelliJ will be able to use this selection in order to properly extract all of the projects and set up the IntelliJ project properly. Since it is a multi-module Maven project, let’s search the project recursively to make sure we load all of these sub-projects. Just to show you really quickly under environment settings, we’re currently using the bundled Maven, if you’ve installed another version of Maven through Homebrew or some other means, you can feel free to use that. Especially if it is newer than the bundle Maven version. Under user settings file, it is pointing to our settings that XML file that we just updated with the Adobe public profile. The Adobe public profile is active by default, so this is checked here and we have some other ones that are provided by the wknd project. We’re gonna leave these unchecked, but we’ll be using these later on. So we are going to import the discovered projects. I’ll be using Java 8. This is the default. Let’s enable auto-import, so we don’t have to worry about sinking in Maven artifacts. IntelliJ will automatically detect if they’re missing and do it for us. Now, if we look at our project in IntelliJ, we see that we have our main reactor project here, along with all the sub projects, including core, which has our share bundle, our UI apps, which is our content project that deploys into the /apps folder, as well as UI content, which actually has the content that drives the wknd site. The last piece we’ll take a look at is over here on the right side, so under our Maven tab. IntelliJ will have inspected all of the Maven projects and sub projects and build out this tree, allowing us to interact with the different projects in different ways. So under profiles, we have all of the profiles, including the default active profile that we set, and then we have these other profiles that were provided by the wknd project that are going to allow us to install our artifacts to AEM in different ways. So auto-install bundle is going to install the OSGi bundle. So if we only make changes to that, we can use our auto-install bundle to deploy those. Auto-install package will install the content package before the project. Auto-install package publish will install the package to localhost for 503 if we have that running. Below that are all of the individual projects. We have our reactor project up here. So if we were to install this using our auto-install package, it would basically go through build all the projects, the OSGi bundle from core would get embedded into UI apps, the UI apps project would build its content project and get deployed into AEM, and the UI content project would build and deploy its content package in the AEM as well. We can also go and run these against individual projects. If we’re only working on our own bundle we could select auto-install bundle and just install the bundle through the core project. Likewise, we could do the same thing with UI apps and content if we don’t need to be installing our content package every time we could auto-install package and simply run it on the UI apps project. All right, so let’s try this out. Since we don’t have anything installed yet, let’s install everything at once and verify that it’s installed into our AEM instance. And for that we want to select auto-install package, which is going to install the package for UI apps as well as UI content like we discussed earlier. Now, we can simply run the install.
We’ll get some output here at the bottom of IntelliJ and we can head over to AEM and check to make sure that everything got installed. So let’s go ahead and go back to sites. We should have our wknd site here, so it looks great. Check out one of the article pages and everything is looking pretty good here. So we have all our content as well as our components. We can verify a few other things. So if we go to package manager, we can see that we have our AEM guides, wknd UI content as well as UI apps, which brought along our core components for us.
The OSGi console, system console bundles, let’s search for the wknd bundle and we can see that we have the bundle installed as well here and it is active. So everything looks great. We were able to load our project into IntelliJ and then build it and deploy it into our AEM author instance running on localhost for 502.
Let’s take a look at how we can use Maven profiles to deploy different artifacts to our local AEM instance. For this we’ll be making some changes to the byline component and they’ll fall into two categories. The first will be a change to the sling model, which is a Java implementation and deployed as part of the OSGi bundle, and the second is a change to the HDL render script, which is part of the UI apps package. So, let’s head to IntelliJ.
So we’ll want to open up the core project and navigate to the byline’s sling model implementation and we’ll be making a very simple change to this. All we’ll be doing is adding some static text to whatever get name returns. So we’ll be adding change from the sling model.
In order to deploy this change to our local AEM developer instance, we’re going to want to select auto-install bundle as our profile. And what this allows us to do is open up the core project and do an install from it. And this is going to deploy only the OSGi bundle to our AEM local developer instance. And I won’t go through and build all of the other projects and deploy those as well. So this is a great way to get your OSGi bundle out to your local AEM developer instance, so you can test out your functionality. Let’s head back to AEM, let’s refresh our page and there you go, you can see that we have our text that we added from the sling model post-fixed to the name.
Let’s do something very similar, but we’re going to be doing it via bylines HTML script, which is part of the UI apps project, which is deployed as a content package rather than a OSGi bundle.
Now that we have our byline HTML file open, we can make our change. I’ll simply add some text after the occupation and now we need to deploy it. So, similarly to our deployment of the OSGi bundle, we can use our profiles as well. So I’m gonna uncheck our auto-install bundle since we’re not installing a bundle and I’m gonna select auto-install package. And now I can navigate to the UI apps project and again do an install. And what this is gonna do is bundle up the UI apps project in its entirety and redeploy that out to our AEM instance.
All right, let’s scroll down and see if our changes were deployed. And here we go, we have our “a change from the HTL”, post-fixed it to the occupations list. So using these Maven profiles, we’re able to deploy changes from both the OSGi bundle, as well as the UI apps project out into our local AEM developer environment.
So now we’re gonna look at a slightly faster way to deploy changes from the UI apps project to our AEM instance. And this can apply to any project that is deployed as an AEM content package. So, for instance, UI apps or UI content. This is not applied to the core project, which is deployed as an OSGi bundle. All right, so we’re gonna take a look at repo and repo is just a little FTP-like tool that allows you to sync nodes or node trees in and out of AEM into your IntelliJ project. So this is actually a command line tool that is ID-diagnostic, but IntelliJ provides some really nice key bindings that make this very easy and efficient to use. So the first thing you’ll need to do is make sure that you have installed Repo. And this information can be found on the repo GitHub page. Since I’m on a Mac, I’ve used Homebrew to install repo.
So if I run repo -version, you can see I’m running version 1.4, but you should always try to use whatever the latest version of repo there is. So to integrate a repo with IntelliJ, the instructions are pretty straightforward. What you need to do is create a new external tool that simply points to the command line tool. And once you set up the external tools, you’ll just set up a few key mappings. So I’m gonna go through and quickly set this up on my local IntelliJ.
So back in IntelliJ, I can open my preferences, search for external tools and I can add a new external tool. So this would be a repo (put).
It’s gonna be sending. I’m gonna just assign it to a group called repo for organizational purposes. Here is our repo command. So this needs to be installed and available on your path and then we can copy in the argument that was provided in the documentation. So we’ll simply want to do this for all four commands.
And make sure you click Apply when you’re done.
The next thing we want to do is map these commands that we defined for our external tool to keyboard shortcuts. So this will make it very easy to invoke a repo from IntelliJ.
So I can select these and I can then right click on them to assign keyboard shortcuts. There are some suggested keyboard shortcuts provided in the repo documentation. However, you don’t have to use these, you can use any available keyboard shortcuts on your computer.
And then add a shortcut. And I actually like to use Ctrl + Command + Right Arrow. So this is kind of pushing it out of IntelliJ into AEM.
Now, after this, I’d like to do Ctrl + Command + Left Arrow. So this is kind of pulling it back in from the local AEM instance into my IntelliJ.
For repo status, Ctrl + Command + Up Arrow. You’ll find that some of these may be taken already, so you may have to remove them.
And for diff, let’s do Ctrl + Command + Down Arrow. So now that we have these key mapped, I can apply them hit. Hit okay, and there is one thing that we need to do. And this is outlined on the repo doc and that is creating a .repo file. And this tells repo what server and what credentials should be used to push and pull content to and from the AEM instance. So we’ll just copy this. And typically I like to put this at the root of my project. So it applies to any content package projects that are therein and pointing this to localhost for 502. So remember that if you are switching between AEM Author and AEM Publish, you may need to be changing this server around. The last thing that we’re gonna do is make sure that we ignore this file from git. So this is really kind of a developer setup file. So we want to make sure that we’re not committing this to source control. But for this we can simply edit the git ignore and add .repo to the git ignore list. So now we won’t be committing this accidentally to our git repository and causing problems for other developers. Now that we’ve done this, we can go to any content package project, navigate to anywhere under the JCR root and we can start invoking a repo from inside IntelliJ. So I’m gonna in and use it on the byline component. You can right-click on it and use the in-context menu here, so I can invoke repo status. So, as you can see, that is appears to be modified. And if we similarly do diff, we should be able to see what these changes are.
The real power of repo though, really comes from making changes in your IDE and pushing those out without having to do a full Maven build. For this, I’m gonna make a simple change to our violent HTML, sent via repo. Save our change here and we could again use the put command in the right-click menu, or when this file is active or selected, we can use our key mappings. So for this I mapped it to Ctrl + Command + Right Arrow, So I’m gonna tap that. So, as you can see it, it pushed only this file out to our local AEM instance at port 502. So let’s go ahead and verify that this happened.
And you can see we made our change here.
So keep in mind that we can make any change in our UI apps project. So we can make changes to the dialogue. So, for instance, I can change the title of this to be a dialogue change from repo, and we can even do interesting things like selecting top-level content tree roots so the byline component is selected here and I can actually push the entire sub-tree from IntelliJ out into our local AEM instance. So again, I can use my keyboard shortcut, of Ctrl + Command + Right Arrow. As you can see, since I had byline folder selected, it pushed that folder and everything under it out into AEM. So again, I can verify this by opening up the dialog and there we go, we have our dialogue title changed here.
Another extremely handy use for repo is syncing changes from AEM to our core project, so we can commit them into SEM. For example, it’s quite usual for at least a base configuration for an editable template to be maintained in source control. And this simply expedites the setup of new AEM instances that you might be deploying your code to. Editable templates are a great example of complex node structures that you probably don’t want to be managing entirely by hand and is much easier to manage via the AEM web UI.
So in this case, we’re going to be making a change to the list components policy. Let’s go ahead and just change the date format to be month then year.
So I’ve changed this policy and this is going to be stored under our comp wknd settings that we see in context-aware configuration. So we want to get this back into our IntelliJ project so we can commit it to SEM. So let’s check out how we can do that.
And we’ll want to go to the UI content project, which contains our content and configuration and sync that configuration back from our local AEM instance to our IntelliJ project. So we have our conf wknd in the CM folder and we have a series of folders here.
So one of the challenges is, it can be hard to understand where in the JCR those changes were persisted. So again we can use repo to help us understand exactly what we want to sync back in. So I can use my status, I’m using my shortcuts. So you can see that there are three new changes that are different between the definition of a comp wknd settings WCM in my IntelliJ project versus my local AEM instance. So here are those three nodes. So it looks like these were the three things that were changed when we updated the list policy, so we’re gonna want to sync these back in. We can simply select the policies node and again, using our shortcuts I’ll use Ctrl +Command + Left Arrow to pull the content back in from AEM to my IntelliJ.
And now I can check to make sure there’s no changes here. It looks like there are no changes, which is great, since I synced them in. We can do that again on the WCM node and it looks like we still need to sync the templates article page template. So you can go ahead and do the same thing using keyboard shortcut. We can get the no definitions from local AEM and save them to IntelliJ. So there we go, we’ve pulled those in and we can verify that everything is fine by going back to the WCM node and executing a repo status. And now we can tell that our state in our local AEM instance for this particular path is mirrored perfectly in IntelliJ and we could commit all these changes back into SEM and have a consistent experience as we deploy this out to new fresh AEM instances.
Next thing I’m gonna do is we can hook IntelliJ up to our AEM instance using a debugger. And this can be very helpful when you’re going through and trying to figure out what is going on in some AEM code. So for this we’re gonna have to restart AEM. I’m gonna head back and I’m gonna stop my local AEM instance, and I’ll wait for this to shut down.
And for this we’re gonna head over to our terminal window and we’re gonna start this up from the command line and we’re gonna do this because we want to pass some parameters to our jar file as we start it up.
So I’m in my AEM instance’s author folder, which contains my jar file. And I’m gonna start AEM using the following command. So what this does is it starts AEM in a mode that the IntelliJ debugger is able to hook up to, and the most important part here is that we are specifying this address. And this is gonna be the port number that we are going to connect IntelliJ up to our local AEM development environment with. So we need to remember our address 8888. Let’s go ahead and start our AEM instance up. And while we’re waiting for it to start up, we’ll head back to IntelliJ.
So we’re gonna add a new configuration. I’m gonna hit the plus sign and create a remote configuration here.
So I’m gonna call this AEM Debug.
It’s gonna be connecting to localhost, and this is where that port that we specified during startup comes in. So I’m gonna change this to 8888.
This is typically used for debugging Java code, but I like to set it at the root project level in case I have multiple projects that need debugging.
And with AEM Debug selected in my configuration, I can start debug mode. So upon successful connection, I will get this message here saying it’s connected to localhost port 888 and from here we can go into our Java code and put some debug breakpoints in. So again, I’ll just be using the byline component. And let’s go ahead and add a breakpoint to our get occupations method. I’ll head back to our article page, that has our byline component and refresh it. And because IntelliJ is hooked up to our local AEM instance, just notice that the byline implementation is under execution and stops at our break point here on line 56. And from here we can use the debugger in the usual manner.
We of course, have access to all the variables and we can even do interesting things like test expressions. So we can check to see what the resource is that is being processed. So we can see that it is the la-skateparks byline component.
All right, so I hope this video helps you develop for AEM a little bit more efficiently, using IntelliJ.

Microsoft Visual Studio Code

Visual Studio Code (VS Code) is a free, open-source tool for front-end developers. Visual Studio Code can be set up to integrate content sync with AEM with the help of an Adobe tool, repo.

Visual Studio Code is the ideal choice for front-end developers primarily creating front-end code; JavaScript, CSS and HTML. While VS Code has Java support via extensions, it may lack some of the advanced features provided by more Java-specific.


Eclipse IDE is a popular IDEs for Java development, and supports the AEM Developer Tools plug-in provided by Adobe, providing an in-IDE GUI for authoring and to synchronize JCR content with a local AEM instance.