Org Skills

AEM

Always-on rules for AEM as a Cloud Service Java bundles, HTL components, OSGi configs, front-end clientlibs and dispatcher configuration.

Raw Source
What it isAlways-on coding rules. GitHub Copilot applies them to files matching **/core/src/**/*.java,**/ui.apps/**,**/ui.config/**,**/ui.frontend/**,**/dispatcher/**; the Claude Code version is a path-scoped rule generated from the same file. Why use instructions →

Install

This repository (recommended)

Adds .github/instructions/aem.instructions.md — commit it so everyone's Copilot follows the same rules.

npx -y github:AGCO-Global/org-skills add instructions aem

Just for me, every repository

Save it in your user profile instead.

npx -y github:AGCO-Global/org-skills add instructions aem --user

Use it

Nothing to invoke — edit a matching file and Copilot picks the rules up. Adjust applyTo if your repository layout differs.

This repository (recommended)

Adds .claude/rules/aem.md — commit it. Claude loads it when it reads a matching file.

npx -y github:AGCO-Global/org-skills add instructions aem --tool claude

Just for me, every repository

Save it in your user profile instead.

npx -y github:AGCO-Global/org-skills add instructions aem --tool claude --user

Use it

Nothing to invoke. Adjust the paths globs if your repository layout differs.

Commands run in your repository folder and need Node.js 20+. They use your normal git sign-in to GitHub, so they work while the repository is private. Run npx -y github:AGCO-Global/org-skills list to see everything available.

Settings

name: "AEM"
description: "Always-on rules for AEM as a Cloud Service Java bundles, HTL components, OSGi configs, front-end clientlibs and dispatcher configuration."
applyTo: "**/core/src/**/*.java,**/ui.apps/**,**/ui.config/**,**/ui.frontend/**,**/dispatcher/**"

Instructions Copilot follows

AEM rules

Write for AEM as a Cloud Service first: immutable /apps, no admin sessions, auto-scaled disposable publish pods.

HTL and components

  • Never use @ context='unsafe'. It disables XSS protection and is a review blocker.
  • Use the right XSS context: context='html' for RTE output, 'uri' for links, 'attribute'/'text' where the default is not inferred, 'scriptString'/'styleString' inside <script>/<style>.
  • Keep logic out of HTL: no string-built markup or URLs; compute them in the Sling Model.
  • Build standard elements as proxies of a pinned Core Component version (sling:resourceSuperType=".../v3/..."); never reference core/wcm/components directly from content.
  • Use the Style System for visual variants, not new components or dialog dropdowns.
  • Set allowed components on the layout container policy, not in code.

Sling Models

  • Adapt component models from SlingHttpServletRequest, expose an interface, and keep the Impl in an internal package.
  • Use injector annotations (@ValueMapValue, @ChildResource, @OSGiService) with DefaultInjectionStrategy.OPTIONAL, and handle missing values. Authors leave fields empty.
  • Keep @PostConstruct cheap: no queries, remote calls or writes during render.
  • Extend Core Components through delegation (@Via(type = ResourceSuperType.class)), not by copying their code.

OSGi services and access

  • Components are singletons: no request state in fields; ResourceResolver and Session are not thread-safe.
  • Never use getAdministrativeResourceResolver or loginAdministrative. Use a service user mapping with least-privilege ACLs defined in repoinit.
  • Close every service resolver you open (try-with-resources). Leaked sessions degrade the instance.
  • Configure services with @Designate/@ObjectClassDefinition and .cfg.json in ui.config under the fixed runmodes (config.author, config.publish.prod, ...).
  • Keep secrets out of Git: use $[secret:NAME] and $[env:NAME] set via Cloud Manager variables.
  • Register servlets by resource type (@SlingServletResourceTypes), not by path; use SlingSafeMethodsServlet for GET.
  • Avoid unindexed queries; add a versioned <name>-custom-<n> Oak index in code when a query needs one.
  • Run long or scheduled work as Sling Jobs, and make it safe to run on any pod; never write /apps or /libs at runtime.

Dispatcher

  • Start filters from deny-all (/0001 { /type "deny" /url "*" }) and allow only needed paths, extensions and selectors.
  • Never allow /crx, /system, /bin wholesale, .infinity.json, .query.json or unrestricted selectors on publish.
  • Cache static and clientlib content with long TTLs; set invalidation rules deliberately and never cache personalized or authenticated responses.
  • Validate changes with the SDK dispatcher validator before pushing; Cloud Manager rejects invalid configs.

Front end and clientlibs

  • Set allowProxy="{Boolean}true" on clientlibs and reference them via /etc.clientlibs; publish denies reads on /apps.
  • Embed component clientlibs into the site clientlib; do not include them per component in HTL.
  • Load CSS in <head> and JS with defer; keep author-only code in cq.authoring.* categories.
  • Never hand-edit generated clientlib folders; change sources in ui.frontend.
  • Make scripts work in the page editor: initialize on DOM content, tolerate components being added or removed.

Go deeper: for larger tasks use the aem-component-development, aem-backend-development, aem-frontend-development, aem-dispatcher, aem-testing and aem-code-review skills.