Client Libraries (ClientLibs)
Learn how AEM manages CSS and JavaScript through Client Libraries - the system that bundles, minifies, and delivers front-end assets.
Last reviewed: December 2024
🔍 What Is It?
AEM Client Libraries are repository folders of type cq:ClientLibraryFolder that package CSS and JavaScript into named categories. Teams include those categories in templates or components so AEM can deliver the right files through /etc.clientlibs.
If someone asks "what are clientlibs in AEM," the practical answer is simple: clientlibs are AEM's asset delivery system for frontend code, handling categories, dependencies, bundling, minification, and cache-aware URLs.
Quick Facts
- →Used in: Site CSS, JavaScript, authoring-only assets, component assets, and frontend delivery through Dispatcher
- →Best for: Managing CSS and JS in reusable AEM projects without manual script ordering
- →Interview importance: High because clientlibs are a core AEM implementation topic
- →Production relevance: High because clientlib setup affects caching, performance, and publish delivery
- →Related topics: Components, HTL, editable templates, Dispatcher
- →Last updated: July 2026
What a clientlib contains
- →CSS files listed in
css.txt - →JavaScript files listed in
js.txt - →A
categoriesproperty used for inclusion - →Optional
dependenciesandembedproperties for load ordering and bundling
Why teams use clientlibs
- →Bundles multiple CSS and JS files into predictable delivery groups
- →Helps manage dependency order between shared frontend assets
- →Supports minified production output
- →Works cleanly with cache-busting through generated clientlib URLs
🎯 Why Do We Need It?
Without clientlibs, AEM projects end up manually managing CSS and JavaScript includes, inconsistent load order, and fragile cache behavior across templates and components.
Clientlibs give teams a standard AEM-native way to organize frontend assets so Author, Publish, Dispatcher, and Cloud Service delivery stay easier to reason about.
Interview Relevance
- →Interviewers ask clientlibs to check whether you understand AEM frontend delivery beyond HTL markup alone
- →Strong answers explain categories, dependencies, embed,
allowProxy, and why/etc.clientlibsmatters on Publish - →Senior discussions often move into caching, author-only assets, and debugging missing CSS or JavaScript in production
🏗️ What Happens in Real Projects?
Production Usage
In real AEM projects, clientlibs are used to separate base site assets, component-specific styles, vendor bundles, and author-only functionality. Teams usually include shared categories at the page level and smaller categories only where a component or template actually needs them.
A common setup includes:
- →
mysite.basefor typography, layout, and shared utilities - →
mysite.componentsfor reusable component styling - →
mysite.authorfor editor-only enhancements - →
mysite.vendorfor approved third-party libraries
Component-scoped clientlibs are also used when a feature should load only with a specific component or experience.
⚙️ How It Works
ClientLib Structure:
/apps/mysite/clientlibs/
base/ [cq:ClientLibraryFolder]
categories: [mysite.base]
dependencies: [cq.jquery]
css.txt <- Lists CSS files
js.txt <- Lists JS files
css/
main.css
typography.css
js/
app.js
utils.jsIncluding in HTL:
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
<sly data-sly-call="${clientlib.css @ categories='mysite.base'}"/>
<!-- page content -->
<sly data-sly-call="${clientlib.js @ categories='mysite.base'}"/>
</sly>Generated Output:
<link rel="stylesheet" href="/etc.clientlibs/mysite/clientlibs/base.min.css?...hash...">
<script src="/etc.clientlibs/mysite/clientlibs/base.min.js?...hash..."></script>💻 Example
Creating a Client Library — Complete ClientLib setup for a component.
🤔 Common Confusions
❓ What is the difference between dependencies and embed?
dependencies ensures another ClientLib loads before yours (separate HTTP request). embed includes another ClientLib's files directly inside yours (single combined request). Use embed for small libraries you always need; use dependencies for large shared libraries.
❓ Why are my ClientLib changes not showing in the browser?
Browser cache or AEM ClientLib cache. Try: 1) Hard refresh (Ctrl+Shift+R), 2) Rebuild ClientLibs via /libs/granite/ui/content/dumplibs.rebuild.html, 3) Clear browser cache. In development, use ?debugClientLibs=true to load unminified files.
🚨 Common Production Issues
CSS/JS not loading on Publish - Dispatcher is blocking /etc.clientlibs/ path. Add allow rule for /etc.clientlibs/* in Dispatcher filters.
ClientLib changes not reflecting - AEM ClientLib cache not invalidated. Rebuild via /libs/granite/ui/content/dumplibs.rebuild.html.
JavaScript errors on production - minification broke the code. Use strict mode and avoid relying on minification behavior.
ClientLib URL returns 404 - allowProxy is missing or the library is stored under /apps without being exposed through /etc.clientlibs.
Styles differ between Author and Publish - author-only categories are leaking into page templates or publish-only categories are missing.
✅ Best Practices
Use the /etc.clientlibs proxy path (not /apps) for ClientLib URLs - it works with Dispatcher caching.
Organize ClientLibs by category
base (always loaded), component-specific (loaded on demand).
Use Long Cache-Control headers for ClientLibs - the hash in the URL ensures cache-busting.
Test with minification enabled (production mode) - some JS patterns break under minification.
Use project-specific category names to avoid collisions with Adobe, Core Component, or other vendor ClientLib categories.
Keep authoring ClientLibs separate from site delivery ClientLibs so author-only scripts never ship to public pages.
🏛️ Architect's Note
ClientLibs are AEM's front-end asset management system. In modern projects, you might integrate with npm-based build tools (webpack, vite) and use ClientLibs just as a delivery mechanism.
For AEM as a Cloud Service: ClientLibs work the same way, but the /etc.clientlibs proxy is even more important for Dispatcher caching. Consider using the Frontend Build Pipeline in Cloud Manager for modern JS/CSS toolchains.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
↗ Where this topic fits
AEM Technology Guide
Return to the AEM learning hub.
AEM Developer Career Path
This AEM developer career path explains how to become an AEM developer through JCR, Sling, HTL, client libraries, Dispatcher, Cloud Service delivery, project depth, and interview-ready enterprise implementation skills.
Drupal Developer Career Path
A practical route through Drupal content modeling, site building, theming, modules, configuration management, APIs, performance, deployment discipline, and interview preparation.
Sources
Sources / References
Use these AEM references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide AEM learning path
Browse the full AEM topic collection and learning order on SplashRide.
AEM Interview Prep
Practice AEM interview questions and scenario-based answers.
AEM Developer Career Path
This AEM developer career path explains how to become an AEM developer through JCR, Sling, HTL, client libraries, Dispatcher, Cloud Service delivery, project depth, and interview-ready enterprise implementation skills.
Drupal Developer Career Path
A practical route through Drupal content modeling, site building, theming, modules, configuration management, APIs, performance, deployment discipline, and interview preparation.
AEM Components Explained: Dialogs, HTL, Sling Models, and Core Components
Learn AEM components with component nodes, dialogs, HTL, Sling Models, Core Components, authoring, inheritance, and real project patterns.
HTL (HTML Template Language)
Master HTL — AEM's templating language. Learn the syntax, best practices, and how it keeps your templates clean and secure.