Appearance
Add menus
What you're doing
Putting your pages in the ERP's navigation. A menu is a tree of nodes, each pointing at a route. One file under spk-assembly/metadata/menu/.
There is a second, easy-to-miss step: a master menu scaffold file that some deployments keep as the merged sidenav. If your plugin's module belongs to a larger application (e.g. HCM), you update that too — see below.
The complete example
spk-assembly/metadata/menu/office-equipment-menu.json — real file:
json
{
"name": "office-equipment-menu",
"description": "Navigation contributed by the Office Equipment plugin.",
"definition": {
"contractVersion": 1,
"name": "office-equipment-menu",
"nodes": [
{
"id": "office-equipment.equipment",
"name": "equipment",
"displayName": "Office Equipment",
"sequence": 0,
"navigation": { "route": null, "openMode": "current-tab" },
"visibility": { "visible": true, "enabled": true, "devices": [] },
"color": null,
"children": [
{
"id": "office-equipment.equipment.equipment-register",
"name": "equipment-register",
"displayName": "Equipment Register",
"sequence": 0,
"children": [],
"navigation": { "route": "/office-equipment/equipment-register", "openMode": "current-tab" },
"visibility": { "visible": true, "enabled": true, "devices": [] },
"color": null
},
{
"id": "office-equipment.equipment.equipment-catalog",
"name": "equipment-catalog",
"displayName": "Equipment Catalog",
"sequence": 1,
"children": [],
"navigation": { "route": "/office-equipment/equipment-catalog", "openMode": "current-tab" },
"visibility": { "visible": true, "enabled": true, "devices": [] },
"color": null
},
{
"id": "office-equipment.equipment.equipment-checkout",
"name": "equipment-checkout",
"displayName": "Equipment Checkout",
"sequence": 2,
"children": [],
"navigation": { "route": "/office-equipment/equipment-checkout", "openMode": "current-tab" },
"visibility": { "visible": true, "enabled": true, "devices": [] },
"color": null
}
]
}
]
},
"modules": ["office-equipment"]
}Line by line
nodes— the tree. A parent node withnavigation.route: nullis a group header; itschildrenare the clickable items.id— dotted, unique, conventionally<pluginId>.<group>.<page>.name— a short slug.displayName— the label shown. (For a translated label usedisplayNameKeywith an i18n key instead.)sequence— sort order among siblings.navigation.route— the page'sroute.pattern, exactly. This is the internal routing key, not the browser URL.visibility.devices—[]means all devices;["mobile"]restricts.modules— the module id(s) this menu contributes to. Match your pages'modules.
Scaffold with the CLI
bash
erp menu create office-equipment office-equipment-menu \
--display-name "Equipment Register" --route /office-equipment/equipment-register --icon devicesproduces a valid one-node menu you then flesh out. (Run it from PowerShell on Windows, or the leading / in --route gets mangled by Git Bash.)
The master-scaffold sync note
Some applications (the HCM suite is the canonical case) keep a single hand-maintained "master menu" file — e.g. hcm-foundation-main-menu.json — that is the merged sidenav shown whether or not a given plugin is installed. If your module attaches to such an application, a new page needs its node added in two places:
- your own
metadata/menu/<plugin>-menu.json(above), and - the application's master menu scaffold.
Skipping (2) means the item is missing from the merged sidenav for anyone who sees the app but hasn't installed your plugin. A standalone plugin that ships its own metadata/application/*.json (like the tutorial) has no master scaffold to sync — one menu file is enough.
Ground yourself first
bash
erp schema pull menuHow to verify it worked
bash
erp schema validate spk-assembly/metadata/menu/office-equipment-menu.json --schema menuOK — ... matches schema "menu"After publishing, open the ERP and confirm the group and its items appear in the sidenav under your application, and each item navigates to the right page.
Common mistakes
| Symptom | Cause | Fix |
|---|---|---|
| menu item 404s | navigation.route doesn't match the page's route.pattern | copy it exactly |
| item appears but page is blank | page's modules array doesn't include this module | align them |
| item missing from the merged app sidenav | didn't sync the master menu scaffold | add the node there too |
erp menu create route is a Windows path | Git Bash / mangling | run from PowerShell / MSYS_NO_PATHCONV=1 |