librelad 0724ed785a feat(webui): load feature modules from the manifest (drop index.html script list)
The kernel now loads each feature's self-registering index.js from the
manifest (new 'module' field) before building routes, so index.html no
longer hardcodes a per-feature <script> list — one of the four registries
the modularization targets is now gone. Adding a page = drop a
features/<id>/ folder + a manifest entry; no index.html edit.

loadScript is idempotent and non-fatal: a module that 404s or fails to
register leaves its route on the legacy handler. Manifest-load failure
still falls back to the built-in route table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-29 23:52:51 +01:00

72 lines
2.2 KiB
JSON

{
"version": 1,
"note": "Phase-0 hand-committed manifest (to be replaced by the generated /data/webui/generated/features.json once the scan generator lands — see docs/frontend-modularization.md). 'module' is the feature's self-registering index.js; the kernel loads these from here so they no longer need <script> tags in index.html. 'handler' names the LibrePortalSPAClean method kept as the fallback during the strangler migration; 'navId' is the topbar element id for active-state highlighting.",
"features": [
{
"id": "dashboard",
"routes": ["/", "/dashboard"],
"module": "/features/dashboard/index.js",
"handler": "handleDashboard",
"navId": "nav-dashboard",
"nav": { "label": "Dashboard", "order": 10 }
},
{
"id": "apps",
"routes": ["/apps", "/apps*"],
"module": "/features/apps/index.js",
"handler": "handleApps",
"navId": "nav-app-center",
"nav": { "label": "App Center", "order": 20 }
},
{
"id": "app-detail",
"routes": ["/app", "/app*"],
"module": "/features/app-detail/index.js",
"handler": "handleAppDetail",
"navId": "nav-app-center"
},
{
"id": "admin",
"routes": ["/admin", "/admin*"],
"module": "/features/admin/index.js",
"handler": "handleAdmin",
"navId": "nav-config",
"nav": { "label": "Admin", "order": 40 }
},
{
"id": "config-redirect",
"routes": ["/config", "/config*"],
"handler": "handleConfigRedirect",
"navId": "nav-config"
},
{
"id": "tasks",
"routes": ["/tasks", "/tasks*"],
"module": "/features/tasks/index.js",
"handler": "handleTasks",
"navId": "nav-tasks",
"nav": { "label": "Tasks", "order": 60 }
},
{
"id": "backup",
"routes": ["/backup", "/backup*"],
"module": "/features/backup/index.js",
"handler": "handleBackup",
"navId": "nav-backup",
"nav": { "label": "Backups", "order": 50 }
},
{
"id": "peers",
"routes": ["/peers", "/peers*"],
"handler": "handlePeers",
"navId": "nav-config"
},
{
"id": "ssh",
"routes": ["/ssh", "/ssh*"],
"handler": "handleSsh",
"navId": "nav-config"
}
]
}