@rashidee/co2 1.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/dist/index.js +25449 -0
  2. package/drizzle/0000_remarkable_charles_xavier.sql +210 -0
  3. package/drizzle/0001_wise_wolf_cub.sql +13 -0
  4. package/drizzle/0002_secret_spyke.sql +16 -0
  5. package/drizzle/0003_workspace_config_singleton.sql +16 -0
  6. package/drizzle/0004_terminal_claim_v120.sql +11 -0
  7. package/drizzle/0005_brainstorm_v124.sql +10 -0
  8. package/drizzle/0006_project_v140.sql +6 -0
  9. package/drizzle/0007_prd_wizard_v124.sql +14 -0
  10. package/drizzle/0008_workflow_artifact_v126.sql +24 -0
  11. package/drizzle/0009_project_import_v150.sql +7 -0
  12. package/drizzle/0010_quality_v151.sql +3 -0
  13. package/drizzle/meta/0000_snapshot.json +1335 -0
  14. package/drizzle/meta/0001_snapshot.json +1416 -0
  15. package/drizzle/meta/0002_snapshot.json +1510 -0
  16. package/drizzle/meta/_journal.json +83 -0
  17. package/package.json +41 -0
  18. package/plugin/.claude-plugin/marketplace.json +36 -0
  19. package/plugin/.claude-plugin/plugin.json +22 -0
  20. package/plugin/README.md +625 -0
  21. package/plugin/SKILLS.md +350 -0
  22. package/plugin/co2.svg +5 -0
  23. package/plugin/commands/brainstorm-loop.md +129 -0
  24. package/plugin/skills/conductor-defect/SKILL.md +898 -0
  25. package/plugin/skills/conductor-feature-develop/SKILL.md +1383 -0
  26. package/plugin/skills/conductor-feature-develop/references/implementation-domain-template.md +131 -0
  27. package/plugin/skills/conductor-feature-develop/references/implementation-master-template.md +89 -0
  28. package/plugin/skills/conductor-feature-develop/references/playwright-setup.md +224 -0
  29. package/plugin/skills/conductor-feature-prepare/SKILL.md +604 -0
  30. package/plugin/skills/depgen-k8s/SKILL.md +468 -0
  31. package/plugin/skills/depgen-k8s/references/dockerfile-laravel.md +197 -0
  32. package/plugin/skills/depgen-k8s/references/dockerfile-nodejs.md +163 -0
  33. package/plugin/skills/depgen-k8s/references/dockerfile-spring-boot.md +174 -0
  34. package/plugin/skills/depgen-k8s/references/k8s-patterns.md +869 -0
  35. package/plugin/skills/mockgen-shadcn/SKILL.md +1067 -0
  36. package/plugin/skills/mockgen-shadcn/references/admin-layout-template.md +1467 -0
  37. package/plugin/skills/mockgen-shadcn/references/mockup-hub-template.md +498 -0
  38. package/plugin/skills/mockgen-shadcn/references/mockup-index-template.md +216 -0
  39. package/plugin/skills/mockgen-tailwind/SKILL.md +904 -0
  40. package/plugin/skills/mockgen-tailwind/references/admin-layout-template.md +720 -0
  41. package/plugin/skills/mockgen-tailwind/references/mockup-hub-template.md +498 -0
  42. package/plugin/skills/mockgen-tailwind/references/mockup-index-template.md +190 -0
  43. package/plugin/skills/modelgen-nosql/SKILL.md +617 -0
  44. package/plugin/skills/modelgen-nosql/references/model-extraction-methodology.md +497 -0
  45. package/plugin/skills/modelgen-nosql/references/nosql-design-guide.md +258 -0
  46. package/plugin/skills/modelgen-relational/SKILL.md +707 -0
  47. package/plugin/skills/modelgen-relational/references/model-extraction-methodology.md +499 -0
  48. package/plugin/skills/specgen-flutter-riverpod/SKILL.md +898 -0
  49. package/plugin/skills/specgen-flutter-riverpod/references/component-patterns.md +971 -0
  50. package/plugin/skills/specgen-flutter-riverpod/references/notification-patterns.md +457 -0
  51. package/plugin/skills/specgen-flutter-riverpod/references/routing-patterns.md +362 -0
  52. package/plugin/skills/specgen-flutter-riverpod/references/security-patterns.md +709 -0
  53. package/plugin/skills/specgen-flutter-riverpod/references/spec-template.md +1566 -0
  54. package/plugin/skills/specgen-flutter-riverpod/references/state-patterns.md +518 -0
  55. package/plugin/skills/specgen-flutter-riverpod/references/storage-patterns.md +370 -0
  56. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/SKILL.md +984 -0
  57. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/batch-patterns.md +359 -0
  58. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/messaging-patterns.md +468 -0
  59. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/modulith-patterns.md +461 -0
  60. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/reporting-patterns.md +803 -0
  61. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/security-patterns.md +501 -0
  62. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/spec-template.md +1268 -0
  63. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/web-patterns.md +301 -0
  64. package/plugin/skills/specgen-node-cli-web/SKILL.md +561 -0
  65. package/plugin/skills/specgen-node-cli-web/references/auth-patterns.md +293 -0
  66. package/plugin/skills/specgen-node-cli-web/references/cli-packaging-patterns.md +250 -0
  67. package/plugin/skills/specgen-node-cli-web/references/server-patterns.md +247 -0
  68. package/plugin/skills/specgen-node-cli-web/references/spec-template.md +401 -0
  69. package/plugin/skills/specgen-node-cli-web/references/testing-patterns.md +174 -0
  70. package/plugin/skills/specgen-react-mui/SKILL.md +789 -0
  71. package/plugin/skills/specgen-react-mui/references/component-patterns.md +1077 -0
  72. package/plugin/skills/specgen-react-mui/references/reporting-patterns.md +1998 -0
  73. package/plugin/skills/specgen-react-mui/references/routing-patterns.md +461 -0
  74. package/plugin/skills/specgen-react-mui/references/security-patterns.md +599 -0
  75. package/plugin/skills/specgen-react-mui/references/spec-template.md +1030 -0
  76. package/plugin/skills/specgen-react-mui/references/state-patterns.md +327 -0
  77. package/plugin/skills/specgen-react-tailwind/SKILL.md +859 -0
  78. package/plugin/skills/specgen-react-tailwind/references/component-patterns.md +1212 -0
  79. package/plugin/skills/specgen-react-tailwind/references/reporting-patterns.md +1529 -0
  80. package/plugin/skills/specgen-react-tailwind/references/routing-patterns.md +669 -0
  81. package/plugin/skills/specgen-react-tailwind/references/security-patterns.md +656 -0
  82. package/plugin/skills/specgen-react-tailwind/references/spec-template.md +1237 -0
  83. package/plugin/skills/specgen-react-tailwind/references/state-patterns.md +327 -0
  84. package/plugin/skills/specgen-sdk-java/SKILL.md +933 -0
  85. package/plugin/skills/specgen-sdk-java/references/api-extraction-patterns.md +247 -0
  86. package/plugin/skills/specgen-sdk-java/references/http-client-patterns.md +495 -0
  87. package/plugin/skills/specgen-sdk-java/references/packaging-patterns.md +366 -0
  88. package/plugin/skills/specgen-sdk-java/references/spec-template.md +956 -0
  89. package/plugin/skills/specgen-spring-jpa-jtehtmx/SKILL.md +1284 -0
  90. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/batch-patterns.md +1224 -0
  91. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/jasper-patterns.md +1638 -0
  92. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/messaging-patterns.md +512 -0
  93. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/modulith-patterns.md +354 -0
  94. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/security-patterns.md +551 -0
  95. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/spec-template.md +2502 -0
  96. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/web-patterns.md +503 -0
  97. package/plugin/skills/specgen-spring-jpa-restapi/SKILL.md +990 -0
  98. package/plugin/skills/specgen-spring-jpa-restapi/references/batch-patterns.md +1224 -0
  99. package/plugin/skills/specgen-spring-jpa-restapi/references/messaging-patterns.md +512 -0
  100. package/plugin/skills/specgen-spring-jpa-restapi/references/modulith-patterns.md +279 -0
  101. package/plugin/skills/specgen-spring-jpa-restapi/references/reporting-patterns.md +1536 -0
  102. package/plugin/skills/specgen-spring-jpa-restapi/references/restapi-patterns.md +722 -0
  103. package/plugin/skills/specgen-spring-jpa-restapi/references/security-patterns.md +351 -0
  104. package/plugin/skills/specgen-spring-jpa-restapi/references/spec-template.md +553 -0
  105. package/plugin/skills/specgen-ts-cli/SKILL.md +861 -0
  106. package/plugin/skills/specgen-ts-cli/references/async-patterns.md +1101 -0
  107. package/plugin/skills/specgen-ts-cli/references/command-patterns.md +383 -0
  108. package/plugin/skills/specgen-ts-cli/references/config-patterns.md +430 -0
  109. package/plugin/skills/specgen-ts-cli/references/database-patterns.md +750 -0
  110. package/plugin/skills/specgen-ts-cli/references/packaging-patterns.md +426 -0
  111. package/plugin/skills/specgen-ts-cli/references/spec-template.md +1391 -0
  112. package/plugin/skills/specgen-ts-cli/references/testing-patterns.md +909 -0
  113. package/plugin/skills/testgen-functional/SKILL.md +1381 -0
  114. package/plugin/skills/tracegen-matrix/SKILL.md +243 -0
  115. package/plugin/skills/util-preparek8senv/SKILL.md +422 -0
  116. package/plugin/skills/util-projectinit/SKILL.md +307 -0
  117. package/plugin/skills/util-projectinit/reference/brainstorm-loop.md +129 -0
  118. package/plugin/skills/util-projectinit/reference/brainstorm-protocol.md +144 -0
  119. package/plugin/skills/util-projectinit/reference/brainstorm-setup-guide.md +153 -0
  120. package/plugin/skills/util-projectinit/reference/brainstorm-template-appdev.md +87 -0
  121. package/plugin/skills/util-projectinit/reference/co2-context-generation-guide.md +761 -0
  122. package/plugin/skills/util-projectsync/SKILL.md +501 -0
  123. package/plugin/skills/util-updprd/SKILL.md +324 -0
  124. package/plugin/skills/util-usanalyzer/SKILL.md +307 -0
  125. package/plugin/skills/util-ustagger/SKILL.md +154 -0
  126. package/static/assets/abnfDiagram-VRR7QNED-DvPuwyCV.js +1 -0
  127. package/static/assets/arc-DRKw7sjs.js +1 -0
  128. package/static/assets/architectureDiagram-ZJ3FMSHR-CaNcxUbC.js +36 -0
  129. package/static/assets/blockDiagram-677ZJIJ3-Demd4AOK.js +132 -0
  130. package/static/assets/c4Diagram-LMCZKHZV-PVKUfc2x.js +10 -0
  131. package/static/assets/channel-C2nVbuwv.js +1 -0
  132. package/static/assets/chunk-2Q5K7J3B-CExf8ww_.js +1 -0
  133. package/static/assets/chunk-32BRIVSS-CFPaoONF.js +1 -0
  134. package/static/assets/chunk-5VM5RSS4-DE2esM67.js +15 -0
  135. package/static/assets/chunk-EX3LRPZG-SON_YdDG.js +231 -0
  136. package/static/assets/chunk-JWPE2WC7-Qxah8LNr.js +1 -0
  137. package/static/assets/chunk-MOJQB5TN-BcWGQV3j.js +88 -0
  138. package/static/assets/chunk-RYQCIY6F-DkDj-OR5.js +1 -0
  139. package/static/assets/chunk-V7JOEXUC-BlI1Mrah.js +206 -0
  140. package/static/assets/chunk-VR4S4FIN-Agf__duj.js +1 -0
  141. package/static/assets/chunk-XXDRQBXY-B5CfAh85.js +1 -0
  142. package/static/assets/classDiagram-OUVF2IWQ-DXJIljsR.js +1 -0
  143. package/static/assets/classDiagram-v2-EOCWNBFH-DXJIljsR.js +1 -0
  144. package/static/assets/cose-bilkent-JH36ORCC-DO0cQkcy.js +1 -0
  145. package/static/assets/cynefin-VYW2F7L2-CfOnsnXc.js +178 -0
  146. package/static/assets/cynefinDiagram-TSTJHNR4-BJ8tULAv.js +62 -0
  147. package/static/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
  148. package/static/assets/dagre-VKFMJZFB-DfjwzHqP.js +4 -0
  149. package/static/assets/defaultLocale-DX6XiGOO.js +1 -0
  150. package/static/assets/diagram-FQU43EPY-CndSOIIM.js +3 -0
  151. package/static/assets/diagram-G47NLZAW-Czf5hN0Z.js +24 -0
  152. package/static/assets/diagram-NH7WQ7WH-COAyojGh.js +24 -0
  153. package/static/assets/diagram-OA4YK3LP-H8PoiN2m.js +30 -0
  154. package/static/assets/diagram-WEI45ONY-DzcaVzjp.js +41 -0
  155. package/static/assets/ebnfDiagram-CCIWWBDH-DPazGYLJ.js +1 -0
  156. package/static/assets/erDiagram-Q63AITRT-Bo-fubgF.js +85 -0
  157. package/static/assets/flowDiagram-23GEKE2U-CSvxUDwh.js +156 -0
  158. package/static/assets/ganttDiagram-NO4QXBWP-DnBveWX6.js +292 -0
  159. package/static/assets/gitGraphDiagram-IHSO6WYX-B3rVL8c-.js +106 -0
  160. package/static/assets/graph-C9eacEi8.js +1 -0
  161. package/static/assets/index-LZSQkLE2.css +41 -0
  162. package/static/assets/index-y7XDSgMG.js +495 -0
  163. package/static/assets/infoDiagram-FWYZ7A6U-CvWV9yy2.js +2 -0
  164. package/static/assets/init-Gi6I4Gst.js +1 -0
  165. package/static/assets/ishikawaDiagram-FXEZZL3T-DF28a1N6.js +70 -0
  166. package/static/assets/journeyDiagram-5HDEW3XC-CB6CugYk.js +139 -0
  167. package/static/assets/kanban-definition-HUTT4EX6-ResSLF6d.js +89 -0
  168. package/static/assets/katex-C5jXJg4s.js +257 -0
  169. package/static/assets/layout-DEXfKzaS.js +1 -0
  170. package/static/assets/linear-CLO--ryk.js +1 -0
  171. package/static/assets/map-Czzmt4hB.js +1 -0
  172. package/static/assets/mindmap-definition-LN4V7U3C-BvW3EbxX.js +96 -0
  173. package/static/assets/ordinal-Cboi1Yqb.js +1 -0
  174. package/static/assets/pegDiagram-2B236MQR-BHCgqrrM.js +1 -0
  175. package/static/assets/pieDiagram-ENE6RG2P-DVmCQ5FA.js +39 -0
  176. package/static/assets/quadrantDiagram-ABIIQ3AL-B3e5KR52.js +7 -0
  177. package/static/assets/railroadDiagram-RFXS5EU6-Csv5ysLc.js +1 -0
  178. package/static/assets/requirementDiagram-TGXJPOKE-DOMVzvnB.js +84 -0
  179. package/static/assets/sankeyDiagram-HTMAVEWB-B1dcTOvy.js +40 -0
  180. package/static/assets/sequenceDiagram-DBY2YBRQ-BY414yeO.js +162 -0
  181. package/static/assets/sizeCapture-X5ZJPWSS-CuJfrfBN.js +1 -0
  182. package/static/assets/stateDiagram-2N3HPSRC-FX4rJkzV.js +1 -0
  183. package/static/assets/stateDiagram-v2-6OUMAXLB-BVufbO_H.js +1 -0
  184. package/static/assets/swimlanes-5IMT3BWC-Sfy58mmv.js +2 -0
  185. package/static/assets/swimlanesDiagram-G3AALYLV-wDCDw08H.js +8 -0
  186. package/static/assets/timeline-definition-FHXFAJF6-CmV7by8p.js +120 -0
  187. package/static/assets/vennDiagram-L72KCM5P-FqIyFZFt.js +34 -0
  188. package/static/assets/wardleyDiagram-EHGQE667-BZ06O45i.js +78 -0
  189. package/static/assets/xychartDiagram-FW5EYKEG-BOkffR06.js +7 -0
  190. package/static/index.html +24 -0
@@ -0,0 +1,461 @@
1
+ # Routing Patterns — React Router v7 + Feature-Based Architecture
2
+
3
+ This reference describes the React Router v7 conventions and feature-based directory
4
+ structure used in the spec. Include this content in Sections 4 and 7 of the generated
5
+ specification.
6
+
7
+ ---
8
+
9
+ ## Feature-Based Directory Structure
10
+
11
+ Each PRD module maps to a `src/features/<module>/` folder. This co-locates everything
12
+ related to a feature (types, API, hooks, components, pages) so the coding agent can
13
+ implement one feature folder at a time.
14
+
15
+ ```
16
+ src/
17
+ ├── main.tsx # App entry — providers, ReactDOM.render
18
+ ├── App.tsx # Root component — router, theme, notifications
19
+ ├── router/
20
+ │ └── index.tsx # Route tree definition
21
+ ├── lib/
22
+ │ ├── api/
23
+ │ │ ├── axiosInstance.ts # Axios instance with interceptors
24
+ │ │ └── authBridge.ts # [If Auth = Keycloak] Auth bridge for interceptors
25
+ │ ├── auth/
26
+ │ │ ├── oidcConfig.ts # [If Auth = Keycloak] oidc-client-ts config
27
+ │ │ ├── keycloakRoles.ts # [If Auth = Keycloak] Role extraction utilities
28
+ │ │ ├── useAuthUser.ts # [If Auth = Keycloak] Auth hook wrapper
29
+ │ │ └── roles.ts # Role constants
30
+ │ └── queryClient.ts # TanStack Query QueryClient instance
31
+ ├── store/
32
+ │ ├── auth.store.ts # [If Auth = Local] Zustand auth store
33
+ │ └── ui.store.ts # Zustand UI store (sidebar, theme mode)
34
+ ├── shared/
35
+ │ ├── layouts/
36
+ │ │ ├── DashboardLayout.tsx # Authenticated layout (sidebar + topbar + outlet)
37
+ │ │ ├── PublicLayout.tsx # Public layout (header/footer + outlet)
38
+ │ │ └── AuthLayout.tsx # Minimal centered layout for login/callback
39
+ │ ├── components/
40
+ │ │ ├── ProtectedRoute.tsx # Auth + role guard wrapper
41
+ │ │ ├── PageHeader.tsx # Page title + breadcrumbs + action buttons
42
+ │ │ ├── DataTable.tsx # Generic MUI Table with sorting/pagination
43
+ │ │ ├── ConfirmDialog.tsx # Generic confirmation Modal
44
+ │ │ ├── StatusChip.tsx # Colored MUI Chip for status badges
45
+ │ │ ├── FormDialog.tsx # Full-screen or modal form dialog wrapper
46
+ │ │ ├── ImageUpload.tsx # Drag-and-drop image upload with preview
47
+ │ │ ├── LoadingOverlay.tsx # Full-page CircularProgress overlay
48
+ │ │ ├── EmptyState.tsx # Empty list placeholder with icon + message
49
+ │ │ ├── ErrorBoundary.tsx # React ErrorBoundary with fallback UI
50
+ │ │ └── SearchInput.tsx # Debounced search text field
51
+ │ ├── hooks/
52
+ │ │ ├── useDebounce.ts # Generic debounce hook
53
+ │ │ ├── useNotification.ts # Toast notification Zustand hook
54
+ │ │ └── useConfirm.ts # Confirm dialog imperative hook
55
+ │ └── form/
56
+ │ ├── TextFieldController.tsx # RHF Controller wrapping MUI TextField
57
+ │ ├── SelectController.tsx # RHF Controller wrapping MUI Select
58
+ │ ├── DatePickerController.tsx # RHF Controller wrapping MUI X DatePicker
59
+ │ ├── SwitchController.tsx # RHF Controller wrapping MUI Switch
60
+ │ ├── AutocompleteController.tsx# RHF Controller wrapping MUI Autocomplete
61
+ │ └── RichTextController.tsx # [If RichText = yes] RHF Controller for Quill
62
+ ├── features/
63
+ │ ├── auth/ # [If Auth != none] Auth feature
64
+ │ │ ├── pages/
65
+ │ │ │ ├── LoginPage.tsx # [If Auth = Local] Login form page
66
+ │ │ │ └── AuthCallbackPage.tsx # [If Auth = Keycloak] OIDC callback handler
67
+ │ │ └── index.ts
68
+ │ ├── {{module1}}/ # PRD module 1 (e.g., heroSection)
69
+ │ │ ├── api/
70
+ │ │ │ └── {{module1}}Api.ts # Axios API functions
71
+ │ │ ├── components/
72
+ │ │ │ ├── {{Module1}}List.tsx # List table/grid component
73
+ │ │ │ ├── {{Module1}}Form.tsx # Create/edit form
74
+ │ │ │ └── {{Module1}}Card.tsx # Card component (if applicable)
75
+ │ │ ├── hooks/
76
+ │ │ │ ├── use{{Module1}}s.ts # useQuery for list
77
+ │ │ │ ├── use{{Module1}}.ts # useQuery for single item
78
+ │ │ │ └── use{{Module1}}Mutations.ts # useMutation for CUD operations
79
+ │ │ ├── pages/
80
+ │ │ │ ├── {{Module1}}ListPage.tsx # List page component (lazy-loaded)
81
+ │ │ │ └── {{Module1}}FormPage.tsx # Create/edit page (lazy-loaded)
82
+ │ │ ├── store/
83
+ │ │ │ └── {{module1}}.store.ts # [If needed] Feature-level Zustand store
84
+ │ │ ├── {{module1}}.types.ts # TypeScript interfaces
85
+ │ │ ├── {{module1}}.schema.ts # Zod validation schemas
86
+ │ │ └── index.ts # Public API re-exports
87
+ │ └── {{module2}}/
88
+ │ └── (same structure)
89
+ ├── theme/
90
+ │ ├── index.ts # MUI createTheme() with design tokens
91
+ │ ├── palette.ts # Color palette extracted from mockup
92
+ │ └── typography.ts # Font config extracted from mockup
93
+ └── types/
94
+ └── global.d.ts # Global type augmentations (e.g., import.meta.env)
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Route Tree Definition
100
+
101
+ ```tsx
102
+ // src/router/index.tsx
103
+ import { lazy, Suspense } from 'react';
104
+ import { createBrowserRouter, Navigate } from 'react-router-dom';
105
+ import { DashboardLayout } from '../shared/layouts/DashboardLayout';
106
+ import { PublicLayout } from '../shared/layouts/PublicLayout';
107
+ import { AuthLayout } from '../shared/layouts/AuthLayout';
108
+ import { ProtectedRoute } from '../shared/components/ProtectedRoute';
109
+ import { LoadingOverlay } from '../shared/components/LoadingOverlay';
110
+ import { Roles } from '../lib/auth/roles';
111
+
112
+ // Lazy-load all page components for code splitting
113
+ // [If Auth = Keycloak]
114
+ const AuthCallbackPage = lazy(() =>
115
+ import('../features/auth/pages/AuthCallbackPage').then((m) => ({
116
+ default: m.AuthCallbackPage,
117
+ })),
118
+ );
119
+
120
+ // [If Auth = Local]
121
+ const LoginPage = lazy(() =>
122
+ import('../features/auth/pages/LoginPage').then((m) => ({ default: m.LoginPage })),
123
+ );
124
+
125
+ // Dashboard / home page
126
+ const DashboardPage = lazy(() =>
127
+ import('../features/dashboard/pages/DashboardPage').then((m) => ({
128
+ default: m.DashboardPage,
129
+ })),
130
+ );
131
+
132
+ // Hero Section (example — replace with actual modules from PRD)
133
+ const HeroSectionListPage = lazy(() =>
134
+ import('../features/heroSection/pages/HeroSectionListPage').then((m) => ({
135
+ default: m.HeroSectionListPage,
136
+ })),
137
+ );
138
+ const HeroSectionFormPage = lazy(() =>
139
+ import('../features/heroSection/pages/HeroSectionFormPage').then((m) => ({
140
+ default: m.HeroSectionFormPage,
141
+ })),
142
+ );
143
+
144
+ // Fallback wrapper for lazy-loaded components
145
+ function SuspenseWrapper({ children }: { children: React.ReactNode }) {
146
+ return <Suspense fallback={<LoadingOverlay />}>{children}</Suspense>;
147
+ }
148
+
149
+ export const router = createBrowserRouter([
150
+ // ── Auth routes (public) ────────────────────────────────────────────
151
+ {
152
+ element: <AuthLayout />,
153
+ children: [
154
+ // [If Auth = Keycloak]
155
+ {
156
+ path: '/auth/callback',
157
+ element: (
158
+ <SuspenseWrapper>
159
+ <AuthCallbackPage />
160
+ </SuspenseWrapper>
161
+ ),
162
+ },
163
+ // [If Auth = Local]
164
+ {
165
+ path: '/login',
166
+ element: (
167
+ <SuspenseWrapper>
168
+ <LoginPage />
169
+ </SuspenseWrapper>
170
+ ),
171
+ },
172
+ ],
173
+ },
174
+
175
+ // ── Protected / dashboard routes ────────────────────────────────────
176
+ {
177
+ element: (
178
+ <ProtectedRoute>
179
+ <DashboardLayout />
180
+ </ProtectedRoute>
181
+ ),
182
+ children: [
183
+ {
184
+ index: true,
185
+ element: <Navigate to="/dashboard" replace />,
186
+ },
187
+ {
188
+ path: '/dashboard',
189
+ element: (
190
+ <SuspenseWrapper>
191
+ <DashboardPage />
192
+ </SuspenseWrapper>
193
+ ),
194
+ },
195
+
196
+ // Hero Section — accessible by ADMIN and EDITOR
197
+ {
198
+ path: '/hero-section',
199
+ element: (
200
+ <ProtectedRoute requiredRoles={[Roles.ADMIN, Roles.EDITOR]}>
201
+ <SuspenseWrapper>
202
+ <HeroSectionListPage />
203
+ </SuspenseWrapper>
204
+ </ProtectedRoute>
205
+ ),
206
+ },
207
+ {
208
+ path: '/hero-section/create',
209
+ element: (
210
+ <ProtectedRoute requiredRoles={[Roles.ADMIN, Roles.EDITOR]}>
211
+ <SuspenseWrapper>
212
+ <HeroSectionFormPage />
213
+ </SuspenseWrapper>
214
+ </ProtectedRoute>
215
+ ),
216
+ },
217
+ {
218
+ path: '/hero-section/:id/edit',
219
+ element: (
220
+ <ProtectedRoute requiredRoles={[Roles.ADMIN, Roles.EDITOR]}>
221
+ <SuspenseWrapper>
222
+ <HeroSectionFormPage />
223
+ </SuspenseWrapper>
224
+ </ProtectedRoute>
225
+ ),
226
+ },
227
+
228
+ // Add additional module routes following the same pattern...
229
+ ],
230
+ },
231
+
232
+ // ── Error routes ────────────────────────────────────────────────────
233
+ {
234
+ path: '/unauthorized',
235
+ element: <div>You do not have permission to access this page.</div>,
236
+ },
237
+ {
238
+ path: '*',
239
+ element: <div>404 — Page not found.</div>,
240
+ },
241
+ ]);
242
+ ```
243
+
244
+ ---
245
+
246
+ ## DashboardLayout
247
+
248
+ ```tsx
249
+ // src/shared/layouts/DashboardLayout.tsx
250
+ import { useState } from 'react';
251
+ import { Outlet } from 'react-router-dom';
252
+ import { Box, Toolbar } from '@mui/material';
253
+ import { AppTopBar } from '../components/AppTopBar';
254
+ import { AppSidebar } from '../components/AppSidebar';
255
+
256
+ const DRAWER_WIDTH = 240;
257
+
258
+ export function DashboardLayout() {
259
+ const [sidebarOpen, setSidebarOpen] = useState(true);
260
+
261
+ return (
262
+ <Box sx={{ display: 'flex', minHeight: '100vh' }}>
263
+ <AppTopBar
264
+ drawerWidth={DRAWER_WIDTH}
265
+ sidebarOpen={sidebarOpen}
266
+ onToggleSidebar={() => setSidebarOpen((prev) => !prev)}
267
+ />
268
+ <AppSidebar
269
+ drawerWidth={DRAWER_WIDTH}
270
+ open={sidebarOpen}
271
+ />
272
+ <Box
273
+ component="main"
274
+ sx={{
275
+ flexGrow: 1,
276
+ p: 3,
277
+ ml: sidebarOpen ? `${DRAWER_WIDTH}px` : 0,
278
+ transition: (theme) =>
279
+ theme.transitions.create('margin', {
280
+ easing: theme.transitions.easing.sharp,
281
+ duration: theme.transitions.duration.leavingScreen,
282
+ }),
283
+ }}
284
+ >
285
+ <Toolbar /> {/* Spacer for fixed AppBar */}
286
+ <Outlet />
287
+ </Box>
288
+ </Box>
289
+ );
290
+ }
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Sidebar Navigation
296
+
297
+ ```typescript
298
+ // src/shared/components/navigationConfig.ts
299
+ import DashboardIcon from '@mui/icons-material/Dashboard';
300
+ import ImageIcon from '@mui/icons-material/Image';
301
+ import PeopleIcon from '@mui/icons-material/People';
302
+ import type { SvgIconComponent } from '@mui/icons-material';
303
+ import { Roles } from '../../lib/auth/roles';
304
+
305
+ export interface NavItem {
306
+ label: string;
307
+ path: string;
308
+ icon: SvgIconComponent;
309
+ /** If provided, user must have at least one of these roles to see this item */
310
+ requiredRoles?: string[];
311
+ children?: NavItem[];
312
+ }
313
+
314
+ /**
315
+ * All sidebar navigation items.
316
+ * Items with requiredRoles are hidden for users who lack those roles.
317
+ * Replace with actual modules from the PRD.md.
318
+ */
319
+ export const navigationItems: NavItem[] = [
320
+ {
321
+ label: 'Dashboard',
322
+ path: '/dashboard',
323
+ icon: DashboardIcon,
324
+ // No requiredRoles = accessible to all authenticated users
325
+ },
326
+ {
327
+ label: 'Hero Section',
328
+ path: '/hero-section',
329
+ icon: ImageIcon,
330
+ requiredRoles: [Roles.ADMIN, Roles.EDITOR],
331
+ },
332
+ {
333
+ label: 'Users',
334
+ path: '/users',
335
+ icon: PeopleIcon,
336
+ requiredRoles: [Roles.ADMIN],
337
+ },
338
+ // Add additional nav items matching the mockup sidebar files...
339
+ ];
340
+ ```
341
+
342
+ ```tsx
343
+ // src/shared/components/AppSidebar.tsx
344
+ import {
345
+ Drawer,
346
+ List,
347
+ ListItemButton,
348
+ ListItemIcon,
349
+ ListItemText,
350
+ Toolbar,
351
+ } from '@mui/material';
352
+ import { useNavigate, useLocation } from 'react-router-dom';
353
+ import { useAuthUser } from '../../lib/auth/useAuthUser';
354
+ import { navigationItems } from './navigationConfig';
355
+
356
+ interface AppSidebarProps {
357
+ drawerWidth: number;
358
+ open: boolean;
359
+ }
360
+
361
+ export function AppSidebar({ drawerWidth, open }: AppSidebarProps) {
362
+ const { hasAnyRole } = useAuthUser();
363
+ const navigate = useNavigate();
364
+ const location = useLocation();
365
+
366
+ const visibleItems = navigationItems.filter(
367
+ (item) => !item.requiredRoles || hasAnyRole(item.requiredRoles),
368
+ );
369
+
370
+ return (
371
+ <Drawer
372
+ variant="persistent"
373
+ anchor="left"
374
+ open={open}
375
+ sx={{
376
+ width: drawerWidth,
377
+ flexShrink: 0,
378
+ '& .MuiDrawer-paper': { width: drawerWidth, boxSizing: 'border-box' },
379
+ }}
380
+ >
381
+ <Toolbar />
382
+ <List>
383
+ {visibleItems.map((item) => {
384
+ const Icon = item.icon;
385
+ const isActive = location.pathname.startsWith(item.path);
386
+ return (
387
+ <ListItemButton
388
+ key={item.path}
389
+ selected={isActive}
390
+ onClick={() => navigate(item.path)}
391
+ >
392
+ <ListItemIcon>
393
+ <Icon color={isActive ? 'primary' : 'inherit'} />
394
+ </ListItemIcon>
395
+ <ListItemText primary={item.label} />
396
+ </ListItemButton>
397
+ );
398
+ })}
399
+ </List>
400
+ </Drawer>
401
+ );
402
+ }
403
+ ```
404
+
405
+ ---
406
+
407
+ ## Breadcrumb Pattern
408
+
409
+ ```tsx
410
+ // src/shared/components/PageHeader.tsx
411
+ import { Box, Breadcrumbs, Link, Typography } from '@mui/material';
412
+ import { useNavigate } from 'react-router-dom';
413
+
414
+ export interface BreadcrumbItem {
415
+ label: string;
416
+ path?: string;
417
+ }
418
+
419
+ interface PageHeaderProps {
420
+ title: string;
421
+ breadcrumbs?: BreadcrumbItem[];
422
+ actions?: React.ReactNode;
423
+ }
424
+
425
+ export function PageHeader({ title, breadcrumbs, actions }: PageHeaderProps) {
426
+ const navigate = useNavigate();
427
+
428
+ return (
429
+ <Box sx={{ mb: 3 }}>
430
+ {breadcrumbs && (
431
+ <Breadcrumbs sx={{ mb: 1 }}>
432
+ {breadcrumbs.map((crumb, index) =>
433
+ crumb.path ? (
434
+ <Link
435
+ key={index}
436
+ component="button"
437
+ variant="body2"
438
+ onClick={() => navigate(crumb.path!)}
439
+ underline="hover"
440
+ color="inherit"
441
+ >
442
+ {crumb.label}
443
+ </Link>
444
+ ) : (
445
+ <Typography key={index} variant="body2" color="text.primary">
446
+ {crumb.label}
447
+ </Typography>
448
+ ),
449
+ )}
450
+ </Breadcrumbs>
451
+ )}
452
+ <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
453
+ <Typography variant="h5" fontWeight={600}>
454
+ {title}
455
+ </Typography>
456
+ {actions && <Box sx={{ display: 'flex', gap: 1 }}>{actions}</Box>}
457
+ </Box>
458
+ </Box>
459
+ );
460
+ }
461
+ ```