Skip to main content

App Structure

A ZeyOS app is the unit of packaging, sync, and deployment. Understanding app structure is essential because iXML behavior depends on where code is executed within the app.

Directory layout

A typical ZeyOS app contains:

Text
app-name/
├── zeyos.app.json # App metadata and identity
├── services/ # Entry points: API, background tasks, hooks
├── resources/ # Reusable domain logic and helpers
├── weblets/ # UI-linked iXML integrations
└── settings/ # Per-instance configuration
├── defaultsettings.json
└── settings.<instance>.json

A useful mental model: services orchestrate requests, resources encapsulate logic, and settings provide runtime variability.

Runtime contexts

Service context

Files in services/ are invoked as runtime entry points. This is where you:

  • Parse inbound payloads
  • Enforce auth and guard clauses
  • Call reusable resource logic
  • Shape final response payloads

Services are registered in zeyos.app.json with types like remotecall (HTTP API endpoint), timing (scheduled job), or before_modification / after_modification (entity lifecycle hooks).

Resource context

Files in resources/ are consumed via include, call, or expand. This context should hold reusable logic that is independent from a specific transport boundary.

Weblet context

Files in weblets/ are linked to UI action flows. They compose resource functions and app settings to produce user-facing behavior.

App settings and APPSETTINGS

Settings under settings/ are the preferred place for tenant-specific values and environment toggles. Avoid hardcoding instance-specific values directly into service logic.

Use APPSETTINGS for values such as:

  • External endpoint URLs
  • Credentials references and key aliases
  • Feature toggles and rollout switches
  • Integration mode flags

This allows one codebase to run against multiple instances with different behavior per instance, without branching code.

Context switching and scope behavior

When iXML enters function/class/include/resource boundaries, it creates local execution context. Variable visibility follows the precedence rules explained in the Introduction.

Key implications:

  • Local variables are context-bound.
  • Globals (<global var="..." />) should be explicit and rare.
  • Free variables (<use>) should be intentional and readable.
XML
<!-- services/account.api.ixml -->
<include id=".AccountController" />

<rest:server>
<rest:resource route="/accounts/:id" method="GET">
<call func="AccountController.getById" var="payload">
<param name="id">$id</param>
</call>
<header>Content-Type: application/json</header>
<output><encode:json var="payload" /></output>
</rest:resource>
</rest:server>

This pattern keeps transport details local to services/ while maintaining reusable, testable logic in resources/.

Common mistakes

  • Treating resources/ as route handlers instead of reusable modules.
  • Hardcoding instance-specific values instead of using settings/ and APPSETTINGS.
  • Using globals as implicit data transport between unrelated contexts.
  • Mixing UI-specific behavior into shared domain modules.