docs(03-03): complete module UI lazy loading plan summary
- Document module loader registry, category pages, and expanded module views - Record threat mitigations T-03-09, T-03-10, T-03-11 - Self-check passed: all files and commits verified
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
---
|
||||
phase: 03-module-system-domaincheck
|
||||
plan: 03
|
||||
subsystem: module-ui-loader
|
||||
tags: [lazy-loading, dynamic-imports, next-dynamic, category-page, module-cards]
|
||||
dependency_graph:
|
||||
requires:
|
||||
- module-registry-service
|
||||
- domaincheck-frontend-page
|
||||
provides:
|
||||
- module-loader-registry
|
||||
- category-page
|
||||
- expanded-module-view
|
||||
- api-client-utils
|
||||
affects: [sidebar-module-links, module-marketplace]
|
||||
tech_stack:
|
||||
added: []
|
||||
patterns: [next-dynamic-ssr-false, slug-whitelist-registry, category-grid-layout]
|
||||
key_files:
|
||||
created:
|
||||
- apps/web/src/lib/module-loader.ts
|
||||
- apps/web/src/lib/api.ts
|
||||
- apps/web/src/app/(portal)/modules/[category]/page.tsx
|
||||
- apps/web/src/app/(portal)/modules/[category]/components/ModuleCard.tsx
|
||||
- apps/web/src/app/(portal)/modules/[category]/[moduleSlug]/page.tsx
|
||||
modified:
|
||||
- apps/web/src/messages/de.json
|
||||
- apps/web/src/messages/en.json
|
||||
key_decisions:
|
||||
- "MODULE_REGISTRY whitelist pattern: only slugs explicitly listed can trigger dynamic imports (T-03-09)"
|
||||
- "Client components for all pages to support next/dynamic with ssr:false and client-side API fetching"
|
||||
- "Inline SVG icons to avoid external icon library dependency while keeping ModuleCard self-contained"
|
||||
patterns_established:
|
||||
- "Module registry pattern: slug -> { component, cardComponent? } mapping for lazy loading"
|
||||
- "Category page pattern: [category] dynamic route with API fetch + filter + grid render"
|
||||
- "Expanded module view pattern: [moduleSlug] route with whitelist check + dynamic component render"
|
||||
requirements_completed: [MOD-04]
|
||||
duration: 6min
|
||||
completed: 2026-06-19
|
||||
---
|
||||
|
||||
# Phase 03 Plan 03: Module UI Lazy Loading + Category Pages Summary
|
||||
|
||||
**Lazy-loaded module UI rendering via next/dynamic with slug-whitelist registry, category grid pages, and expanded module views**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 6 min
|
||||
- **Started:** 2026-06-19T11:32:50Z
|
||||
- **Completed:** 2026-06-19T11:38:50Z
|
||||
- **Tasks:** 2/2
|
||||
- **Files created:** 5
|
||||
- **Files modified:** 2
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- MODULE_REGISTRY in module-loader.ts maps module slugs to dynamically imported components via next/dynamic with ssr:false, ensuring inactive modules are never bundled (MOD-04)
|
||||
- Category page at /modules/[category] fetches active modules from API, filters by category, and renders a responsive card grid (D-04)
|
||||
- ModuleCard component displays icon, name, localized description, and link to expanded view with hover effects (D-05a)
|
||||
- Expanded module view at /modules/[category]/[moduleSlug] loads the module component on demand via whitelist lookup (D-05b)
|
||||
- API client utilities (getActiveModules, getModuleBySlug) provide typed fetch wrappers for module endpoints
|
||||
- i18n keys added for "modules" namespace in both German and English
|
||||
|
||||
## Task Commits
|
||||
|
||||
Each task was committed atomically:
|
||||
|
||||
1. **Task 1: Module Loader Utility + Category Page with Lazy Cards** - `a191628` (feat)
|
||||
2. **Task 2: Expanded Module View with Dynamic Routing** - `de63b10` (feat)
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `apps/web/src/lib/module-loader.ts` - MODULE_REGISTRY with loadModuleComponent and loadModuleCard exports
|
||||
- `apps/web/src/lib/api.ts` - getActiveModules and getModuleBySlug API client functions
|
||||
- `apps/web/src/app/(portal)/modules/[category]/page.tsx` - Category page with module grid and empty state
|
||||
- `apps/web/src/app/(portal)/modules/[category]/components/ModuleCard.tsx` - Module card with icon, description, and link
|
||||
- `apps/web/src/app/(portal)/modules/[category]/[moduleSlug]/page.tsx` - Expanded module view with lazy loading and not-found state
|
||||
- `apps/web/src/messages/de.json` - Added modules namespace (categoryTitle, openModule, noModules, notFound, etc.)
|
||||
- `apps/web/src/messages/en.json` - Added modules namespace (categoryTitle, openModule, noModules, notFound, etc.)
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- **Slug whitelist pattern:** MODULE_REGISTRY acts as an allowlist — only explicitly registered slugs can trigger dynamic imports. Arbitrary URL slugs get a not-found state, never an import attempt (T-03-09).
|
||||
- **Client components throughout:** All three pages use 'use client' to support next/dynamic with ssr:false and client-side fetch with credentials:include for auth cookie forwarding.
|
||||
- **Inline SVG icons:** ModuleCard uses inline SVGs rather than an icon library to avoid adding a dependency for a small number of icons. Icons are mapped by the module's icon property (e.g., 'Globe' for domaincheck).
|
||||
- **Category filtering:** The category page fetches all active modules and filters client-side by category. This keeps the API simple (single /modules/active endpoint) while supporting category-based views.
|
||||
|
||||
## Threat Mitigations Applied
|
||||
|
||||
| Threat ID | Mitigation | Implementation |
|
||||
|-----------|------------|----------------|
|
||||
| T-03-09 | Slug whitelist via MODULE_REGISTRY | module-loader.ts: only registered slugs resolve to components; [moduleSlug]/page.tsx checks `slug in MODULE_REGISTRY` before loading |
|
||||
| T-03-10 | API filters by tenant active modules | [category]/page.tsx: fetches from /modules/active which is tenant-scoped server-side |
|
||||
| T-03-11 | Accepted | Module names/descriptions are non-sensitive catalog data |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None - plan executed exactly as written.
|
||||
|
||||
## Verification Results
|
||||
|
||||
- `pnpm --filter web build`: PASS
|
||||
- Route `/modules/[category]` generated: confirmed in build output (2.01 kB)
|
||||
- Route `/modules/[category]/[moduleSlug]` generated: confirmed in build output (1.95 kB)
|
||||
- Domaincheck module code at `/modules/domaincheck` (1.47 kB) is separate from category page, confirming code-splitting works
|
||||
- No stubs or placeholders found in created files
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
All 5 created files verified on disk. Both task commits (a191628, de63b10) verified in git log.
|
||||
Reference in New Issue
Block a user