Menus and Navigation
The platform uses a fully data-driven menu system rather than hard-coded navigation. This enables role-based visibility, per-tenant customisation, dynamic schema binding, and hierarchical menu structures that nest to arbitrary depth.
Structure
Menus
Each menu is a top-level navigation group (e.g. "CRM", "Administration", "Platform"). The platform provides a set of default menus during tenant setup, including both internal administration menus and an external-facing "My Dashboard" menu.
Key attributes:
| Attribute | Purpose |
|---|---|
| Code | Unique identifier within the tenant |
| Name | Display name with i18n support |
| Icon | Icon identifier for the UI |
| Display order | Sort position in the navigation bar |
Menu entries
Entries are the items within a menu. Each entry has a type that controls how it renders:
| Type | Renders as |
|---|---|
link | Navigable item pointing to a schema/href |
section | Non-navigable group header |
link-group | Collapsible group of links |
divider | Visual separator |
custom | Custom component identified by code |
Hierarchy
Entries form a tree via parent-child relationships. A "Customers" link can have child entries like "Subscriptions", "Payment Methods", and "Contact Points" nested underneath. An entry can also appear under multiple parents when needed.
Schema binding
Each entry links to a schema definition that the application uses to resolve which data grid, form, or view to render.
Permission gating
Each entry can declare permission requirements via two mutually exclusive mechanisms:
- Domain permissions — based on a resource group and resource name
- Relationship-based — based on a specific object type, object ID, and relation
Layouts
Each entry has at most one layout configuration that controls how data is presented — grid columns, default sorting, filter state, and similar settings. Available layouts allow a single entry to offer multiple view options (e.g. table view, card view, timeline view).
Actions
Actions define what operations appear on a menu entry's toolbar or context menu:
| Attribute | Purpose |
|---|---|
| Type | Standard types: create, edit, delete, view, custom |
| Code | Identifier for the action |
| Schema | Optional override schema for the action |
| Hidden | Whether the action is suppressed in the UI |
| Multi-select | Whether the action applies to multiple selected rows |
Custom actions trigger client-side handlers identified by the action code.
Role-menu assignments
Roles are mapped to menus, with role inheritance meaning child roles automatically see parent menus. Per-role overrides allow fine-grained control — for example, hiding the "delete" action for a particular role while leaving "create" and "edit" visible.
How the menu tree is resolved
When a user logs in, the platform resolves their complete menu tree:
- Determines the user's roles (direct and inherited)
- Finds all menus assigned to those roles
- Filters entries by permission checks
- Applies role-specific overrides
- Returns the full menu structure including entries, children, actions, and layouts
The result is cached for the duration of the user's session.