Modules
What It Is
A module is Jetstack's navigation entry and experience container for a domain area. It tells the platform:
- how the module appears in navigation
- what kind of link the module represents
- what content should open when the module is entered
- who may see it
- whether it can be exposed publicly or embedded
Why It Matters
Modules shape the first impression of a solution. A strong module structure makes the tenant feel coherent and intentional. A weak one makes even a good data model feel scattered.
Modules are also more than menu items. Depending on configuration, a module can behave as:
- a normal in-app destination
- a wrapper around a default view
- a custom layout or canvas-based landing page
- an external link
- a structural heading in navigation
How To Read This Chapter
Unlike some other builder objects, the module resource does not define custom form groups of its own. The most useful way to document it is by capability area:
- identity and labels
- link and destination behavior
- content and rendering behavior
- navigation hierarchy
- access and exposure
Use this chapter together with:
Mental Model
Keep these distinctions clear:
module_nameis the main internal and administrative label.module_titleis the display-facing title. If left empty, the runtime falls back tomodule_name.link_typedefines where the navigation entry goes.default_view,layout, andcanvasdefine what the module renders when it opens.parent_moduledefines navigation nesting, not data ownership.available_to_roles,is_public, andallowed_framing_hostsdefine who can reach the module and from where.
Configuration Options
Identity And Labeling
| Option | What it controls | How to configure it | Notes |
|---|---|---|---|
module_name | Main name of the module. | Enter a stable, recognizable name such as Sales, HR, Projects, or Knowledge Base. | This is the title-role field and the main administrative identifier used in the builder. |
module_title | Display title of the module. | Enter the title users should see in the heading and navigation. | If left empty, the runtime fills it from module_name. |
icon | Icon shown for the module in navigation and entry points. | Choose an icon that matches the module's business meaning. | This is a semantic navigation signal. Reuse icon conventions across related modules. |
Identity Details
module_name
Use this as the stable module label in the implementation.
Good examples:
CustomersFinanceLegalOperations
This field is required on create and edit.
module_title
This is the display-oriented title shown when the module is rendered. The runtime explicitly fills it from module_name when empty, so:
- use it when the displayed module title should differ from the administrative name
- leave it empty when the same wording is correct in both places
This is especially useful when:
- the navigation label should be shorter
- the page heading should be more descriptive
- translated or localized naming needs a cleaner display label
Link And Destination Behavior
| Option | What it controls | How to configure it | Notes |
|---|---|---|---|
link_type | What kind of navigation target the module represents. | Choose one of Module, Within app, External, or None. | This is one of the most important module settings. |
link_href | Explicit target used by non-module link types. | Enter the internal presenter/action target or the external URL, depending on link_type. | Most relevant for Within app and External. |
default_view | View opened when the module has no layout and no canvas. | Select the fallback view the module should show. | This is the standard "full screen view" fallback when neither layout nor canvas is configured. |
link_type In Detail
Jetstack defines four link types:
ModuleWithin appExternalNone
Module
This is the normal module behavior.
Use it when:
- the module should open its own module page
- the module is a real Jetstack destination
- you want the module to use
default_view,layout, orcanvas
Runtime behavior:
- the generated link points to
Module:defaultfor normal modules - or
Module:publicwhenis_publicis enabled and the public link is used
This is the usual choice for business-area modules.
Within app
Use this when the module should navigate to another internal application route directly.
Configure:
link_type = Within applink_hrefwith a valid internal application destination
Runtime behavior:
- the module link is produced through
$app->link($this->link_href) - the module acts more like a navigation shortcut than a self-contained module page
Use this when:
- the best destination is another presenter or route
- the module should behave like an alias or shortcut into an existing screen
External
Use this when the module should open an external URL.
Configure:
link_type = Externallink_hrefwith the full external target URL
Runtime behavior:
- the module link is the raw configured external URL
Use this sparingly and intentionally. External modules make sense when Jetstack is one part of a wider tool landscape.
None
Use this when the module should not be a direct destination.
Runtime behavior:
- the generated module link is empty
- in navigation templates, modules with this link type behave like structural entries or headings
- this is the main pattern for parent/grouping nodes with children
Use it when:
- the module exists to organize child modules
- the navigation needs headings rather than more destinations
link_href
How to configure it depends on the selected link type:
- for
Within app, enter the internal target expected by the application's link system - for
External, enter the full external URL - for
ModuleorNone, this is usually left empty
Treat this field as a contract:
- internal links should stay valid when modules evolve
- external links should point to stable destinations
default_view
This field is more important than it first appears.
Runtime rendering order:
- if neither
layoutnorcanvasis set, the module rendersdefault_viewin a full-screen module page - if either
layoutorcanvasis set, the module renders through the module template file instead
So default_view is not the universal main content field. It is specifically the fallback content model for standard modules without custom page composition.
Use default_view when:
- the module should simply open a view
- you do not need a custom layout page
- a canvas would be unnecessary complexity
Content And Rendering
| Option | What it controls | How to configure it | Notes |
|---|---|---|---|
layout_file | Layout wrapper file used when rendering the module page. | Select the layout file to use. The default points to the standard @layout.latte file. | Required on create and edit. This is the page shell, not the module body content itself. |
layout | Module-specific layout content rendered inside the module page when no canvas takes over. | Enter the HTML or Latte-safe content the module should render. | If a canvas is set, the canvas takes precedence and layout acts as fallback. |
canvas | Canvas used to render the module body. | Select a canvas when the module should open a custom canvas-based page. | This is the strongest content override for module rendering. |
Rendering Precedence
The module runtime works like this:
- if neither
layoutnorcanvasis set: the module falls back todefault_view - if
layoutorcanvasis set: the module renders a generated module template file - if
canvasis set: the generated template renders the canvas control - otherwise:
the generated template renders the
layoutcontent
In plain terms:
canvaswins overlayoutlayoutwins overdefault_viewdefault_viewis the simple fallback
layout_file
This controls the broader wrapper around the module page.
Use it when:
- the module should use a specific page shell
- a custom wrapper is needed for styling, structure, or public-page presentation
Do not confuse it with:
layout, which is the module body contentcanvas, which is a canvas-based module body
layout
Use this when:
- the module needs a custom composed page
- you want module-specific HTML or layout content
- a simple full-screen default view is not enough
Important runtime note:
- the module content is written into a tenant file under
TENANT_DIR/modules/<moduleId>.latte - if a canvas is present, the module template becomes a canvas control call instead
This means layout is appropriate for carefully designed module entry pages, dashboards, or landing layouts.
canvas
Use this when:
- the module should open a canvas-driven experience
- the module needs a highly tailored landing page
- a more visual or assembled page model is required
The presenter also loads canvas meta tags for module pages, which makes canvas-backed modules especially useful for richer experiences.
Read Canvases.
Navigation Hierarchy
| Option | What it controls | How to configure it | Notes |
|---|---|---|---|
parent_module | Parent module in the navigation tree. | Select the parent module when this module should appear nested under another one. | This is a navigation relationship, not a data or permission hierarchy. |
parent_module
Use this when:
- you want child modules under a broader section
- the navigation should be grouped by business area
- the parent module acts as a structural heading
This is especially powerful with link_type = None on the parent module.
Typical pattern:
- parent module
Peoplewithlink_type = None - child modules
Employees,Recruiting,Policies
That gives you a clean navigation section instead of a long flat list.
Access And Exposure
| Option | What it controls | How to configure it | Notes |
|---|---|---|---|
available_to_roles | Roles that may access or see the module. | Select the roles that should have access to the module. | This is a multi-role relation and part of the module's access surface. |
is_public | Whether the module may be opened through its public route. | Enable only when the module should be reachable publicly. | Public exposure meaningfully changes the risk profile of the module. |
allowed_framing_hosts | Which referring hosts may embed the public module. | Configure this as an array of allowed host names, or * to allow any host. | This matters only for public module embedding scenarios. |
is_active | Whether the module is active in the current navigation model. | Enable for modules that should participate in the active tenant experience. | Use inactive modules only for staged or retired navigation assets. |
available_to_roles
This field defines which roles the module is available to.
Use it when:
- a domain area should be visible only to specific roles
- navigation itself should respect role boundaries
- the module is not appropriate as a globally visible entry point
This is a module-level navigation/access concept and should be designed together with Roles And Permissions.
is_public
When this is enabled:
- the module can expose a public link
- the module presenter can render it through
Module:public - the module becomes part of the public surface of the tenant
Use it for:
- public portals
- externally reachable landing modules
- controlled public entry points
Do not enable it casually. A public module should be reviewed as a public-facing asset, not just a convenient shortcut.
allowed_framing_hosts
This field controls who may frame the public module.
Runtime behavior:
- when the module is opened publicly, the presenter reads
allowed_framing_hosts - if the first configured host is
*, framing is allowed from anywhere - otherwise, the HTTP referer host must appear in the allowed-host list
Use this when:
- a public module should be embedded in a known external portal
- you need to restrict which hosts may frame the module
Configure it as an array of host names such as:
["portal.example.com", "partners.example.com"]
Use ["*"] only when fully open framing is truly intended.
is_active
Use this to control whether the module should be part of the active navigation experience.
Disable it when:
- the module is being prepared but should not yet be visible
- the module has been retired but not fully removed
- the navigation structure is being migrated in stages
Common Module Patterns
Standard Destination Module
Use:
link_type = Moduledefault_viewset- no custom layout or canvas unless needed
This is the simplest and most maintainable pattern.
Dashboard Or Landing Module
Use:
link_type = Module- a custom
layoutorcanvas - optional
default_viewonly as fallback when no custom content is present
This is a good fit for rich module entry pages.
Structural Navigation Module
Use:
link_type = None- child modules through
parent_module
This is the best pattern for section headings and grouped navigation.
External Shortcut Module
Use:
link_type = Externallink_hrefset to the external target
This works when Jetstack is part of a broader business-tool landscape.
Internal Shortcut Module
Use:
link_type = Within applink_hrefset to the internal route
This is good when a module should serve as a shortcut to another application area instead of a self-contained module page.
Public Embedded Module
Use:
is_public = trueallowed_framing_hostsconfigured deliberately- a purpose-built
layoutorcanvas
This is the right pattern for public portals and embedded external experiences.
Design Questions To Ask Before Finalizing A Module
- Is this module a real destination or just a structural navigation node?
- Should it open a default view, a custom layout page, or a canvas?
- Should it be visible to everyone, only some roles, or publicly?
- Does it need to be embeddable in another host?
- Would a parent-child module structure make the navigation clearer?
- Is
link_type = Within apporExternalactually the right abstraction, or should this be a normal module instead?
Best Practices
- Design modules around user journeys and business areas, not around raw table structure.
- Use
link_type = Noneintentionally for structural parent modules. - Prefer
default_viewfor straightforward list-entry modules. - Use
layoutorcanvasonly when the module truly needs a custom landing experience. - Treat
is_publicandallowed_framing_hostsas exposure and security decisions, not convenience toggles. - Keep
module_namestable and usemodule_titlewhen the user-facing title needs different wording.