UI Frameworks & Libraries
UI Libraries
A UI Library is a standalone bundle of CSS, JavaScript, and HTL templates that a UI Framework can pull in. Because Kestros keeps components separate from their views, libraries let you package and version front-end assets once and reuse them across many sites in the same instance.
kes:vendorLibraries property, and library nodes live under /etc/vendor-libraries. This page uses UI Library throughout, but the JCR paths and property names below are the real, current ones.What a UI Library is for
Every page and site in Kestros is configured with a UI Framework, which decides two things: what CSS and JavaScript is included on the page, and which HTL templates render at the component level. A UI Library is a self-contained unit that a framework can include to supply those assets.
Splitting front-end code into libraries keeps CSS, JavaScript, and HTL separated for multisite and microsite setups. You can create several libraries and assign them to independent sites managed within the same instance. As a rule of thumb, the more you push into UI Libraries, the less you have to manage inside any single framework, and the more reuse you get out of your code.
The simplest library
Before the versioning and packaging details, here is the smallest thing that counts as a UI Library: a single kes:VendorLibrary node with a css folder inside it. No versions/ folder, nothing else. This is a real one from the sample sites, a styleless library shipping a single stylesheet:
/etc/vendor-libraries/lorem-ipsum-site-vendor-library/ # kes:VendorLibrary
css/ # sling:OrderedFolder
lorem-ipsum-sample-site-library.less
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="kes:VendorLibrary"
jcr:title="Lorem Ipsum Generic Library"
jcr:description="Styleless library. Black text on a white background."
documentationUrl="https://kestros.io"/>
That is a working library. Everything below, versioning, the css/js folder details, and filter.xml packaging, is refinement on top of this shape.
Versioning UI Libraries
A UI Library does not have to be versioned, but it can be. In a managed library each version is its own node, and several versions of the same library can exist at once. That gives you conflict-free upgrades: when you use a versioned front-end framework such as Tailwind, Bootstrap, Vue, or Svelte, you can stand up each version as its own node and avoid dependency clashes for legacy sites.
Location and structure
Project UI Libraries are created under /etc/vendor-libraries. For a managed (versioned) library the root node is a kes:ManagedVendorLibrary whose versions live beneath a versions folder; every version carries its own css and js folders:
/etc/vendor-libraries/my-ui-library/ # kes:ManagedVendorLibrary (root)
versions/
1.0.0/ # kes:VendorLibrary (a version)
css/ # sling:OrderedFolder (include=[...])
styles.css
js/ # sling:OrderedFolder (include=[...])
scripts.js
The library root node
For a managed library, create the library folder and a .content.xml for its root node. The root is a kes:ManagedVendorLibrary:
Required property:
| Property | Value |
|---|---|
jcr:primaryType | kes:ManagedVendorLibrary |
Configurable properties (in .content.xml):
| Property | Type | Req | Description |
|---|---|---|---|
jcr:title | String | Title of the UI Library as it appears in the system | |
kes:libraryCode | String | Shorthand code used for component-view folder structures; defaults to the node name if omitted | |
jcr:description | String | Description of the UI Library | |
documentationUrl | String | External URL for third-party documentation | |
fontAwesomeIcon | String | Font Awesome icon class shown for the library in the Site Admin UI |
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:kes="http://kestros.io/kes/1.0"
jcr:primaryType="kes:ManagedVendorLibrary"
jcr:title="My UI Library"
kes:libraryCode="my-ui-library"
jcr:description="My custom UI Library"/>
Adding CSS and JavaScript
Assets live under a version node. Create a version folder whose name is a semantic version number (major.minor.patch), then add css and js folders inside it. Any CSS or JavaScript files go into the matching folder.
The version folder is itself a kes:VendorLibrary. Give it a .content.xml with its own properties:
| Property | Type | Req | Description |
|---|---|---|---|
jcr:primaryType | Y | Must be kes:VendorLibrary | |
jcr:title | String | Display name in the system view and authoring dialogs | |
jcr:description | String | Description of the UI Library version | |
dependencies | String[] | Other libraries this version needs, each entry node-name/minVersion:maxVersion (for example vendor-library/0.0.1:1.0.0) | |
documentationUrl | String | External URL for third-party documentation |
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:kes="http://kestros.io/kes/1.0"
jcr:primaryType="kes:VendorLibrary"
jcr:title="My UI Library"
jcr:description="Description of my UI Library"/>
The source files sit in the JCR at /etc/vendor-libraries/my-ui-library/versions/1.0.0/css/styles.css and /etc/vendor-libraries/my-ui-library/versions/1.0.0/js/scripts.js.
Each of the css and js folders also needs its own .content.xml to set the compile order. Both are a sling:OrderedFolder with an include array:
| Property | Type | Req | Description |
|---|---|---|---|
jcr:primaryType | Y | Must be sling:OrderedFolder | |
include | String[] | Y | Lists the files in the folder to be compiled by the system, in order |
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:kes="http://kestros.io/kes/1.0"
jcr:primaryType="sling:OrderedFolder"
include="[styles.css]"/>
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:kes="http://kestros.io/kes/1.0"
jcr:primaryType="sling:OrderedFolder"
include="[scripts.js]"/>
Referencing a library from a framework
A framework pulls in a library through its kes:vendorLibraries property. Each entry is the library’s JCR node name, not its library code (the two can differ):
- Unversioned:
[my-library] - Versioned:
[my-versioned-library/0.0.1](node name, a slash, then the version)
See UI Frameworks & Themes for how a framework declares its libraries and exposes them through a theme.
Packaging with filter.xml
The filter.xml defines the JCR paths the content package owns. It lives under the module's src/content/META-INF/vault/filter.xml (or src/main/resources/META-INF/vault/), and normally needs no changes:
<?xml version="1.0" encoding="UTF-8"?>
<workspaceFilter version="1.0">
<filter root="/etc/vendor-libraries/my-ui-library"/>
</workspaceFilter>
/apps/kestros/commons/components, with the include pattern) is only needed when the library also ships component views under that path. A plain CSS/JS UI Library owns just its /etc/vendor-libraries/<lib> tree, so it needs only the first filter root. Do not copy the /apps/kestros/commons/components filter into a library that ships no views.<filter root="/apps/kestros/commons/components">
<include pattern="^/apps/kestros/commons/components(/.*/my-ui-library(/.*)?)?$"/>
</filter>
Failed to include script) while the component-view cache is stale; redeploying kestros-site-building-core and letting it settle clears it.