CQ5 components are the place where projects either sing or stall. If you are building on Adobe Experience Manager, still called CQ5 by many teams, your components decide the authoring feel, the speed of delivery, and the sanity of your future self. With HTL Sightly getting real adoption and Touch UI maturing, this is the moment to reset the bar. Let us talk about what doing components right looks like, with stories from the field and steps you can put to work this week.
Problem framing
The trouble is rarely the platform. The trouble is a pile of tiny decisions that turn into a maze. Mix markup with business rules in JSP, let dialogs grow without a plan, copy and paste a carousel three times for three brands, and you get brittle pages that no one wants to touch. Authors ask for a small change and you need a release window. Infra teams watch publish nodes burn while the Dispatcher cache barely helps. It is not fun.
Done right means three things. Separate content, presentation, and behavior. Ship author friendly dialogs that feel obvious. Keep components cache aware so publish stays calm. CQ5 and AEM give us the tools for this. HTL for clean markup, Sling Models for request scoped logic, clientlibs for front end assets, content policies and editable templates for guardrails, and OSGi services for the heavy lifting. The rest is discipline.
Three case walkthrough
Case 1, the Hero that stays simple
Every site has a hero. A big image, a headline, a button, sometimes a background video. Most teams start fine then let the hero absorb site wide rules, personalisation flags, and A B test hints. Soon the file looks like a closet with boxes falling on your head.
What works better:
- Make HTL show only markup and simple condition checks. Keep logic out of the view.
- Use a Sling Model to read author content, pick defaults, resolve images, and prepare links. Test this class on its own.
- Put CSS and JS in a clientlib category and include it from the page template, not from the hero itself. Avoid hidden includes in random components.
- Define content policies so authors pick a style name, like wide or compact, instead of editing classes by hand.
- Expose tidy alt text, title, and button labels so accessibility is part of the default author flow.
The win shows up on day two. Designers change spacing across pages by updating the clientlib and policy. Authors do not break markup by poking at properties. The hero is portable across sites because it is not tied to a single page script.
Case 2, the Carousel that does not eat content
Touch UI made life nicer for authors, yet many projects still suffer from that old multifield issue where items save as a long string and then vanish on edit. Teams work around it with custom widgets or strange property hacks and it becomes a trap.
The pattern that lasts:
- Use a composite multifield that stores each slide as a child node with clear names, like item0, item1, item2. No custom JSON in one property.
- Populate select lists through a DataSource so you can share choices across components and keep dialogs tidy.
- Keep the slide item schema small, title, image, description, link, and a simple variant. Fewer fields means fewer broken states.
- Render with HTL looping over child nodes, not over property arrays. It reads clean and survives round trips.
- Let the front end do just the motion. The data and order come from content, so authors can reorder without touching code.
This approach keeps author trust. What they enter is what they see. You also gain stable exports for search and social tags if you need them. The carousel stops being a one off and turns into a reliable building block.
Case 3, the External Feed that stays fast
Say you need to show a list of items from a partner API. The first instinct is to call that API in the component and print the result. It works on dev, then falls apart in publish when the third party stalls and your page waits.
Trade that instinct for a pattern:
- Fetch the API in an OSGi service with a cache and a simple serializer, for example keep the last good response for ten minutes.
- Expose a Sling Model that reads the cache. If the cache is empty, show a friendly fallback state.
- Render a compact view in author so editors never wait on remote calls. Add a refresh button in the dialog that only editors see.
- On publish, include the feed area through Sling Dynamic Include if you need short lived content while keeping page level cache warm at the Dispatcher.
- Log the age of the data with each render and alert if the cache goes stale. Support teams love this.
You get the best of both worlds. Pages stay fast, authors can place the component without fear, and the integration lives in one service where you can test and tune it.
Objections and replies
HTL is too limiting, I need real logic. That is the point. Put the logic in Sling Models and services, where it is testable and safe. HTL gives auto XSS protection and clear templates. Once you switch, maintenance gets easier and the view files stop growing wild branches.
JSP is faster. In practice the win comes from cache design, not from micro differences between render engines. With tidy models and smart Dispatcher caching, HTL based pages fly and the code stays readable. Teams ship changes with less risk, which is the real speed boost.
Touch UI dialogs take too long. Big dialogs take long. Keep fields lean, set sane defaults, and reuse lists through DataSource providers. Authors value clarity more than knobs. A small dialog that always works beats a giant one that surprises people.
One big page component is easier than many small ones. It is easier for one sprint. Then your backlog fills with requests that collide and you cannot change one part without shaking the rest. Make small components with clear contracts. Page templates remain simple, and teams can work in parallel without stepping on each other.
Our front end team wants a single app that owns the page. You can still use that approach where it fits, for example on a product finder or account area. For content pages, let AEM do layout and data, and let the app own one region. If you need JSON for the app, add a tiny selector based endpoint on the resource and keep the authoring story intact.
We must support both Classic UI and Touch UI. Pick one for authoring, preferably Touch UI now that editors are on it across tools. If you must keep Classic for a bit, freeze changes there and move new work to Touch. Split focus doubles cost without much gain.
Action oriented close
If you are in the middle of a build, or about to start one, here is a compact plan to get your CQ5 components into a better place. It works on AEM 6 and carries forward cleanly.
- Draw the lines. For each component, write down what is content, what is presentation, and what is behavior. Move behavior into a Sling Model or service. Leave HTL to print and decide small branches only.
- Use content policies. Set allowed styles, allowed images, and edit rules at the template level. This guards authors from mistakes and cuts dialog size.
- Keep naming boring. Resource types, clientlibs, and categories should read like plain paths, for example mysite components hero v1. Clear names help reuse and versioning without surprises.
- Plan for cache. Decide what renders with full page cache and what should be included through a dynamic include. Aim for warm pages and tiny fresh holes when needed.
- Flatten dialogs. Prefer a few groups with clear labels over deep tabs. Add help text where confusion is likely. Authors pay you back with fewer tickets.
- Multifield the safe way. Store items as child nodes. No custom packing into single properties. Your future migrations will thank you.
- Put assets in clientlibs. One category per concern and reference only from templates or policies. Keep components free of sneaky includes.
- Write small tests. Use AEM Mocks to test models and services. You catch regressions early and keep code honest.
- Document just enough. Add a README in each component folder that states purpose, dialog fields, policies, and any quirks. New team members get up to speed fast.
- Give authors a sandbox. Ship a sample page with sample content. Editors learn by doing and you spot gaps before launch.
Right now we are seeing more teams move to editable templates and Touch UI across the board. Sightly is stable, Sling Models are widely used, and the platform is in a good spot for clean component work. If you pick these patterns today, you are setting yourself up for easy upgrades and happy editors.
One last thought. The best AEM builds are boring in the right places. Components that read clean, dialogs that make sense, cache that just works. That kind of boring frees your team to ship the fun parts faster. Start with one component this week, the hero or the carousel, and make it an example of CQ5 components done right. Then repeat. Your authors will cheer without even knowing why, and your future self will send you a thank you.