Weblets
A weblet is a UI panel embedded within a ZeyOS entity detail view. When a user opens a contact, ticket, account, or any other entity record, weblets appear as tabs or panels alongside the standard entity fields. They are the primary extension point for adding custom interfaces to ZeyOS.
How weblets work
Weblets are iXML files stored in the weblets/ directory of a ZeyOS application. Each weblet is registered in zeyos.app.json and linked to one or more entity types. When a user navigates to a matching entity record, ZeyOS executes the weblet's iXML and renders the result inside the entity detail view.
Context variables
Inside a weblet, several context variables are available:
| Variable | Description |
|---|---|
$ID | The ID of the current entity record |
$ENTITY | The entity type (e.g., contacts, tickets) |
$EXTDATA | Previously saved form data for this record |
$REQUEST | HTTP request parameters |
$APPSETTINGS | Application settings for the current instance |
Two approaches
Form-based weblets use the form namespace to build native ZeyOS input controls declaratively. The form engine handles rendering, layout, and data persistence through EXTDATA. This is the fastest way to build data-entry interfaces.
Custom weblets output raw HTML, CSS, and JavaScript using iXML's <output> command. This gives you full control over the UI, including custom visualizations, interactive dashboards, or integration with external JavaScript libraries.
Custom HTML weblets
A custom weblet outputs HTML directly. You can use any standard web technology — HTML, CSS, JavaScript — and call back to ZeyOS services via AJAX.
Basic structure
<output><![CDATA[
<style>
.dashboard { padding: 16px; font-family: sans-serif; }
.metric { display: inline-block; margin: 8px; padding: 16px; background: #f5f5f5; border-radius: 4px; }
.metric-value { font-size: 24px; font-weight: bold; }
.metric-label { font-size: 12px; color: #666; }
</style>
]]></output>
<!-- Fetch data for the current entity -->
<db:select var_result="stats" type="self" entity="transactions">
<db:fields>
<db:field>COUNT(*) AS total</db:field>
<db:field>SUM(t.netamount) AS revenue</db:field>
</db:fields>
<db:table alias="t">transactions</db:table>
<db:is field="t.account">$ID</db:is>
</db:select>
<output><![CDATA[
<div class="dashboard">
<div class="metric">
<div class="metric-value">]]>$stats.total<![CDATA[</div>
<div class="metric-label">Transactions</div>
</div>
<div class="metric">
<div class="metric-value">]]>$stats.revenue<![CDATA[ €</div>
<div class="metric-label">Total Revenue</div>
</div>
</div>
]]></output>
Calling services from JavaScript
Custom weblets can interact with the application's remotecall services using AJAX. This enables dynamic, interactive interfaces:
<output><![CDATA[
<div id="app">
<button onclick="loadData()">Refresh</button>
<div id="result"></div>
</div>
<script>
function loadData() {
fetch('./remotecall/my-service/]]>$ID<![CDATA[')
.then(r => r.json())
.then(data => {
document.getElementById('result').innerHTML =
JSON.stringify(data, null, 2);
});
}
</script>
]]></output>
For complex custom UIs, keep the iXML weblet thin — use it only to inject context variables (like $ID and $APPSETTINGS) into the HTML, and handle all business logic in remotecall services that return JSON.
When to use which approach
| Scenario | Approach |
|---|---|
| Data-entry form with standard fields | Form namespace |
| Custom dashboard or visualization | Custom HTML weblet |
| Interactive UI with real-time updates | Custom HTML + remotecall services |
| Simple read-only data display | Either — forms with readonly fields or custom HTML |
| Generating downloadable files | Exports |