Layout & Navigation
Layout system
A pluggable module that aggregates navigation from all frontend modules and provides an Admin Layout Manager for toggling visibility.
Overview
- Frontend module contributes a route for an Admin Layout Manager page.
- Aggregates
navItems
from all loaded frontend modules viaFrontendModuleLoader
. - Supports role-based visibility through each item's
visible
predicate. - Non-invasive: does not alter existing app behavior; simply adds layout tooling.
Backend
src/modules/layout/index.ts
: declaresEnvSpec
and installs a small health endpoint.- Health check:
GET /api/layout/health
→{ ok: true, module: "layout", version: "1.0.0" }
Environment variables (backend)
FEATURE_LAYOUT
: Enable/disable the Layout module (default: enabled).LAYOUT_DEFAULT
: Default preset (e.g.,drawer-left
,drawer-right
,topbar-only
).LAYOUT_SHOW_FOOTER
: Whether to render a footer in the app shell (default:true
).
Frontend
client/src/modules/layout/index.ts
: registers route/admin/layout
(rendered under the app base) and contributes a topbar nav item to/app/admin/layout
.- Requires admin/owner: wrapped with
RequireAdmin
and usesisAuthenticatedWithSomeRole(["admin","owner"])
. client/src/modules/layout/pages/AdminLayoutManager.tsx
: loads modules, aggregatesnavItems
, and lets admins toggle item visibility.
Navigation item contract
// client/src/modules/types.ts
export type FrontendModuleNavItem = {
to: string; // e.g. "/app/admin/layout"
label: string; // UI label
area?: string; // e.g. "topbar"
icon?: React.ReactNode; // optional icon
visible?: boolean | (() => boolean); // RBAC or custom conditions
};
Admin Layout Manager
Page component: client/src/modules/layout/pages/AdminLayoutManager.tsx
- Persists hidden items in
localStorage
under key"layout.hiddenNavItems"
. - Emits a
window
event"layout:nav.changed"
after changes so consumers can re-render navigation. - Respects each item's
visible
predicate before presenting toggles.
// Toggle handler excerpt
function saveHidden(set: Set<string>) {
localStorage.setItem("layout.hiddenNavItems", JSON.stringify(Array.from(set)));
window.dispatchEvent(new Event("layout:nav.changed"));
}
Enable the module
# Backend/Frontend modules loader
MODULES_ENABLED=layout
# Optional (default is enabled)
FEATURE_LAYOUT=true
# Optional layout preferences
LAYOUT_DEFAULT=drawer-left
LAYOUT_SHOW_FOOTER=true
Restart the server. The backend exposes the health endpoint; the frontend adds the admin page and topbar item for admins.
Troubleshooting
- If the admin page doesn't show, ensure your user has
admin
orowner
role. - Verify
MODULES_ENABLED
containslayout
andFEATURE_LAYOUT
is not false. - Check console logs:
[frontend-modules][layout]
and[modules][layout]
in development.
Related
- Modules system — how modules are loaded and discovered.
- Auth & RBAC — roles required for accessing layout admin tools.