Modules
A module is an opt-in bundle of additional classes. Modules let multiple tenants share the same base data model while each enabling only the functionality they need.
How modules work
Modules are declared in the repository — typically in index.json. Each module has a name, a description, and its own list of class imports.
When the platform loads a tenant's model, it checks the tenant's configuration for which module names are active:
- Activated — the module's classes are loaded and fully available to the tenant.
- Available — the module is declared in the repository but not enabled for this tenant. It appears as an opt-in option in the platform UI.
Declaring a module
Modules are declared in the modules array on a NONE-type class (usually index.json):
{
"class": "my-project.index",
"type": "NONE",
"imports": [
"my-project.company",
"my-project.contact"
],
"modules": [
{
"name": "HRM",
"description": "Human resource management: employees, contracts, and leave.",
"imports": [
"my-project.employee",
"my-project.employmentAgreement",
"my-project.leaveRequest"
]
},
{
"name": "Finance",
"description": "Invoicing and expense management.",
"moreInfo": "https://docs.example.com/modules/finance",
"imports": [
"my-project.invoice",
"my-project.invoiceLine",
"my-project.expense"
]
}
]
}
| Property | Type | Description |
|---|---|---|
name | string | Unique identifier for the module. Used to match against the tenant's activated module list. |
description | string | Human-readable description shown in the module-selection UI. |
moreInfo | URL | Optional link to external documentation for the module. |
imports | TypeFQN[] | Classes to load when this module is activated. |
Use case: SaaS product with optional functionality
Suppose you build an application where all tenants share a common foundation (companies and contacts), but only some tenants need HRM or Finance features.
Base model (always loaded) Optional modules
───────────────────────── ──────────────────────────────────
my-project.company HRM → employee, contract, leave
my-project.contact Finance → invoice, expense
Tenant A activates HRM. Tenant B activates Finance. Tenant C activates both. All three tenants run from the same Git repository and the same branch.
This keeps the repository as a single source of truth for your entire product, while giving each tenant only the data model they need.
Modules and branches
Module activation is a tenant configuration setting, separate from the repository. A tenant can switch modules on or off without any change to the repository. Combined with branch-based environments, this gives you two independent axes of variation:
- Branch — controls which version of the model is active (develop, staging, production)
- Modules — controls which optional bundles are enabled per tenant