From 22aafe3a5597fca4b4c1aca607ceefb0cc0dea22 Mon Sep 17 00:00:00 2001 From: librelad Date: Fri, 29 May 2026 22:10:36 +0100 Subject: [PATCH] docs: frontend feature-module modularization design Synthesized architecture for turning the no-build vanilla-JS WebUI into a scan-and-manifest feature system mirroring the backend container scan: self-contained features// folders, a navigation kernel, uniform mount/unmount lifecycle, DI service context replacing ~80 window globals, per-feature CSS, god-file decomposition, and a strangler migration roadmap. Co-Authored-By: Claude Opus 4.8 Signed-off-by: librelad --- docs/frontend-modularization.md | 499 ++++++++++++++++++++++++++++++++ 1 file changed, 499 insertions(+) create mode 100644 docs/frontend-modularization.md diff --git a/docs/frontend-modularization.md b/docs/frontend-modularization.md new file mode 100644 index 0000000..42c7a6e --- /dev/null +++ b/docs/frontend-modularization.md @@ -0,0 +1,499 @@ +# LibrePortal WebUI — Feature-Module Architecture (Design Doc) + +**Status:** Proposed · **Audience:** implementing engineer · **Scope:** `containers/libreportal/frontend/` (no-build vanilla-JS SPA) + +--- + +## 1. Executive summary + +We turn the frontend into a **scan-and-manifest feature system** that mirrors the backend's container scan: each page becomes a self-contained folder (`features//`) carrying its own HTML fragment, scoped CSS, controller, and a `feature.json` manifest. A single shell generator — hung off the existing `webuiLibrePortalUpdate`/`libreportal regen` pass that already emits the apps-tools artifact — walks those folders and writes one read-only `/data/webui/generated/features.json`. A small **navigation kernel** consumes that manifest to build the route table, the topbar nav, and the per-feature CSS links, replacing the four hand-maintained registries (`index.html`, `spa.js` `routes` Map, `system-loader.js` component registry, `config-manager.js` `renderConfig()` if-chain). Every feature implements **one uniform lifecycle** (`mount(ctx)` / `unmount(ctx)`) and receives shared services (taskBus, liveSystem, auth, dataLoader, router, notifications) via an injected `ctx` instead of ~80 `window.*` globals. We stay **no-build by default** (plain `