@rashidee/co2 1.3.7 → 1.3.9

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 (77) hide show
  1. package/dist/.co2-dat/app.db +0 -0
  2. package/dist/.co2-dat/app.db-shm +0 -0
  3. package/dist/.co2-dat/app.db-wal +0 -0
  4. package/dist/index.js +204 -75
  5. package/package.json +41 -41
  6. package/plugin/skills/conductor-feature-develop/SKILL.md +1384 -1383
  7. package/plugin/skills/conductor-feature-develop/references/playwright-setup.md +225 -224
  8. package/plugin/skills/mockgen-shadcn/SKILL.md +1073 -1067
  9. package/plugin/skills/mockgen-shadcn/references/admin-layout-template.md +5 -3
  10. package/plugin/skills/mockgen-shadcn/references/mockup-hub-template.md +631 -498
  11. package/plugin/skills/mockgen-shadcn/references/mockup-index-template.md +2 -2
  12. package/plugin/skills/mockgen-tailwind/SKILL.md +913 -904
  13. package/plugin/skills/mockgen-tailwind/references/admin-layout-template.md +722 -720
  14. package/plugin/skills/mockgen-tailwind/references/mockup-hub-template.md +631 -498
  15. package/plugin/skills/mockgen-tailwind/references/mockup-index-template.md +190 -190
  16. package/static/assets/{abnfDiagram-VRR7QNED-CsyqZblo.js → abnfDiagram-VRR7QNED-C0CrqPXX.js} +1 -1
  17. package/static/assets/{arc-it3yvCvj.js → arc-BFSRYIcI.js} +1 -1
  18. package/static/assets/{architectureDiagram-ZJ3FMSHR-sjNv2MOQ.js → architectureDiagram-ZJ3FMSHR-DuwTK2W9.js} +1 -1
  19. package/static/assets/{blockDiagram-677ZJIJ3-DW9ZjtwO.js → blockDiagram-677ZJIJ3-Bn9tAB0n.js} +1 -1
  20. package/static/assets/{c4Diagram-LMCZKHZV-DP3gJkhN.js → c4Diagram-LMCZKHZV-CDiCEjY7.js} +1 -1
  21. package/static/assets/channel-CZGeGYqv.js +1 -0
  22. package/static/assets/{chunk-2Q5K7J3B-ByxTr7KB.js → chunk-2Q5K7J3B-BMwS7NgW.js} +1 -1
  23. package/static/assets/{chunk-32BRIVSS-vNETwpX4.js → chunk-32BRIVSS-8l0XBCjq.js} +1 -1
  24. package/static/assets/{chunk-5VM5RSS4-DbdsRtpE.js → chunk-5VM5RSS4-C6Cv-67E.js} +1 -1
  25. package/static/assets/{chunk-EX3LRPZG-DPkDGikN.js → chunk-EX3LRPZG-DjWs4lB9.js} +1 -1
  26. package/static/assets/{chunk-JWPE2WC7-Ccpx-Rog.js → chunk-JWPE2WC7-DuK_Mu9c.js} +1 -1
  27. package/static/assets/{chunk-MOJQB5TN-CnRPtHb3.js → chunk-MOJQB5TN-K-bFFmpr.js} +1 -1
  28. package/static/assets/{chunk-RYQCIY6F-C--_KRGR.js → chunk-RYQCIY6F-B-b4TyDb.js} +1 -1
  29. package/static/assets/{chunk-V7JOEXUC-BJQ5fwNa.js → chunk-V7JOEXUC-BZRKjyVr.js} +1 -1
  30. package/static/assets/{chunk-VR4S4FIN-BPcVRYqJ.js → chunk-VR4S4FIN-BcvbM_n3.js} +1 -1
  31. package/static/assets/{chunk-XXDRQBXY-BoC3DCKQ.js → chunk-XXDRQBXY-Z2nhcpRg.js} +1 -1
  32. package/static/assets/classDiagram-OUVF2IWQ-DV5beYlE.js +1 -0
  33. package/static/assets/classDiagram-v2-EOCWNBFH-DV5beYlE.js +1 -0
  34. package/static/assets/{cose-bilkent-JH36ORCC-DlKrOw_E.js → cose-bilkent-JH36ORCC-CPBw8Z2X.js} +1 -1
  35. package/static/assets/{cynefin-VYW2F7L2-CZQhaPM1.js → cynefin-VYW2F7L2-DeJ1X-1F.js} +1 -1
  36. package/static/assets/{cynefinDiagram-TSTJHNR4-cZP74_0I.js → cynefinDiagram-TSTJHNR4-BPs3jIZR.js} +1 -1
  37. package/static/assets/{dagre-VKFMJZFB-tB2cBd_e.js → dagre-VKFMJZFB-Bn5Xp63O.js} +1 -1
  38. package/static/assets/{diagram-FQU43EPY-QwoADT9c.js → diagram-FQU43EPY-DWIlVMUR.js} +1 -1
  39. package/static/assets/{diagram-G47NLZAW-Bjz2rwUz.js → diagram-G47NLZAW-BWxpunVI.js} +1 -1
  40. package/static/assets/{diagram-NH7WQ7WH-DS9j6K7F.js → diagram-NH7WQ7WH-CpoAYUis.js} +1 -1
  41. package/static/assets/{diagram-OA4YK3LP-CUPwlGEi.js → diagram-OA4YK3LP-Dv1XfQGK.js} +1 -1
  42. package/static/assets/{diagram-WEI45ONY-iejOZOdV.js → diagram-WEI45ONY-DSk6wZtO.js} +1 -1
  43. package/static/assets/{ebnfDiagram-CCIWWBDH-Bg3puNXE.js → ebnfDiagram-CCIWWBDH-DIDhI2dD.js} +1 -1
  44. package/static/assets/{erDiagram-Q63AITRT-DTxdGEtK.js → erDiagram-Q63AITRT-CGO6ep6G.js} +1 -1
  45. package/static/assets/{flowDiagram-23GEKE2U-CRl-AJlj.js → flowDiagram-23GEKE2U-D8nzLjfG.js} +1 -1
  46. package/static/assets/{ganttDiagram-NO4QXBWP-wCOJ8cfC.js → ganttDiagram-NO4QXBWP-Usz8f26d.js} +1 -1
  47. package/static/assets/{gitGraphDiagram-IHSO6WYX-CnVtKot-.js → gitGraphDiagram-IHSO6WYX-WEJUXa7P.js} +1 -1
  48. package/static/assets/{index-xLqMMC0F.css → index-CM4GfOLV.css} +1 -1
  49. package/static/assets/{index-DAL1vVaa.js → index-j3pCmOym.js} +194 -194
  50. package/static/assets/{infoDiagram-FWYZ7A6U-DmvEl4fi.js → infoDiagram-FWYZ7A6U-BRPwqRvz.js} +1 -1
  51. package/static/assets/{ishikawaDiagram-FXEZZL3T-CjKerAXn.js → ishikawaDiagram-FXEZZL3T-CrntEiqz.js} +1 -1
  52. package/static/assets/{journeyDiagram-5HDEW3XC-Bmc4ARKl.js → journeyDiagram-5HDEW3XC-BmhRsz4F.js} +1 -1
  53. package/static/assets/{kanban-definition-HUTT4EX6-BZ9I3imN.js → kanban-definition-HUTT4EX6-CWxUXdc3.js} +1 -1
  54. package/static/assets/{linear-CrHKLpp_.js → linear-BGjzqzT6.js} +1 -1
  55. package/static/assets/{mindmap-definition-LN4V7U3C-SUk59XXF.js → mindmap-definition-LN4V7U3C-CoVNmO4b.js} +1 -1
  56. package/static/assets/{pegDiagram-2B236MQR-CknFYdh_.js → pegDiagram-2B236MQR-hBHOzL7x.js} +1 -1
  57. package/static/assets/{pieDiagram-ENE6RG2P-B3VlLXXT.js → pieDiagram-ENE6RG2P-Cpv7VZPG.js} +1 -1
  58. package/static/assets/{quadrantDiagram-ABIIQ3AL-BUkZjvW_.js → quadrantDiagram-ABIIQ3AL-BIQAB21D.js} +1 -1
  59. package/static/assets/{railroadDiagram-RFXS5EU6-LklmPimD.js → railroadDiagram-RFXS5EU6-DX6hST3S.js} +1 -1
  60. package/static/assets/{requirementDiagram-TGXJPOKE-DnRFaZbz.js → requirementDiagram-TGXJPOKE-Gas2cE_l.js} +1 -1
  61. package/static/assets/{sankeyDiagram-HTMAVEWB-D242DUlQ.js → sankeyDiagram-HTMAVEWB-BpwoyJDe.js} +1 -1
  62. package/static/assets/{sequenceDiagram-DBY2YBRQ-DmiiStqo.js → sequenceDiagram-DBY2YBRQ-CzBxna5k.js} +1 -1
  63. package/static/assets/{sizeCapture-X5ZJPWSS-cbMvR047.js → sizeCapture-X5ZJPWSS-Cn-5NsLr.js} +1 -1
  64. package/static/assets/{stateDiagram-2N3HPSRC-YIIylI9N.js → stateDiagram-2N3HPSRC-BiW03iCW.js} +1 -1
  65. package/static/assets/stateDiagram-v2-6OUMAXLB-CmQ_Kjkj.js +1 -0
  66. package/static/assets/{swimlanes-5IMT3BWC-Ba309Ysu.js → swimlanes-5IMT3BWC-3jPuufWt.js} +2 -2
  67. package/static/assets/swimlanesDiagram-G3AALYLV-OaMW2HRF.js +8 -0
  68. package/static/assets/{timeline-definition-FHXFAJF6-BdpW3kGY.js → timeline-definition-FHXFAJF6-CzThWt1O.js} +1 -1
  69. package/static/assets/{vennDiagram-L72KCM5P-BiSgQ9Lf.js → vennDiagram-L72KCM5P-D1Axj0CM.js} +1 -1
  70. package/static/assets/{wardleyDiagram-EHGQE667-Clr8YWGW.js → wardleyDiagram-EHGQE667-mKj7UT6Q.js} +1 -1
  71. package/static/assets/{xychartDiagram-FW5EYKEG-LsC066MO.js → xychartDiagram-FW5EYKEG-CSAkvAer.js} +1 -1
  72. package/static/index.html +2 -2
  73. package/static/assets/channel-C_J_aLZ7.js +0 -1
  74. package/static/assets/classDiagram-OUVF2IWQ-yUfBrCjx.js +0 -1
  75. package/static/assets/classDiagram-v2-EOCWNBFH-yUfBrCjx.js +0 -1
  76. package/static/assets/stateDiagram-v2-6OUMAXLB-m0MSGh0v.js +0 -1
  77. package/static/assets/swimlanesDiagram-G3AALYLV-DY_J_ih_.js +0 -8
@@ -1,1067 +1,1073 @@
1
- ---
2
- name: mockgen-shadcn
3
- model: claude-opus-4-8
4
- effort: high
5
- description: >
6
- Generate React + shadcn/ui mockup screens from PRD.md files for UI/UX human designer review.
7
- Creates a Vite + React 19 + TypeScript + shadcn/ui mockup application with admin dashboard layout
8
- (collapsible sidebar navigation, header with logo/notifications/locale/user menu, footer
9
- with copyright/version) using React Router v7 for client-side navigation, organized by user role
10
- in a mockup/ folder. The app is BUILT (npm run build) and its dist/ output is served by the
11
- SINGLE shared Mockup Hub at <root>/mockup — a zero-dependency Node.js server with a landing
12
- page listing every application and role (unclickable when not ready) and a configurable port
13
- (PORT env / mockup.config.json). The Vite dev server remains available for design iteration only.
14
- Input: application name (mandatory), version (mandatory), module (optional).
15
- Output: mockup/ folder in the application's context folder
16
- containing MOCKUP.html index page, mockup-manifest.json, Vite + React project files, layout
17
- components, shadcn/ui components, role-specific page components, and the built dist/ folder;
18
- plus the shared hub at <root>/mockup if not already present.
19
- Trigger on keywords: "generate mockup shadcn", "generate shadcn mockup",
20
- "create shadcn mockup screens", "shadcn UI mockup", "React mockup from user stories",
21
- "mockup from PRD.md shadcn", "generate shadcn screens", "create shadcn UI screens".
22
- Accepts application name and version as input
23
- (e.g., `/mockgen-shadcn hub_middleware v1.0.3`).
24
- Optionally accepts a module name to limit generation to screens for that module only
25
- (e.g., `/mockgen-shadcn hub_middleware v1.0.3 module:Location Information`).
26
- When module is specified, only page components for that module are generated/updated;
27
- layout components, sidebars, config files, and other module pages are left untouched
28
- (the manifest is updated and the app is rebuilt).
29
- Automatically excludes strikethrough (deprecated/removed) items.
30
- ---
31
-
32
- # Mockgen shadcn/ui
33
-
34
- Generate a Vite + React 19 + TypeScript + shadcn/ui mockup application from PRD.md for UI/UX
35
- designer review. Layout uses React components (header, sidebar, footer) composed in a shared
36
- layout route. Pages are React Router routes rendered inside the layout. All navigation is
37
- client-side via React Router `<Link>` and `useNavigate`.
38
-
39
- The mockup is generated with `base`/`basename` set to `/{app_slug}/`, **built** with
40
- `npm run build`, and served from its `dist/` folder by the **shared Mockup Hub** — a single
41
- zero-dependency Node.js server at `<root>/mockup/` that serves ALL applications' mockups
42
- (see [references/mockup-hub-template.md](references/mockup-hub-template.md)). The hub renders
43
- a landing page listing every application and role (roles are unclickable until the app is
44
- generated AND built) and listens on a configurable port (`PORT` env var →
45
- `mockup.config.json` → 3000). The Vite dev server (`npm run dev`) remains available for
46
- design iteration only.
47
-
48
- ## Stack
49
-
50
- | Layer | Technology |
51
- |-------|------------|
52
- | Serving | Shared Mockup Hub — `<root>/mockup/server.js` serves the built `dist/` (SPA fallback) |
53
- | Build tool | Vite 6 |
54
- | UI framework | React 19 + TypeScript 5 |
55
- | Component library | shadcn/ui (Radix UI + Tailwind CSS) |
56
- | Routing / navigation | React Router v7 |
57
- | Styling | Tailwind CSS v3 (PostCSS) |
58
- | Icons | Lucide React |
59
- | Dark mode | next-themes |
60
-
61
- ## Input
62
-
63
- This skill uses standardized input resolution. Provide:
64
-
65
- | Argument | Required | Example | Description |
66
- |----------|----------|---------|-------------|
67
- | `<application>` | Yes | `hub_middleware` | Application name to locate the context folder |
68
- | `<version>` | Yes | `v1.0.3` | Version to scope processing (filter user stories <= this version) |
69
- | `module:<name>` | No | `module:Location Information` | Limit generation to a single module |
70
-
71
- ### Application Folder Resolution
72
-
73
- The application name is matched against root-level application folders:
74
- 1. Strip any leading `<number>_` prefix from folder names (e.g., `1_hub_middleware` → `hub_middleware`)
75
- 2. Match case-insensitively against the provided application name
76
- 3. Accept snake_case, kebab-case, or title-case input (all match the same folder)
77
- 4. If no match found, list available applications and stop
78
-
79
- ### Auto-Resolved Paths
80
-
81
- | File | Resolved Path |
82
- |------|---------------|
83
- | PRD.md | `<app_folder>/context/PRD.md` |
84
- | Module Models | `<app_folder>/context/model/` |
85
- | Output (mockup) | `<app_folder>/context/mockup/` |
86
- | Mockup Hub (shared) | `<root>/mockup/` |
87
-
88
- **App slug** (used as the URL base path): the application folder name with the leading
89
- `<number>_` prefix stripped (e.g., `1_hub_middleware` → `hub_middleware`). Record it during
90
- input resolution — it is baked into `vite.config.ts` (`base`), `main.tsx`
91
- (`BrowserRouter basename`), and all MOCKUP.html links.
92
-
93
- ### Example Invocations
94
-
95
- - `/mockgen-shadcn hub_middleware v1.0.3` (all modules, up to v1.0.3)
96
- - `/mockgen-shadcn hub_middleware v1.0.3 module:Location Information` (one module, specific version)
97
- - `/mockgen-shadcn "Hub Middleware" v1.0.3 module:Employer` (title-case app name)
98
-
99
- ### Version and Module Filtering
100
-
101
- - Only include user stories, NFRs, constraints,
102
- and references from sections whose version tag is **less than or equal to** the target version
103
- - If a module is provided (e.g., `module:Location Information`), only generate/update pages
104
- for that specific module. All other modules are skipped. Common pages (home, profile,
105
- account, notifications), layout components (header, footer, sidebars), and config files are
106
- NOT regenerated when a module filter is active — only the module's own page components
107
- are written (and MOCKUP.html is updated for only that module's cards).
108
- - If no module is provided, process all modules (default behavior)
109
-
110
- **Argument parsing**: The `module:` prefix is the canonical form. Also accept:
111
- - `module:"Location Information"` (quoted, with space)
112
- - `module:location_information` (snake_case — convert to title-case for matching)
113
- - Natural language: `for Location Information module`, `only Location Information`
114
-
115
- ## Version Gate
116
-
117
- Before starting any work, resolve the application folder first (see Input Resolution below), then check `CHANGELOG.md` in the application folder (`<app_folder>/CHANGELOG.md`):
118
-
119
- 1. If `<app_folder>/CHANGELOG.md` does not exist, skip this check (first-ever execution for this application).
120
- 2. If `<app_folder>/CHANGELOG.md` exists, scan all `## vX.Y.Z` headings and determine the **highest version** using semantic versioning comparison.
121
- 3. Compare the requested version against the highest version:
122
- - If requested version **>=** highest version: proceed normally.
123
- - If requested version **<** highest version: **STOP immediately**. Print: `"Version {requested} is lower than the current application version {highest} recorded in <app_folder>/CHANGELOG.md. Execution rejected."` Do NOT proceed with any work.
124
-
125
- ## Workflow
126
-
127
- ### Step 1: Parse PRD.md
128
-
129
- Read the auto-resolved PRD.md file and extract:
130
-
131
- 1. **Application name**: Derive from the parent folder name containing PRD.md.
132
- Strip leading number and underscore prefix, then title-case.
133
- Example: `1_hub_middleware` -> "Hub Middleware"
134
-
135
- 2. **Application initials**: First letter of each word, uppercase.
136
- Example: `1_hub_middleware` -> "HM"
137
-
138
- 3. **Modules**: Each `## Module Name` section under a `# Module Category` heading.
139
- Record the module name and its description (the line after the heading).
140
-
141
- 4. **User stories per module**: Lines matching `- [USxx#####] As a {Role} user, I want to...`
142
- Extract: tag, role, action summary.
143
-
144
- 5. **Unique roles**: Collect all distinct roles from user stories.
145
- Example: "Hub Administrator", "Hub Operation Support"
146
-
147
- 6. **Target version** (from input argument): If a version was provided, record it for
148
- filtering in the next sub-step.
149
-
150
- #### 1a: Version Filtering and Strikethrough Exclusion (MANDATORY)
151
-
152
- PRD.md is a version-controlled document. Each section (User Story, Non Functional
153
- Requirement, Constraint, Reference) has a version tag in square brackets, e.g., `[v1.0.1]`.
154
- Items may also be marked with strikethrough (`~~`) to indicate they are deprecated/removed.
155
-
156
- **Strikethrough exclusion** (always applied, regardless of version parameter):
157
- - Any line wrapped in `~~strikethrough~~` markup MUST be excluded from processing
158
- - This includes user stories, NFRs, constraints, and references
159
- - Example: `~~[USHM00006] As a Hub Administrator user, I want to...~~` → **SKIP**
160
- - Partially strikethrough lines (where only part is struck) should still be excluded
161
- if the tag identifier is within the strikethrough
162
-
163
- **Version filtering** (applied only when a target version is provided):
164
- - Each section under a module has one or more version tags like `[v1.0.0]` or `[v1.0.1]`
165
- - Items listed under a version tag belong to that version
166
- - When a target version is specified (e.g., `v1.0.1`):
167
- - **Include** items from sections whose version tag is **<= target version**
168
- - **Exclude** items from sections whose version tag is **> target version**
169
- - Version comparison uses semantic versioning: compare major, then minor, then patch
170
- - When no target version is specified, include all items from all versions (but still
171
- exclude strikethrough items)
172
-
173
- **Version tracking per section**: Record which version tag each item belongs to, as this
174
- will be used for traceability in the generated pages.
175
-
176
- Example parsing of a section with multiple versions:
177
- ```markdown
178
- ### User Story
179
- [v1.0.0]
180
- - ~~[USHM00006] As a Hub Administrator user, I want to manage...~~
181
- - [USHM00009] As a Hub Administrator user, I want to map...
182
- [v1.0.1]
183
- - [USHM00012] As a Hub Administrator user, I want to manage the list...
184
- ```
185
-
186
- With target version `v1.0.0`:
187
- - USHM00006 → EXCLUDED (strikethrough)
188
- - USHM00009 → INCLUDED (v1.0.0 <= v1.0.0, not strikethrough)
189
- - USHM00012 → EXCLUDED (v1.0.1 > v1.0.0)
190
-
191
- With target version `v1.0.1` (or no version specified):
192
- - USHM00006 → EXCLUDED (strikethrough)
193
- - USHM00009 → INCLUDED
194
- - USHM00012 → INCLUDED
195
-
196
- #### 1c: Module Filtering (applied only when a module argument is provided)
197
-
198
- When a `module` argument is present, apply module filtering after version filtering:
199
-
200
- 1. **Match the specified module** against the list of parsed modules (case-insensitive, ignoring
201
- leading/trailing whitespace). Also accept snake_case input by converting it to title-case
202
- for comparison (e.g., `location_information` → match "Location Information").
203
- 2. **Record the matched module name** for use in Step 3 and beyond.
204
- 3. If no module matches, stop and report the available module names to the user before proceeding.
205
- 4. **Module filter scope**: the filter only affects **page component generation** (Step 6e).
206
- All other steps complete normally (parsing, design system, planning) but output is restricted
207
- to the filtered module's pages.
208
-
209
- **Module-filtered generation mode** differs from full generation in these ways:
210
-
211
- | Aspect | Full Generation | Module-Filtered |
212
- |--------|----------------|-----------------|
213
- | Common pages (home, profile, account, notifications) | Generate for every role | **SKIP** — already exist |
214
- | Layout components (header, footer, sidebar) | Generate | **SKIP** — already exist |
215
- | Config files (package.json, vite.config.ts, etc.) | Generate | **SKIP** — already exist |
216
- | shadcn/ui component files | Generate | **SKIP** — already exist |
217
- | Route config (App.tsx) | Generate | **Update** — add routes for new module pages |
218
- | Module page components (target module) | Generate | **Generate / overwrite** |
219
- | Module page components (other modules) | Generate | **SKIP** — leave untouched |
220
- | MOCKUP.html | Generate full file | **Update only the target module's cards** |
221
- | Footer version string | Update | **Update** (version may have changed) |
222
- | mockup-manifest.json | Generate | **Update** (version, generatedAt, screen counts) |
223
- | Mockup Hub (`<root>/mockup/`) | Ensure (create/upgrade) | **Ensure** (create/upgrade) |
224
- | `npm run build` (dist/ for hub serving) | Run | **Run** (rebuild required after page changes) |
225
-
226
- **MOCKUP.html partial update** (module-filtered mode):
227
- - Read the existing MOCKUP.html
228
- - Locate the screen cards section for the target module (search by module name heading or
229
- existing card tags)
230
- - Replace only those cards with freshly generated ones reflecting the new pages
231
- - Update the total screen count per role (add net new pages)
232
- - Update the version badge if it changed
233
- - Update the "N new screens added in vX.Y.Z" banner text
234
- - Leave all other role sections and cards unchanged
235
-
236
- ### Step 1b: Discover and Load Module Models
237
-
238
- After parsing PRD.md, look for module models at the auto-resolved model path:
239
- `<app_folder>/context/model/`
240
-
241
- For each module extracted in Step 1:
242
-
243
- 1. Convert the module name to **kebab-case** to derive the model folder name:
244
- - Lowercase the module name and replace spaces with hyphens
245
- - Examples: "Location Information" → `location-information`, "Industrial Classification" → `industrial-classification`, "Employer" → `employer`
246
-
247
- 2. Check for `{model_dir}/{kebab-module}/model.md`
248
-
249
- 3. If the file exists, parse it and extract the following sections:
250
-
251
- - **Section 2 – Collection Catalog**: collection names and types (Root Collection, Audit Collection, etc.)
252
- - **Section 5 – Field Detail per Collection**: for each collection — field name, type, required, nullable, constraints/notes
253
- - **Section 6 – Embedded Document Definitions**: embedded type name and its sub-fields
254
- - **Section 7 – Enum Definitions**: enum name and all allowed values with descriptions
255
- - **Section 9 – Index Recommendations**: indexed fields (used to identify search/filter parameters)
256
-
257
- 4. Store this as the **module model** for the module, keyed by module name
258
-
259
- **Field classification** (used during page generation in Step 6e):
260
-
261
- | Category | Definition | Usage |
262
- |----------|-----------|-------|
263
- | System fields | `_id`, `_audit`, `_version`, `deleted`, `deletedAt`, `deletedBy` | Exclude from user-facing forms |
264
- | Audit-only fields | Fields whose Source is `CONVENTION` and type is `Audit` | Show in detail views only |
265
- | Required form fields | `Required: Yes` AND not a system field | Mandatory inputs in create/edit forms |
266
- | Optional form fields | `Required: No` AND not a system field | Optional inputs in create/edit forms |
267
- | Read-only after creation | Fields marked as unique identity keys (e.g., `companyRegistrationNumber`) | Show in edit forms as readonly |
268
- | Search/filter fields | Fields referenced in Index Recommendations | Render as filter controls in list pages |
269
- | Enum fields | Type matches an entry in Section 7 Enum Definitions | Render as `<Select>` dropdowns |
270
- | Embedded object fields | Type is a custom embedded document type (not a primitive) | Render as grouped `<Card>` sections |
271
- | Embedded array fields | Type ends in `[]` (e.g., `PersonInCharge[]`) | Render as repeatable row with Add/Remove |
272
-
273
- **Fallback**: If no `model.md` exists for a module, infer fields from user story text (original behavior).
274
-
275
- ---
276
-
277
- ### Step 2: Load Design System
278
-
279
- Load the design system using a two-tier resolution strategy:
280
-
281
- #### 2a: PRD.md Design System Reference (Primary Source)
282
-
283
- Check if PRD.md contains a `# Design System` section. If it does:
284
- 1. Extract the referenced file path (e.g., from `[DESIGN_SYSTEM.md](reference/DESIGN_SYSTEM.md)`)
285
- 2. Resolve the path relative to PRD.md's location
286
- 3. If the referenced file exists, read it and extract:
287
- - Color palettes (primary, secondary, accent, neutral — hex values)
288
- - Typography (font families, font sizes, weight scale)
289
- - Spacing scale (if overriding Tailwind defaults)
290
- - Component patterns (button styles, card styles, form input styles, table styles, badge/chip styles, modal patterns)
291
- - Layout grid rules
292
- 4. Apply extracted tokens to the Tailwind config (`tailwind.config.js`) custom colors/fonts,
293
- shadcn/ui CSS variables in `src/index.css`, and all generated components
294
-
295
- #### 2b: Context Design Folder (Fallback)
296
-
297
- If PRD.md does not have a `# Design System` section, or the referenced file does not exist, fall back to the application's `<app_folder>/context/design/` folder. This folder contains pre-defined design tokens and Tailwind component guidelines maintained externally by the UI/UX team.
298
-
299
- Read all files in `{app_name}/context/design/` (where `{app_name}` is the resolved application folder name from Step 1). Apply the design tokens and guidelines found there to all generated mockup pages.
300
-
301
- **Expected files** (any or all may be present):
302
- - `design-system.md` — Colors, typography, spacing, and visual style definitions
303
- - `components.md` — Reusable component patterns and Tailwind class conventions
304
- - `guidelines.md` — Layout rules, accessibility standards, and stack-specific guidelines
305
-
306
- #### 2c: Default Fallback
307
-
308
- If neither the PRD reference nor the `{app_name}/context/design/` folder provides design tokens, use the default shadcn/ui "New York" style: zinc/neutral color palette, Inter/Geist font stack, and default shadcn/ui component styling with CSS variables.
309
-
310
- #### 2d: Process Flow Status States
311
-
312
- If PRD.md contains a `# High Level Process Flow` section, scan it for entity status lifecycle descriptions (e.g., "Received → Validated → Enriched → Active"). For each status lifecycle found:
313
- - Ensure list pages for the corresponding module include a status column with colored `<Badge>` variants for each state
314
- - Use design system color tokens for badge variants (e.g., `default` for active/completed, `secondary` for pending, `destructive` for failed/rejected)
315
-
316
- ### Step 3: Plan Screen Files
317
-
318
- For each role, determine ALL pages to generate. **Every clickable link, tab, or action
319
- in any generated page MUST have a corresponding page component. No link may be a dead end.**
320
-
321
- **Module filter applied here**: If a module argument was provided (Step 1c), plan only the
322
- pages for that module across all roles. Skip common pages (home, profile, account,
323
- notifications) and skip all other modules entirely. The screen plan table should list only
324
- the filtered module's pages.
325
-
326
- #### 3a: Core Pages (React components)
327
-
328
- 1. **home.tsx**: Default home/dashboard page with welcome message and summary widgets
329
- 2. **profile.tsx**: User profile page (linked from header user dropdown)
330
- 3. **account.tsx**: Account settings page (linked from header user dropdown)
331
- 4. **notifications.tsx**: Notifications page (linked from header notification bell)
332
- 5. **One page per module that has user stories for this role**
333
-
334
- #### 3b: Sub-Pages (Detail / Edit / Create)
335
-
336
- For each module page, analyze the user stories and identify sub-pages needed:
337
-
338
- | User Story Pattern | Sub-Page Required |
339
- |-------------------|-------------------|
340
- | "view details of X" | `{module}-detail.tsx` - Detail view for a single record |
341
- | "add/create/register X" | `{module}-create.tsx` - Create/add form |
342
- | "edit/update/modify X" | `{module}-edit.tsx` - Edit form (pre-filled) |
343
- | "view history/audit of X" | `{module}-history.tsx` - History/audit log view |
344
- | "view associated X of Y" | `{module}-{sub}-list.tsx` - Associated records list |
345
-
346
- #### 3f: Report Layout Pages (conditional — if PRD.md contains report-related content)
347
-
348
- Scan PRD.md for report-related content:
349
- - NFRs mentioning "report", "Report interface", "generate report", "report generation"
350
- - User stories describing generating/downloading PDF, Excel, or CSV reports
351
- - A "Report" module or report-related NFRs defining specific report types
352
-
353
- **If report requirements are found**, generate HTML report layout mockups for each
354
- identified report. These layouts serve as draft previews for human designers/stakeholders
355
- to verify the report structure before the AI coding agent implements the actual report
356
- generation code.
357
-
358
- For each identified report, create a standalone HTML file in a `public/reports/` subfolder:
359
-
360
- | Report Source | File Generated |
361
- |--------------|----------------|
362
- | NFR describes "Staff Allocation Summary report" | `public/reports/staff_allocation_summary.html` |
363
- | User story: "generate Job Demand report by country" | `public/reports/job_demand_by_country.html` |
364
- | Report module NFR: "Monthly Activity Report" | `public/reports/monthly_activity_report.html` |
365
-
366
- **Report layout file conventions:**
367
- - Each report layout is a **standalone self-contained HTML document** (not a React component)
368
- with its own `<html>`, `<head>`, `<body>` tags and Tailwind CDN `<script>` in the head
369
- - Layout simulates a **print-ready A4 page** with appropriate margins and sizing:
370
- ```html
371
- <body class="bg-gray-100">
372
- <div class="mx-auto bg-white shadow" style="width: 210mm; min-height: 297mm; padding: 15mm;">
373
- <!-- Report content -->
374
- </div>
375
- </body>
376
- ```
377
- - **Report header**: Report title (centered, bold), generation date, filter parameters used
378
- - **Report body**: Data table or summary layout using actual fields from the module model
379
- (if `model/{module}/model.md` exists, use its field definitions for column headers)
380
- - **Report footer**: Page indicator text ("Page 1 of 1"), generation timestamp
381
- - Use **sample data rows** (5-10 rows) with realistic placeholder values matching model constraints
382
- - Apply the design system colors from Step 2 for header background, borders, and accents
383
- - For landscape reports (wide tables with many columns), use `style="width: 297mm; min-height: 210mm;"`
384
-
385
- **Report parameter section**: Above the report data, include a gray-shaded "Parameters" box
386
- showing the filter criteria used to generate the report (e.g., Date Range: 2025-01-01 to
387
- 2025-12-31, Department: All, Status: Active).
388
-
389
- **Add to MOCKUP.html**: Include a "Reports" section at the bottom of each role's screen cards
390
- (after all module cards) listing the report layout links. Report links open in new tabs
391
- pointing to the hub's static route `/{app_slug}/reports/{report_file}.html`. Also list the
392
- report file names in the manifest's `reports` array.
393
-
394
- **Add to sidebar**: If reports are present, add a "Reports" navigation group in each role's
395
- sidebar with links opening report layouts in new tabs.
396
-
397
- #### 3c: Tabbed Pages
398
-
399
- If a module page contains tabs (e.g., a detail page with Overview, Documents, History tabs),
400
- use shadcn/ui `<Tabs>` component **within the same page component**. Only create separate
401
- page component files for tabs if the tab content is substantial (more than ~100 lines).
402
- Use the naming convention for separate files: `{module}-tab-{tab_name}.tsx`
403
-
404
- Example: `employer-tab-overview.tsx`, `employer-tab-documents.tsx`, `employer-tab-history.tsx`
405
-
406
- #### 3d: Page File Naming Convention
407
-
408
- Convert names to kebab-case for file names, PascalCase for component names.
409
- Example: "Location Information" → file: `location-information.tsx`, component: `LocationInformation`
410
-
411
- #### 3e: Build Screen Plan
412
-
413
- Build a **complete** screen plan. Every entry must map to a generated file:
414
-
415
- | Role | Folder Name | Page File | Source | Description |
416
- |------|-------------|-----------|--------|-------------|
417
- | Hub Administrator | hub-administrator | home.tsx | Common | Dashboard home |
418
- | Hub Administrator | hub-administrator | profile.tsx | Common | User profile |
419
- | Hub Administrator | hub-administrator | account.tsx | Common | Account settings |
420
- | Hub Administrator | hub-administrator | notifications.tsx | Common | Notifications list |
421
- | Hub Administrator | hub-administrator | location-information.tsx | Module | USHM00006, USHM00009 |
422
- | Hub Administrator | hub-administrator | location-information-detail.tsx | Sub-page | View location details |
423
- | Hub Administrator | hub-administrator | location-information-create.tsx | Sub-page | Add new location |
424
- | Hub Operation Support | hub-operation-support | home.tsx | Common | Dashboard home |
425
- | Hub Operation Support | hub-operation-support | profile.tsx | Common | User profile |
426
- | Hub Operation Support | hub-operation-support | account.tsx | Common | Account settings |
427
- | Hub Operation Support | hub-operation-support | notifications.tsx | Common | Notifications list |
428
- | Hub Operation Support | hub-operation-support | employer.tsx | Module | USHM00021-USHM00033 |
429
- | Hub Operation Support | hub-operation-support | employer-detail.tsx | Sub-page | View employer details |
430
- | Hub Operation Support | hub-operation-support | employer-create.tsx | Sub-page | Register new employer |
431
-
432
- ### Step 4: Create Output Folder Structure
433
-
434
- **Module filter**: When a module argument is active, skip this step entirely — the folder
435
- structure already exists from a previous full generation. Only page components for the target
436
- module will be written in Step 6e.
437
-
438
- Create the mockup folder at the auto-resolved mockup output path (full generation only):
439
-
440
- ```
441
- <app_folder>/context/
442
- mockup/
443
- .gitignore
444
- package.json
445
- vite.config.ts
446
- tsconfig.json
447
- tsconfig.app.json
448
- tsconfig.node.json
449
- tailwind.config.js
450
- postcss.config.js
451
- components.json # shadcn/ui configuration
452
- index.html # Vite entry HTML
453
- MOCKUP.html # Per-app screen index (served by hub at /{app_slug})
454
- mockup-manifest.json # Hub discovery manifest (app, stack, roles, version)
455
- dist/ # Built output served by the hub (npm run build; gitignored)
456
- public/
457
- reports/ # Report layout files (if applicable)
458
- src/
459
- main.tsx # React entry point
460
- App.tsx # Router configuration
461
- index.css # Tailwind directives + shadcn/ui CSS variables
462
- lib/
463
- utils.ts # cn() utility
464
- components/
465
- ui/ # shadcn/ui components
466
- button.tsx
467
- card.tsx
468
- table.tsx
469
- badge.tsx
470
- input.tsx
471
- label.tsx
472
- select.tsx
473
- dialog.tsx
474
- dropdown-menu.tsx
475
- avatar.tsx
476
- separator.tsx
477
- tabs.tsx
478
- switch.tsx
479
- tooltip.tsx
480
- breadcrumb.tsx
481
- pagination.tsx
482
- sheet.tsx
483
- layout/
484
- app-layout.tsx # Shared layout with sidebar + header + footer
485
- app-header.tsx # Top header component
486
- app-sidebar.tsx # Sidebar nav component (role-aware)
487
- app-footer.tsx # Footer component
488
- sidebar-config.ts # Sidebar menu items per role
489
- pages/
490
- {role-kebab-case}/
491
- home.tsx
492
- profile.tsx
493
- account.tsx
494
- notifications.tsx
495
- {module-kebab-case}.tsx
496
- {module-kebab-case}-detail.tsx
497
- {module-kebab-case}-create.tsx
498
- {module-kebab-case}-edit.tsx
499
- ...
500
- ```
501
-
502
- ### Step 4b: Generate Project Config Files
503
-
504
- **Module filter**: When a module argument is active, skip this step entirely.
505
-
506
- Generate all config and entry files using the templates from
507
- [references/admin-layout-template.md](references/admin-layout-template.md).
508
-
509
- #### .gitignore
510
-
511
- ```
512
- node_modules/
513
- dist/
514
- .DS_Store
515
- *.log
516
- *.local
517
- ```
518
-
519
- Key project setup:
520
- - `package.json` — Vite + React 19 + TypeScript + Tailwind CSS + shadcn/ui dependencies
521
- - `vite.config.ts` — Vite config with React plugin, path aliases, and
522
- `base: "/{app_slug}/"` (REQUIRED so the built app is servable by the hub at `/{app_slug}`)
523
- - `tsconfig.json` / `tsconfig.app.json` / `tsconfig.node.json` — TypeScript configs with path aliases
524
- - `tailwind.config.js` — Tailwind config with shadcn/ui integration and design system tokens
525
- - `postcss.config.js` — PostCSS with Tailwind and autoprefixer
526
- - `components.json` — shadcn/ui configuration (New York style, zinc base)
527
- - `index.html` — Vite entry HTML with Google Fonts
528
- - `src/main.tsx` — React root render with `<BrowserRouter basename="/{app_slug}">`
529
- (REQUIRED to match the Vite `base`)
530
- - `src/App.tsx` — React Router configuration with all role/page routes
531
- - `src/index.css` — Tailwind directives + shadcn/ui CSS variables (light and dark)
532
- - `src/lib/utils.ts` — `cn()` utility (clsx + tailwind-merge)
533
-
534
- ### Step 4c: Generate shadcn/ui Component Files
535
-
536
- **Module filter**: When a module argument is active, skip this step entirely.
537
-
538
- Generate the shadcn/ui component files directly into `src/components/ui/`. These follow the
539
- standard shadcn/ui "New York" style patterns. The components are owned by the project — they
540
- are NOT imported from npm.
541
-
542
- **Required components** (generate all of these):
543
-
544
- | Component | File | Primary Usage |
545
- |-----------|------|--------------|
546
- | Button | `button.tsx` | Actions, navigation, form submission |
547
- | Card | `card.tsx` | Content containers, stat cards, detail panels |
548
- | Table | `table.tsx` | Data lists, records, audit logs |
549
- | Badge | `badge.tsx` | Status indicators, tags, enum values |
550
- | Input | `input.tsx` | Text fields, search, filters |
551
- | Label | `label.tsx` | Form field labels |
552
- | Select | `select.tsx` | Dropdowns, enum selectors, page size |
553
- | Dialog | `dialog.tsx` | Delete confirmations, modals |
554
- | DropdownMenu | `dropdown-menu.tsx` | Header user menu, notification dropdown |
555
- | Avatar | `avatar.tsx` | User avatars in header and profile |
556
- | Separator | `separator.tsx` | Visual dividers |
557
- | Tabs | `tabs.tsx` | Detail page sections, notification filters |
558
- | Switch | `switch.tsx` | Boolean toggles, notification preferences |
559
- | Tooltip | `tooltip.tsx` | Field hints, readonly explanations |
560
- | Breadcrumb | `breadcrumb.tsx` | Page navigation trail |
561
- | Pagination | `pagination.tsx` | Table/list pagination |
562
- | Sheet | `sheet.tsx` | Mobile sidebar overlay |
563
-
564
- Each component follows the standard shadcn/ui implementation pattern:
565
- - Uses `@radix-ui/*` primitives for accessibility
566
- - Styled with Tailwind CSS utility classes
567
- - Supports `className` prop via `cn()` utility
568
- - Uses `cva` (class-variance-authority) for variants where applicable
569
- - Forwards refs properly
570
-
571
- ### Step 4d: Write mockup-manifest.json and Ensure the Mockup Hub
572
-
573
- **Always runs** (full AND module-filtered generation; in module-filtered mode UPDATE the
574
- existing manifest version, generatedAt, per-role screen counts).
575
-
576
- 1. Write `<app_folder>/context/mockup/mockup-manifest.json` following the schema in
577
- [references/mockup-hub-template.md](references/mockup-hub-template.md):
578
-
579
- ```json
580
- {
581
- "app": "{app_slug}",
582
- "appName": "{App Name}",
583
- "description": "{short description from PRD.md}",
584
- "stack": "shadcn",
585
- "version": "{target version}",
586
- "generatedAt": "{YYYY-MM-DD}",
587
- "roles": [
588
- { "name": "{Role Name}", "slug": "{role-kebab-case}", "screens": {count} }
589
- ],
590
- "reports": ["{report_file}.html"]
591
- }
592
- ```
593
-
594
- (`reports` only when report layouts were generated.) The hub reads this manifest to
595
- route the app and render its landing-page card; without it the app shows as "Not
596
- generated yet" and its roles are unclickable.
597
-
598
- 2. Ensure the shared hub exists at `<root>/mockup/` per the Ensure-Hub rules in
599
- [references/mockup-hub-template.md](references/mockup-hub-template.md): create
600
- `server.js`, `package.json`, `mockup.config.json`, and `.gitignore` if missing;
601
- upgrade `server.js`/`package.json` only when the existing `HUB_VERSION` is lower;
602
- never overwrite an existing `mockup.config.json` or `.gitignore`. All hub artifacts
603
- (config, logs, any `node_modules/`) live inside `<root>/mockup/` and are gitignored
604
- there.
605
-
606
- ### Step 5: Generate MOCKUP.html Index
607
-
608
- **Module filter**: When a module argument is active, do NOT regenerate the full MOCKUP.html.
609
- Instead, apply a **partial update** as described in Step 1c: update only the target module's
610
- screen cards, the version badge, and the per-role screen count. Leave all other content
611
- unchanged.
612
-
613
- Create the index page using the template in [references/mockup-index-template.md](references/mockup-index-template.md).
614
-
615
- MOCKUP.html is this app's screen index, served by the hub at `/{app_slug}`. It shows:
616
- - Hub startup banner with instructions (`cd <root>/mockup && npm start` — no install
617
- needed; port configurable via `PORT` env var or `mockup.config.json`) and a reminder
618
- that the app must be built (`npm run build`) before screens open
619
- - Application name and description
620
- - **Target version** used for generation
621
- - Number of excluded items for transparency
622
- - For each role: role name, list of screen cards with links
623
- - **ALL screen links use `target="_blank" rel="noopener noreferrer"`** with
624
- **root-relative** URLs `/{app_slug}/{role}/{page}` (never hardcode
625
- `http://localhost:<port>` the hub port is user-configurable) so they open in new
626
- tabs via the running hub (SPA fallback serves `dist/index.html`, React Router resolves
627
- the route)
628
- - A "Open Role Dashboard" quick-launch link per role section
629
-
630
- ### Step 6: Generate Layout Components and Page Components
631
-
632
- Use templates from [references/admin-layout-template.md](references/admin-layout-template.md).
633
-
634
- **Apply the design system** from Step 2 (colors, typography, spacing) to all components via
635
- the CSS variables in `src/index.css` and the Tailwind config.
636
-
637
- **Module filter**: When a module argument is active, skip steps 6a–6d (layout components).
638
- Proceed directly to **6e** for the target module's page components only. Also update the
639
- footer version string in `app-footer.tsx` if the version changed.
640
-
641
- #### 6a: Generate src/components/layout/app-layout.tsx
642
-
643
- Shared layout component using React Router `<Outlet>`. Contains:
644
- - `<AppHeader>` at the top (fixed)
645
- - `<AppSidebar>` on the left (fixed, collapsible)
646
- - `<Outlet>` for page content (scrollable)
647
- - `<AppFooter>` at the bottom
648
- - ThemeProvider wrapping for dark mode support
649
- - Sidebar state management (expanded/collapsed)
650
-
651
- #### 6b: Generate src/components/layout/app-header.tsx
652
-
653
- Header component containing:
654
- - Logo + App Name (left) — `<Link>` to home
655
- - Notification bell with shadcn/ui `<DropdownMenu>` and `<Badge>` count
656
- - Globe/locale selector with shadcn/ui `<DropdownMenu>`
657
- - Dark mode toggle button using next-themes `useTheme()`
658
- - User `<Avatar>` with `<DropdownMenu>` (Profile, Account, Logout)
659
- - All Profile/Account/Notifications links use React Router `<Link>` / `useNavigate()`
660
- - Lucide React icons throughout (Bell, Globe, Moon, Sun, User, LogOut, Settings)
661
-
662
- #### 6c: Generate src/components/layout/app-footer.tsx
663
-
664
- Simple footer with copyright year and version string using `<Separator>` divider.
665
-
666
- #### 6d: Generate src/components/layout/sidebar-config.ts and app-sidebar.tsx
667
-
668
- **sidebar-config.ts**: Export a configuration object mapping each role to its sidebar menu items:
669
- ```typescript
670
- export type SidebarItem = {
671
- title: string;
672
- path: string;
673
- icon: string; // Lucide icon name
674
- };
675
-
676
- export type SidebarConfig = {
677
- [role: string]: {
678
- label: string;
679
- items: SidebarItem[];
680
- reports?: { title: string; href: string }[];
681
- };
682
- };
683
- ```
684
-
685
- **app-sidebar.tsx**: Sidebar component that:
686
- - Reads the current role from React Router `useParams()`
687
- - Renders menu items from sidebar-config.ts for that role
688
- - Highlights the active menu item using `useLocation().pathname`
689
- - Uses React Router `<Link>` for navigation (not HTMX)
690
- - Uses Lucide React icons dynamically based on config
691
- - Supports collapsed state (icons only) via context/state
692
- - Has a collapsible toggle button
693
-
694
- #### 6e: Generate page components (src/pages/{role-kebab-case}/{page}.tsx)
695
-
696
- Each page component is a **standard React functional component** that returns JSX.
697
- Pages use shadcn/ui components for all UI elements.
698
-
699
- **All navigation within page components uses React Router** `<Link>` or `useNavigate()`.
700
-
701
- **Breadcrumbs**: Use shadcn/ui `<Breadcrumb>` component. Home link is a `<Link>`,
702
- module link is a `<Link>`, current page is `<BreadcrumbPage>` (non-interactive).
703
-
704
- #### Admin Layout: Screen Content Generation
705
-
706
- For each module page, analyze the user stories and generate appropriate UI mockup elements:
707
-
708
- | User Story Pattern | UI Element |
709
- |-------------------|------------|
710
- | "search for X based on parameters" | Filter `<Card>` with `<Input>`/`<Select>` + `<Table>` results |
711
- | "view details of X" | Detail `<Card>` with labeled fields in grid layout |
712
- | "manage X" / "configure X" | `<Table>` with Add/Edit/Delete action `<Button>` components |
713
- | "view history/changes" | `<Table>` with timestamps and `<Badge>` change types |
714
- | "map X to Y" | Two-panel mapping interface or matrix `<Table>` |
715
- | "activate/deactivate X" | `<Switch>` toggles in table rows or config panel |
716
- | "view associated X" | Related records `<Table>` or linked `<Card>` sections |
717
-
718
- #### Model-Driven Field Usage (MANDATORY when model file exists)
719
-
720
- When a module model was loaded in Step 1b, use its actual field definitions — not generic placeholders — to populate every page. Generic field names like "Field 1" or "Description" are not acceptable when a model is available.
721
-
722
- **Field type → shadcn/ui component mapping:**
723
-
724
- | Model Type | Form Component | Notes |
725
- |------------|---------------|-------|
726
- | `String` | `<Input type="text">` with `<Label>` | Use `maxLength` if constraints specify length |
727
- | `Number` | `<Input type="number">` with `<Label>` | |
728
- | `Boolean` | `<Switch>` with `<Label>` | |
729
- | `ISODate` | `<Input type="date">` or `<Input type="datetime-local">` | |
730
- | `ObjectId` (reference) | `<Input readOnly>` or lookup widget with `<Tooltip>` | Display as read-only ID reference |
731
- | Enum (Section 7 match) | `<Select>` with all enum values as `<SelectItem>` | Show enum value descriptions as item text |
732
- | Embedded Object | `<Card>` section grouping sub-fields | Title the card with embedded type name |
733
- | Embedded Array (`[]`) | Repeatable `<Card>` section with `<Button>` "+ Add" / "Remove" | Show one pre-filled example row |
734
-
735
- **List / Search pages** (`{module}.tsx`):
736
- - **Filter section**: `<Card>` with filter inputs only for fields in Index Recommendations (Section 9). Use the correct component per the mapping above. Enum-indexed fields use `<Select>`. Date-indexed fields use date range pickers.
737
- - **Results table**: shadcn/ui `<Table>` with 5–7 most identifying non-system fields as columns. For embedded objects, show as a single column (e.g., "Company Name"). Null/optional fields shown with a dash (`—`).
738
- - **Table row actions**: View → `<Link>` to `{module}-detail`, Edit → `<Link>` to `{module}-edit`, Delete → shadcn/ui `<Dialog>` confirm
739
- - **Pagination** (MANDATORY): Every results table MUST include shadcn/ui `<Pagination>` directly below the table. Requirements:
740
- - Default page size: **10 items per page**
741
- - Show "Showing X–Y of Z results" summary text on the left
742
- - Show page size `<Select>` with options 10, 25, 50 on the right (default 10)
743
- - Show Previous / Next and page number buttons using `<Pagination>` component
744
- - Page state managed via React `useState` (`currentPage`, `pageSize`, `totalItems`)
745
- - Previous/Next buttons are disabled when at first/last page
746
- - Use sample data: populate exactly 10 visible rows in the table (matching the default page size)
747
-
748
- **Detail pages** (`{module}-detail.tsx`):
749
- - Show ALL non-system fields, grouped logically:
750
- - Basic fields: flat primitive fields in a 2-column grid `<Card>`
751
- - Embedded objects (e.g., `address`, `contact`): each in its own labeled sub-`<Card>`
752
- - Embedded arrays (e.g., `personsInCharge`): rendered as a sub-`<Table>` with a row per item
753
- - Enum fields: display value wrapped in a `<Badge>` with appropriate variant
754
- - ISODate fields: formatted as `DD MMM YYYY HH:mm` in sample data
755
- - Boolean fields: show as a `<Badge>` ("Active" variant=default / "Inactive" variant=secondary)
756
- - Include Edit `<Button>`, Delete `<Dialog>` confirm, and Back to List `<Button>` actions
757
-
758
- **Create pages** (`{module}-create.tsx`):
759
- - Include ALL `Required: Yes` non-system fields as mandatory inputs (mark with `*` via `<Label>`)
760
- - Include `Required: No` fields as optional inputs where they make sense for initial creation
761
- - Group embedded objects as `<Card>` sections with a title
762
- - For embedded arrays: show one empty repeatable row with a `<Button>` "+ Add"
763
- - Submit `<Button>` and Cancel `<Button>` (Cancel navigates back to `{module}` list via `useNavigate()`)
764
-
765
- **Edit pages** (`{module}-edit.tsx`):
766
- - Same structure as create page but with sample data pre-filled in all inputs
767
- - Fields that serve as unique identity keys (e.g., `companyRegistrationNumber`) must be rendered as `<Input readOnly>` with a `<Tooltip>` explaining they cannot be changed
768
- - Save `<Button>` and Cancel `<Button>`
769
-
770
- **History / Audit pages** (`{module}-history.tsx`):
771
- - Use fields from the **audit/history collection** (the non-root collection in the Collection Catalog):
772
- - `changeType` → `<Badge>` using enum values from Section 7 with variant mapping
773
- - `fieldChanged` → `<code>` styled text
774
- - `previousValue` / `newValue` → inline diff or truncated display
775
- - `changedAt` → formatted timestamp
776
- - `changedBy` → plain text (e.g., "SYSTEM" or username)
777
- - Render as a `<Table>`, newest first
778
- - **Pagination** (MANDATORY): Include `<Pagination>` below the history table. Default 10 items per page.
779
-
780
- **Sample data alignment**: Placeholder values in pages must be consistent with field constraints:
781
- - `countryCode` → use actual allowed values (e.g., "MYS", "BHR", "MDV") per constraints if present
782
- - Enum fields → use one of the defined enum values (not arbitrary strings)
783
- - `companyRegistrationNumber` → e.g., "201901012345 (1234567-X)"
784
- - `ISODate` fields → use realistic ISO dates (e.g., "2025-08-15T10:30:00Z")
785
-
786
- ---
787
-
788
- #### Link Integrity Rules (CRITICAL)
789
-
790
- **Every clickable element MUST navigate to a real route. No dead-end links allowed.**
791
-
792
- 1. **Table row actions** (View, Edit, Delete):
793
- - "View" / "Details" → React Router `<Link to="/{role}/{module}-detail">`
794
- - "Edit" → React Router `<Link to="/{role}/{module}-edit">`
795
- - "Delete" → shadcn/ui `<Dialog>` confirm (no navigation, inline confirm)
796
- - "Add New" / "Create" → React Router `<Link to="/{role}/{module}-create">`
797
-
798
- 2. **Tabs within a page**:
799
- - Use shadcn/ui `<Tabs>` component with `<TabsContent>` for inline tabs
800
- - If tabs are separate page files, each tab header is a `<Link>` to the tab route
801
-
802
- 3. **Header links**:
803
- - Notification bell icon → React Router `<Link>` to `notifications`
804
- - Notification dropdown "View all notifications" → React Router `<Link>` to `notifications`
805
- - Locale dropdown options → no-op handler (static language switcher mockup)
806
- - Dark mode toggle → `useTheme().setTheme()` (no navigation)
807
- - Profile dropdown → React Router `<Link>` to `profile`
808
- - Account dropdown → React Router `<Link>` to `account`
809
- - Logout → plain `<a href="/">` (escapes the SPA to the hub landing page — a React
810
- Router `<Link to="/">` would only reach the app's own root because of the basename)
811
-
812
- 4. **Sidebar links**: React Router `<Link>` to correct module routes
813
-
814
- 5. **Breadcrumb links**: shadcn/ui `<Breadcrumb>`
815
- - Home → `<Link to="/{role}/home">`
816
- - Module → `<Link to="/{role}/{module}">`
817
- - Detail / current → `<BreadcrumbPage>` (non-interactive)
818
-
819
- 6. **Pagination links**: shadcn/ui `<Pagination>` with React `useState` for page state — navigation is in-component state, not route-based
820
-
821
- 7. **Back / Cancel buttons**: React Router `useNavigate()` or `<Link>` to the parent page
822
-
823
- 8. **Images** (inline previews, thumbnails, etc.):
824
- - Must open the full image in a **new tab** via `<a href="..." target="_blank" rel="noopener noreferrer">`
825
- - Use placeholder image URLs like `https://placehold.co/800x600`
826
-
827
- 9. **PDFs and documents** (download/view links):
828
- - Must open in a **new tab** via `<a href="..." target="_blank" rel="noopener noreferrer">`
829
- - Never render PDFs inline within the mockup
830
-
831
- **Content guidelines:**
832
- - Use placeholder/sample data that reflects the module context
833
- - Include appropriate form fields based on NFRs and constraints
834
- - Show the user story tags with their version as JSX comments for traceability
835
- (e.g., `{/* USHM00012 [v1.0.1] */}`)
836
- - All interactive elements use React state and shadcn/ui components
837
- - Use Tailwind utility classes for layout and custom styling
838
- - Use Lucide React icons (`import { IconName } from "lucide-react"`)
839
-
840
- #### Common Pages Content
841
-
842
- **home.tsx**: Dashboard home page showing:
843
- - Welcome message with user role
844
- - Summary stat `<Card>` grid (one per module: total count, recent activity)
845
- - Recent activity `<Table>` with recent actions across modules
846
-
847
- **profile.tsx**: User profile page showing:
848
- - User `<Avatar>`, full name, email, role `<Badge>`
849
- - Personal information `<Card>` (read-only display): Name, Email, Phone, Department
850
- - "Edit Profile" `<Button>` (navigates to self since it's a mockup)
851
-
852
- **account.tsx**: Account settings page showing:
853
- - Change Password `<Card>` (current password, new password, confirm password `<Input>` fields)
854
- - Notification Preferences `<Card>` (`<Switch>` toggles for email/SMS)
855
- - Language/Locale `<Select>`
856
- - Session Management `<Card>` (active sessions `<Table>`)
857
-
858
- **notifications.tsx**: Notifications list page showing:
859
- - shadcn/ui `<Tabs>`: All, Unread, Read
860
- - List of notification `<Card>` items with: Lucide icon, title, message preview, timestamp, read/unread dot
861
- - Mark all as read `<Button>`
862
- - **Pagination** (MANDATORY): `<Pagination>` below the notification list, default 10 items per page.
863
-
864
- #### Sub-Page Content
865
-
866
- **{module}-detail.tsx**: Record detail page showing:
867
- - Page title with record identifier
868
- - Back `<Button>` (React Router `<Link>` to `{module}`)
869
- - Detail `<Card>` panels with all relevant fields from user stories
870
- - Action buttons: Edit `<Button>` (`<Link>` to `{module}-edit`), Delete `<Dialog>`, Back to List
871
- - Related data sections if applicable
872
- - If the entity has sub-entities, show them in shadcn/ui `<Tabs>` or sectioned `<Card>` groups
873
-
874
- **{module}-create.tsx**: Create/add form page showing:
875
- - Page title: "Add New {Entity}"
876
- - `<Breadcrumb>`: Home > {Module} > Add New
877
- - Form `<Card>` with all required fields derived from user stories
878
- - Submit and Cancel `<Button>` (Cancel: `<Link>` to `{module}`)
879
-
880
- **{module}-edit.tsx**: Edit form page showing:
881
- - Page title: "Edit {Entity}"
882
- - `<Breadcrumb>`: Home > {Module} > Edit
883
- - Pre-filled form `<Card>` with sample data
884
- - Save and Cancel `<Button>` (Cancel: `<Link>` to `{module}-detail` or `{module}`)
885
-
886
- ### Step 6f: Build for Hub Serving (MANDATORY)
887
-
888
- The hub serves this app from its built `dist/` folder — an unbuilt app appears on the hub
889
- landing page as "Build required" with unclickable roles.
890
-
891
- 1. Run in `<app_folder>/context/mockup/`:
892
- ```bash
893
- npm install
894
- npm run build
895
- ```
896
- 2. Verify `dist/index.html` exists and its asset URLs start with `/{app_slug}/`.
897
- 3. If the build fails or cannot run (e.g., no network for `npm install`), report it in the
898
- output summary with the exact command the user must run — the hub landing page will show
899
- the app as "Build required" until then.
900
- 4. **Module-filtered runs**: rebuilding is still REQUIRED the previous `dist/` does not
901
- contain the new/updated page components.
902
-
903
- The Vite dev server (`npm run dev`) remains available for design iteration; it serves the
904
- app at `http://localhost:5173/{app_slug}/` because of the `base` setting.
905
-
906
- ### Step 7: Output Summary
907
-
908
- After generation, print a summary:
909
-
910
- ```
911
- Mockup Generation Complete
912
- ===========================
913
- Application: {App Name} ({Initials})
914
- Target Version: {version or "latest (all versions)"}
915
- Module Filter: {module name or "all modules"}
916
- Output: {path}/mockup/
917
-
918
- Filtering Summary:
919
- - User stories included: {count}
920
- - User stories excluded (strikethrough): {count}
921
- - User stories excluded (version filter): {count}
922
- - User stories excluded (module filter): {count}
923
- - NFRs/Constraints included: {count}
924
- - NFRs/Constraints excluded: {count}
925
-
926
- | Role | Pages | Page Folder |
927
- |-----------------------|-------|--------------------------------------|
928
- | Hub Administrator | 8 | src/pages/hub-administrator/ |
929
- | Hub Operation Support | 6 | src/pages/hub-operation-support/ |
930
-
931
- Files generated:
932
- - Config: .gitignore, package.json, vite.config.ts, tsconfig.json, tailwind.config.js, etc.
933
- - shadcn/ui: {N} component files in src/components/ui/
934
- - Layout: app-layout.tsx, app-header.tsx, app-sidebar.tsx, app-footer.tsx, sidebar-config.ts
935
- - Pages: {N} page component files
936
- - MOCKUP.html (per-app screen index) + mockup-manifest.json
937
- - Build: dist/ {built successfully | BUILD REQUIRED — run npm install && npm run build}
938
- - Mockup Hub: {created at <root>/mockup | upgraded to v{N} | already present}
939
-
940
- Total: {N} files
941
-
942
- Quick Start
943
- ===========
944
- 1. cd <root>/mockup
945
- 2. npm start (zero dependencies — no npm install required)
946
- 3. Open http://localhost:3000 in your browser
947
- - Landing page lists ALL applications and roles
948
- - This app's screen index: http://localhost:3000/{app_slug}
949
- 4. Change port: PORT=4000 npm start, or edit <root>/mockup/mockup.config.json
950
-
951
- Design iteration (optional): cd {mockup folder path} && npm run dev
952
- http://localhost:5173/{app_slug}/
953
- ```
954
-
955
- ### Step 7b: Route Integrity Validation (MANDATORY)
956
-
957
- Before finalizing output, perform a route integrity check across ALL generated files:
958
-
959
- 1. **Scan every generated page and layout component** for all `<Link to="...">`, `useNavigate("...")`,
960
- and `<a href="...">` references
961
- 2. **Build a route registry**: map every route reference to the page component that handles it
962
- 3. **Verify each React Router route** has a corresponding page component:
963
- - `<Link to="/{role}/{page}">` → verify `src/pages/{role}/{page}.tsx` exists
964
- - plain `<a href="/">` → acceptable for logout (hub landing); a `<Link to="/">` is NOT
965
- equivalent (basename keeps it inside the app)
966
- - `target="_blank"` links → acceptable for images, PDFs, external resources
967
- - `href="#"` or dead-end `<Link>` → **NOT ALLOWED** — must be fixed
968
- 4. **Verify App.tsx routes**: every page component must have a corresponding route definition
969
- 5. **For any missing page file**, either:
970
- - Generate the missing page component, OR
971
- - Update the link to point to an existing route
972
- 6. **Report any fixes** made during validation in the output summary
973
-
974
- If any dead-end link is found in the final output, the generation is **incomplete**.
975
-
976
- ## Changelog Append
977
-
978
- After all mockup files are successfully generated, append an entry to `CHANGELOG.md` in the application folder (`<app_folder>/CHANGELOG.md`):
979
-
980
- 1. Read `<app_folder>/CHANGELOG.md`. If it does not exist, create it with:
981
- ```markdown
982
- # Changelog
983
-
984
- - This file tracks all skill executions by version for this application.
985
- - The highest version recorded here is the current application version.
986
- - Skills MUST NOT execute for a version lower than the highest version in this file.
987
-
988
- ---
989
- ```
990
- 2. Search for a `## {version}` heading matching the current version.
991
- 3. If the section **exists**: append a new row to its table.
992
- 4. If the section **does not exist**: insert a new section after the `---` below the context header and before any existing `## vX.Y.Z` section (newest-first ordering), with a new table header and the first row.
993
- 5. Row format: `| {YYYY-MM-DD} | {application_name} | mockgen-shadcn | {module or "All"} | Generated React + shadcn/ui mockup screens |`
994
- 6. **Never modify or delete existing rows.**
995
-
996
- ## Important Rules
997
-
998
- - **Module filter is additive, not destructive**: When `module:` is specified, only the named
999
- module's page components are written/overwritten. All other files (layout components, other module
1000
- pages, config files) remain untouched. If the target module does not exist in PRD.md,
1001
- stop and report available module names before doing any file writes.
1002
- - **Version + module are independent axes**: Both may be combined freely. `module:Employer
1003
- v1.0.2` means "generate Employer module pages as they exist at v1.0.2". Version filtering
1004
- and module filtering each apply independently; a story must satisfy BOTH to be included.
1005
- - **Base path is mandatory**: `vite.config.ts` MUST set `base: "/{app_slug}/"` and
1006
- `main.tsx` MUST set `<BrowserRouter basename="/{app_slug}">` without them the built
1007
- app cannot be served by the hub at `/{app_slug}`.
1008
- - **No per-app server for viewing**: reviewers use ONLY the shared hub at `<root>/mockup/`
1009
- (ensure it per Step 4d). The Vite dev server is for design iteration only.
1010
- - **Manifest is mandatory**: every run writes/updates `mockup-manifest.json` without it
1011
- the hub cannot route the app and the landing page shows it as not ready.
1012
- - **Build is mandatory**: every run ends with `npm run build` (Step 6f) so the hub can
1013
- serve `dist/`; an unbuilt app shows as "Build required" with unclickable roles.
1014
- - **Root-relative links only in MOCKUP.html**: never hardcode `http://localhost:<port>`
1015
- the hub port is user-configurable.
1016
- - **ZERO dead links**: Every `<Link>`, `useNavigate()`, and `<a href>` in every file must resolve. No `href="#"`
1017
- - **Pagination on every list** (MANDATORY): Every page that renders a `<Table>` of records MUST include
1018
- shadcn/ui `<Pagination>` below it. Default page size is **10 items per page**. Applies to: module list
1019
- pages, history/audit pages, notifications page, and any embedded sub-tables within detail pages
1020
- that may grow unbounded. Use React `useState` for page state. Omitting pagination from any list
1021
- is a generation error.
1022
- - **Layout components for structure**: Header, footer, and sidebar are React components composed in a
1023
- shared layout route — NOT duplicated inline in each page
1024
- - **Page components are content only**: Role page files return only the page content JSX — the
1025
- layout wrapper is handled by `AppLayout` via React Router `<Outlet>`
1026
- - **React Router for navigation**: All in-app navigation uses `<Link>` or `useNavigate()` — no
1027
- `window.location` assignments, no `<a href>` for internal routes
1028
- - **shadcn/ui for all UI elements**: Buttons, inputs, tables, dialogs, dropdowns, badges, tabs,
1029
- avatars, etc. MUST use the generated shadcn/ui components — not raw HTML elements
1030
- - **Lucide React for all icons**: Use `import { IconName } from "lucide-react"` — no inline SVG,
1031
- no icon CDN dependencies
1032
- - **Images open in new tab**: Any image link or image view action uses `target="_blank"`
1033
- - **PDFs open in new tab**: Any PDF/document view link uses `target="_blank" rel="noopener noreferrer"`
1034
- - **MOCKUP.html links open in new tab**: All screen card links in the index use `target="_blank"`
1035
- - No external image dependencies; use `https://placehold.co/` for placeholder images
1036
- - Sidebar navigation must link between pages within the same role using React Router `<Link>`
1037
- - Header navigation (notification, profile, account) links use React Router
1038
- - Table action buttons (View, Edit, Add) use React Router navigation
1039
- - Tabs within pages use shadcn/ui `<Tabs>` component
1040
- - Back/Cancel buttons use React Router `useNavigate()` or `<Link>` to the parent page
1041
- - Preserve traceability: include user story tags with version as JSX comments in each page
1042
- (e.g., `{/* USHM00012 [v1.0.1] */}`)
1043
- - Do not generate pages for modules that have no user stories for a given role
1044
- - Common pages (home, profile, account, notifications) are generated for EVERY role
1045
- - Use consistent color scheme from the design system via CSS variables and Tailwind config
1046
- - The version displayed in footer should be the target version if specified, or the latest version
1047
- found in PRD.md
1048
- - **Strikethrough items MUST always be excluded** — lines wrapped in `~~` are deprecated/removed
1049
- - **Version filtering**: When a target version is provided, only include items from sections
1050
- with version tags <= target version
1051
- - **Model-driven pages**: When a module model file exists at `model/{kebab-module}/model.md`,
1052
- use the actual field definitions (field names, types, required/nullable, enums) for all
1053
- form inputs, table columns, and detail panels. Generic placeholder field names are NOT
1054
- acceptable when a model is available. See Step 1b and the "Model-Driven Field Usage" section.
1055
- - **Enum accuracy**: Enum `<Select>` options must use the exact values from the model's Enum
1056
- Definitions (Section 7), not inferred strings
1057
- - **Constraint-aware sample data**: Sample values must respect field constraints noted in the
1058
- model (e.g., use `MYS`, `BHR`, `MDV` for countryCode fields constrained by CONSHM018)
1059
- - **Report layouts**: When PRD.md contains report-related NFRs or user stories, generate
1060
- standalone HTML report layout files in `public/reports/` subfolder. These are self-contained A4
1061
- mockups (not React components) for stakeholder review of report structure before coding.
1062
- Use actual module model fields for column headers and realistic sample data rows. See
1063
- Step 3f for full report layout generation rules.
1064
- - **Dark mode support**: All pages and components must support dark mode via next-themes and
1065
- Tailwind `dark:` variant classes. shadcn/ui components handle this automatically through CSS variables.
1066
- - **TypeScript**: All generated `.tsx` files must be valid TypeScript. Use proper type annotations
1067
- for component props, state, and event handlers. Avoid `any` types.
1
+ ---
2
+ name: mockgen-shadcn
3
+ model: claude-opus-4-8
4
+ effort: high
5
+ description: >
6
+ Generate React + shadcn/ui mockup screens from PRD.md files for UI/UX human designer review.
7
+ Creates a Vite + React 19 + TypeScript + shadcn/ui mockup application with admin dashboard layout
8
+ (collapsible sidebar navigation, header with logo/notifications/locale/user menu, footer
9
+ with copyright/version) using React Router v7 for client-side navigation, organized by user role
10
+ in a mockup/ folder. The app is BUILT (npm run build) and its dist/ output is served by the
11
+ SINGLE shared Mockup Hub at <root>/mockup — a zero-dependency Node.js server with a landing
12
+ page listing every application and role (unclickable when not ready) and a configurable port
13
+ (PORT env / mockup.config.json). The Vite dev server remains available for design iteration only.
14
+ Input: application name (mandatory), version (mandatory), module (optional).
15
+ Output: mockup/ folder in the application's context folder
16
+ containing MOCKUP.html index page, mockup-manifest.json, Vite + React project files, layout
17
+ components, shadcn/ui components, role-specific page components, and the built dist/ folder;
18
+ plus the shared hub at <root>/mockup if not already present.
19
+ Trigger on keywords: "generate mockup shadcn", "generate shadcn mockup",
20
+ "create shadcn mockup screens", "shadcn UI mockup", "React mockup from user stories",
21
+ "mockup from PRD.md shadcn", "generate shadcn screens", "create shadcn UI screens".
22
+ Accepts application name and version as input
23
+ (e.g., `/mockgen-shadcn hub_middleware v1.0.3`).
24
+ Optionally accepts a module name to limit generation to screens for that module only
25
+ (e.g., `/mockgen-shadcn hub_middleware v1.0.3 module:Location Information`).
26
+ When module is specified, only page components for that module are generated/updated;
27
+ layout components, sidebars, config files, and other module pages are left untouched
28
+ (the manifest is updated and the app is rebuilt).
29
+ Automatically excludes strikethrough (deprecated/removed) items.
30
+ ---
31
+
32
+ # Mockgen shadcn/ui
33
+
34
+ Generate a Vite + React 19 + TypeScript + shadcn/ui mockup application from PRD.md for UI/UX
35
+ designer review. Layout uses React components (header, sidebar, footer) composed in a shared
36
+ layout route. Pages are React Router routes rendered inside the layout. All navigation is
37
+ client-side via React Router `<Link>` and `useNavigate`.
38
+
39
+ The mockup is generated with `base`/`basename` set to `/{app_slug}/`, **built** with
40
+ `npm run build`, and served from its `dist/` folder by the **shared Mockup Hub** — a single
41
+ zero-dependency Node.js server at `<root>/mockup/` that serves ALL applications' mockups
42
+ (see [references/mockup-hub-template.md](references/mockup-hub-template.md)). The hub renders
43
+ a landing page listing every application and role (roles are unclickable until the app is
44
+ generated AND built) and listens on a configurable port (`PORT` env var →
45
+ `mockup.config.json` → first unused port starting from 4000). The landing page includes
46
+ a port input text (defaulting to the current port) that persists a new port via
47
+ `POST /api/port` and re-listens on it; Compound Context Studio's Mockup page passes its
48
+ own topbar port input via `PORT` when its Start Hub button spawns the hub. The Vite dev
49
+ server (`npm run dev`) remains available for design iteration only.
50
+
51
+ ## Stack
52
+
53
+ | Layer | Technology |
54
+ |-------|------------|
55
+ | Serving | Shared Mockup Hub — `<root>/mockup/server.js` serves the built `dist/` (SPA fallback) |
56
+ | Build tool | Vite 6 |
57
+ | UI framework | React 19 + TypeScript 5 |
58
+ | Component library | shadcn/ui (Radix UI + Tailwind CSS) |
59
+ | Routing / navigation | React Router v7 |
60
+ | Styling | Tailwind CSS v3 (PostCSS) |
61
+ | Icons | Lucide React |
62
+ | Dark mode | next-themes |
63
+
64
+ ## Input
65
+
66
+ This skill uses standardized input resolution. Provide:
67
+
68
+ | Argument | Required | Example | Description |
69
+ |----------|----------|---------|-------------|
70
+ | `<application>` | Yes | `hub_middleware` | Application name to locate the context folder |
71
+ | `<version>` | Yes | `v1.0.3` | Version to scope processing (filter user stories <= this version) |
72
+ | `module:<name>` | No | `module:Location Information` | Limit generation to a single module |
73
+
74
+ ### Application Folder Resolution
75
+
76
+ The application name is matched against root-level application folders:
77
+ 1. Strip any leading `<number>_` prefix from folder names (e.g., `1_hub_middleware` → `hub_middleware`)
78
+ 2. Match case-insensitively against the provided application name
79
+ 3. Accept snake_case, kebab-case, or title-case input (all match the same folder)
80
+ 4. If no match found, list available applications and stop
81
+
82
+ ### Auto-Resolved Paths
83
+
84
+ | File | Resolved Path |
85
+ |------|---------------|
86
+ | PRD.md | `<app_folder>/context/PRD.md` |
87
+ | Module Models | `<app_folder>/context/model/` |
88
+ | Output (mockup) | `<app_folder>/context/mockup/` |
89
+ | Mockup Hub (shared) | `<root>/mockup/` |
90
+
91
+ **App slug** (used as the URL base path): the application folder name with the leading
92
+ `<number>_` prefix stripped (e.g., `1_hub_middleware` → `hub_middleware`). Record it during
93
+ input resolution — it is baked into `vite.config.ts` (`base`), `main.tsx`
94
+ (`BrowserRouter basename`), and all MOCKUP.html links.
95
+
96
+ ### Example Invocations
97
+
98
+ - `/mockgen-shadcn hub_middleware v1.0.3` (all modules, up to v1.0.3)
99
+ - `/mockgen-shadcn hub_middleware v1.0.3 module:Location Information` (one module, specific version)
100
+ - `/mockgen-shadcn "Hub Middleware" v1.0.3 module:Employer` (title-case app name)
101
+
102
+ ### Version and Module Filtering
103
+
104
+ - Only include user stories, NFRs, constraints,
105
+ and references from sections whose version tag is **less than or equal to** the target version
106
+ - If a module is provided (e.g., `module:Location Information`), only generate/update pages
107
+ for that specific module. All other modules are skipped. Common pages (home, profile,
108
+ account, notifications), layout components (header, footer, sidebars), and config files are
109
+ NOT regenerated when a module filter is active — only the module's own page components
110
+ are written (and MOCKUP.html is updated for only that module's cards).
111
+ - If no module is provided, process all modules (default behavior)
112
+
113
+ **Argument parsing**: The `module:` prefix is the canonical form. Also accept:
114
+ - `module:"Location Information"` (quoted, with space)
115
+ - `module:location_information` (snake_case — convert to title-case for matching)
116
+ - Natural language: `for Location Information module`, `only Location Information`
117
+
118
+ ## Version Gate
119
+
120
+ Before starting any work, resolve the application folder first (see Input Resolution below), then check `CHANGELOG.md` in the application folder (`<app_folder>/CHANGELOG.md`):
121
+
122
+ 1. If `<app_folder>/CHANGELOG.md` does not exist, skip this check (first-ever execution for this application).
123
+ 2. If `<app_folder>/CHANGELOG.md` exists, scan all `## vX.Y.Z` headings and determine the **highest version** using semantic versioning comparison.
124
+ 3. Compare the requested version against the highest version:
125
+ - If requested version **>=** highest version: proceed normally.
126
+ - If requested version **<** highest version: **STOP immediately**. Print: `"Version {requested} is lower than the current application version {highest} recorded in <app_folder>/CHANGELOG.md. Execution rejected."` Do NOT proceed with any work.
127
+
128
+ ## Workflow
129
+
130
+ ### Step 1: Parse PRD.md
131
+
132
+ Read the auto-resolved PRD.md file and extract:
133
+
134
+ 1. **Application name**: Derive from the parent folder name containing PRD.md.
135
+ Strip leading number and underscore prefix, then title-case.
136
+ Example: `1_hub_middleware` -> "Hub Middleware"
137
+
138
+ 2. **Application initials**: First letter of each word, uppercase.
139
+ Example: `1_hub_middleware` -> "HM"
140
+
141
+ 3. **Modules**: Each `## Module Name` section under a `# Module Category` heading.
142
+ Record the module name and its description (the line after the heading).
143
+
144
+ 4. **User stories per module**: Lines matching `- [USxx#####] As a {Role} user, I want to...`
145
+ Extract: tag, role, action summary.
146
+
147
+ 5. **Unique roles**: Collect all distinct roles from user stories.
148
+ Example: "Hub Administrator", "Hub Operation Support"
149
+
150
+ 6. **Target version** (from input argument): If a version was provided, record it for
151
+ filtering in the next sub-step.
152
+
153
+ #### 1a: Version Filtering and Strikethrough Exclusion (MANDATORY)
154
+
155
+ PRD.md is a version-controlled document. Each section (User Story, Non Functional
156
+ Requirement, Constraint, Reference) has a version tag in square brackets, e.g., `[v1.0.1]`.
157
+ Items may also be marked with strikethrough (`~~`) to indicate they are deprecated/removed.
158
+
159
+ **Strikethrough exclusion** (always applied, regardless of version parameter):
160
+ - Any line wrapped in `~~strikethrough~~` markup MUST be excluded from processing
161
+ - This includes user stories, NFRs, constraints, and references
162
+ - Example: `~~[USHM00006] As a Hub Administrator user, I want to...~~` → **SKIP**
163
+ - Partially strikethrough lines (where only part is struck) should still be excluded
164
+ if the tag identifier is within the strikethrough
165
+
166
+ **Version filtering** (applied only when a target version is provided):
167
+ - Each section under a module has one or more version tags like `[v1.0.0]` or `[v1.0.1]`
168
+ - Items listed under a version tag belong to that version
169
+ - When a target version is specified (e.g., `v1.0.1`):
170
+ - **Include** items from sections whose version tag is **<= target version**
171
+ - **Exclude** items from sections whose version tag is **> target version**
172
+ - Version comparison uses semantic versioning: compare major, then minor, then patch
173
+ - When no target version is specified, include all items from all versions (but still
174
+ exclude strikethrough items)
175
+
176
+ **Version tracking per section**: Record which version tag each item belongs to, as this
177
+ will be used for traceability in the generated pages.
178
+
179
+ Example parsing of a section with multiple versions:
180
+ ```markdown
181
+ ### User Story
182
+ [v1.0.0]
183
+ - ~~[USHM00006] As a Hub Administrator user, I want to manage...~~
184
+ - [USHM00009] As a Hub Administrator user, I want to map...
185
+ [v1.0.1]
186
+ - [USHM00012] As a Hub Administrator user, I want to manage the list...
187
+ ```
188
+
189
+ With target version `v1.0.0`:
190
+ - USHM00006 → EXCLUDED (strikethrough)
191
+ - USHM00009 → INCLUDED (v1.0.0 <= v1.0.0, not strikethrough)
192
+ - USHM00012 → EXCLUDED (v1.0.1 > v1.0.0)
193
+
194
+ With target version `v1.0.1` (or no version specified):
195
+ - USHM00006 → EXCLUDED (strikethrough)
196
+ - USHM00009 → INCLUDED
197
+ - USHM00012 → INCLUDED
198
+
199
+ #### 1c: Module Filtering (applied only when a module argument is provided)
200
+
201
+ When a `module` argument is present, apply module filtering after version filtering:
202
+
203
+ 1. **Match the specified module** against the list of parsed modules (case-insensitive, ignoring
204
+ leading/trailing whitespace). Also accept snake_case input by converting it to title-case
205
+ for comparison (e.g., `location_information` → match "Location Information").
206
+ 2. **Record the matched module name** for use in Step 3 and beyond.
207
+ 3. If no module matches, stop and report the available module names to the user before proceeding.
208
+ 4. **Module filter scope**: the filter only affects **page component generation** (Step 6e).
209
+ All other steps complete normally (parsing, design system, planning) but output is restricted
210
+ to the filtered module's pages.
211
+
212
+ **Module-filtered generation mode** differs from full generation in these ways:
213
+
214
+ | Aspect | Full Generation | Module-Filtered |
215
+ |--------|----------------|-----------------|
216
+ | Common pages (home, profile, account, notifications) | Generate for every role | **SKIP** — already exist |
217
+ | Layout components (header, footer, sidebar) | Generate | **SKIP** — already exist |
218
+ | Config files (package.json, vite.config.ts, etc.) | Generate | **SKIP** — already exist |
219
+ | shadcn/ui component files | Generate | **SKIP** — already exist |
220
+ | Route config (App.tsx) | Generate | **Update** — add routes for new module pages |
221
+ | Module page components (target module) | Generate | **Generate / overwrite** |
222
+ | Module page components (other modules) | Generate | **SKIP** — leave untouched |
223
+ | MOCKUP.html | Generate full file | **Update only the target module's cards** |
224
+ | Footer version string | Update | **Update** (version may have changed) |
225
+ | mockup-manifest.json | Generate | **Update** (version, generatedAt, screen counts) |
226
+ | Mockup Hub (`<root>/mockup/`) | Ensure (create/upgrade) | **Ensure** (create/upgrade) |
227
+ | `npm run build` (dist/ for hub serving) | Run | **Run** (rebuild required after page changes) |
228
+
229
+ **MOCKUP.html partial update** (module-filtered mode):
230
+ - Read the existing MOCKUP.html
231
+ - Locate the screen cards section for the target module (search by module name heading or
232
+ existing card tags)
233
+ - Replace only those cards with freshly generated ones reflecting the new pages
234
+ - Update the total screen count per role (add net new pages)
235
+ - Update the version badge if it changed
236
+ - Update the "N new screens added in vX.Y.Z" banner text
237
+ - Leave all other role sections and cards unchanged
238
+
239
+ ### Step 1b: Discover and Load Module Models
240
+
241
+ After parsing PRD.md, look for module models at the auto-resolved model path:
242
+ `<app_folder>/context/model/`
243
+
244
+ For each module extracted in Step 1:
245
+
246
+ 1. Convert the module name to **kebab-case** to derive the model folder name:
247
+ - Lowercase the module name and replace spaces with hyphens
248
+ - Examples: "Location Information" → `location-information`, "Industrial Classification" → `industrial-classification`, "Employer" → `employer`
249
+
250
+ 2. Check for `{model_dir}/{kebab-module}/model.md`
251
+
252
+ 3. If the file exists, parse it and extract the following sections:
253
+
254
+ - **Section 2 – Collection Catalog**: collection names and types (Root Collection, Audit Collection, etc.)
255
+ - **Section 5 – Field Detail per Collection**: for each collection — field name, type, required, nullable, constraints/notes
256
+ - **Section 6 – Embedded Document Definitions**: embedded type name and its sub-fields
257
+ - **Section 7 – Enum Definitions**: enum name and all allowed values with descriptions
258
+ - **Section 9 – Index Recommendations**: indexed fields (used to identify search/filter parameters)
259
+
260
+ 4. Store this as the **module model** for the module, keyed by module name
261
+
262
+ **Field classification** (used during page generation in Step 6e):
263
+
264
+ | Category | Definition | Usage |
265
+ |----------|-----------|-------|
266
+ | System fields | `_id`, `_audit`, `_version`, `deleted`, `deletedAt`, `deletedBy` | Exclude from user-facing forms |
267
+ | Audit-only fields | Fields whose Source is `CONVENTION` and type is `Audit` | Show in detail views only |
268
+ | Required form fields | `Required: Yes` AND not a system field | Mandatory inputs in create/edit forms |
269
+ | Optional form fields | `Required: No` AND not a system field | Optional inputs in create/edit forms |
270
+ | Read-only after creation | Fields marked as unique identity keys (e.g., `companyRegistrationNumber`) | Show in edit forms as readonly |
271
+ | Search/filter fields | Fields referenced in Index Recommendations | Render as filter controls in list pages |
272
+ | Enum fields | Type matches an entry in Section 7 Enum Definitions | Render as `<Select>` dropdowns |
273
+ | Embedded object fields | Type is a custom embedded document type (not a primitive) | Render as grouped `<Card>` sections |
274
+ | Embedded array fields | Type ends in `[]` (e.g., `PersonInCharge[]`) | Render as repeatable row with Add/Remove |
275
+
276
+ **Fallback**: If no `model.md` exists for a module, infer fields from user story text (original behavior).
277
+
278
+ ---
279
+
280
+ ### Step 2: Load Design System
281
+
282
+ Load the design system using a two-tier resolution strategy:
283
+
284
+ #### 2a: PRD.md Design System Reference (Primary Source)
285
+
286
+ Check if PRD.md contains a `# Design System` section. If it does:
287
+ 1. Extract the referenced file path (e.g., from `[DESIGN_SYSTEM.md](reference/DESIGN_SYSTEM.md)`)
288
+ 2. Resolve the path relative to PRD.md's location
289
+ 3. If the referenced file exists, read it and extract:
290
+ - Color palettes (primary, secondary, accent, neutral — hex values)
291
+ - Typography (font families, font sizes, weight scale)
292
+ - Spacing scale (if overriding Tailwind defaults)
293
+ - Component patterns (button styles, card styles, form input styles, table styles, badge/chip styles, modal patterns)
294
+ - Layout grid rules
295
+ 4. Apply extracted tokens to the Tailwind config (`tailwind.config.js`) custom colors/fonts,
296
+ shadcn/ui CSS variables in `src/index.css`, and all generated components
297
+
298
+ #### 2b: Context Design Folder (Fallback)
299
+
300
+ If PRD.md does not have a `# Design System` section, or the referenced file does not exist, fall back to the application's `<app_folder>/context/design/` folder. This folder contains pre-defined design tokens and Tailwind component guidelines maintained externally by the UI/UX team.
301
+
302
+ Read all files in `{app_name}/context/design/` (where `{app_name}` is the resolved application folder name from Step 1). Apply the design tokens and guidelines found there to all generated mockup pages.
303
+
304
+ **Expected files** (any or all may be present):
305
+ - `design-system.md` — Colors, typography, spacing, and visual style definitions
306
+ - `components.md` — Reusable component patterns and Tailwind class conventions
307
+ - `guidelines.md` — Layout rules, accessibility standards, and stack-specific guidelines
308
+
309
+ #### 2c: Default Fallback
310
+
311
+ If neither the PRD reference nor the `{app_name}/context/design/` folder provides design tokens, use the default shadcn/ui "New York" style: zinc/neutral color palette, Inter/Geist font stack, and default shadcn/ui component styling with CSS variables.
312
+
313
+ #### 2d: Process Flow Status States
314
+
315
+ If PRD.md contains a `# High Level Process Flow` section, scan it for entity status lifecycle descriptions (e.g., "Received → Validated → Enriched → Active"). For each status lifecycle found:
316
+ - Ensure list pages for the corresponding module include a status column with colored `<Badge>` variants for each state
317
+ - Use design system color tokens for badge variants (e.g., `default` for active/completed, `secondary` for pending, `destructive` for failed/rejected)
318
+
319
+ ### Step 3: Plan Screen Files
320
+
321
+ For each role, determine ALL pages to generate. **Every clickable link, tab, or action
322
+ in any generated page MUST have a corresponding page component. No link may be a dead end.**
323
+
324
+ **Module filter applied here**: If a module argument was provided (Step 1c), plan only the
325
+ pages for that module across all roles. Skip common pages (home, profile, account,
326
+ notifications) and skip all other modules entirely. The screen plan table should list only
327
+ the filtered module's pages.
328
+
329
+ #### 3a: Core Pages (React components)
330
+
331
+ 1. **home.tsx**: Default home/dashboard page with welcome message and summary widgets
332
+ 2. **profile.tsx**: User profile page (linked from header user dropdown)
333
+ 3. **account.tsx**: Account settings page (linked from header user dropdown)
334
+ 4. **notifications.tsx**: Notifications page (linked from header notification bell)
335
+ 5. **One page per module that has user stories for this role**
336
+
337
+ #### 3b: Sub-Pages (Detail / Edit / Create)
338
+
339
+ For each module page, analyze the user stories and identify sub-pages needed:
340
+
341
+ | User Story Pattern | Sub-Page Required |
342
+ |-------------------|-------------------|
343
+ | "view details of X" | `{module}-detail.tsx` - Detail view for a single record |
344
+ | "add/create/register X" | `{module}-create.tsx` - Create/add form |
345
+ | "edit/update/modify X" | `{module}-edit.tsx` - Edit form (pre-filled) |
346
+ | "view history/audit of X" | `{module}-history.tsx` - History/audit log view |
347
+ | "view associated X of Y" | `{module}-{sub}-list.tsx` - Associated records list |
348
+
349
+ #### 3f: Report Layout Pages (conditional — if PRD.md contains report-related content)
350
+
351
+ Scan PRD.md for report-related content:
352
+ - NFRs mentioning "report", "Report interface", "generate report", "report generation"
353
+ - User stories describing generating/downloading PDF, Excel, or CSV reports
354
+ - A "Report" module or report-related NFRs defining specific report types
355
+
356
+ **If report requirements are found**, generate HTML report layout mockups for each
357
+ identified report. These layouts serve as draft previews for human designers/stakeholders
358
+ to verify the report structure before the AI coding agent implements the actual report
359
+ generation code.
360
+
361
+ For each identified report, create a standalone HTML file in a `public/reports/` subfolder:
362
+
363
+ | Report Source | File Generated |
364
+ |--------------|----------------|
365
+ | NFR describes "Staff Allocation Summary report" | `public/reports/staff_allocation_summary.html` |
366
+ | User story: "generate Job Demand report by country" | `public/reports/job_demand_by_country.html` |
367
+ | Report module NFR: "Monthly Activity Report" | `public/reports/monthly_activity_report.html` |
368
+
369
+ **Report layout file conventions:**
370
+ - Each report layout is a **standalone self-contained HTML document** (not a React component)
371
+ with its own `<html>`, `<head>`, `<body>` tags and Tailwind CDN `<script>` in the head
372
+ - Layout simulates a **print-ready A4 page** with appropriate margins and sizing:
373
+ ```html
374
+ <body class="bg-gray-100">
375
+ <div class="mx-auto bg-white shadow" style="width: 210mm; min-height: 297mm; padding: 15mm;">
376
+ <!-- Report content -->
377
+ </div>
378
+ </body>
379
+ ```
380
+ - **Report header**: Report title (centered, bold), generation date, filter parameters used
381
+ - **Report body**: Data table or summary layout using actual fields from the module model
382
+ (if `model/{module}/model.md` exists, use its field definitions for column headers)
383
+ - **Report footer**: Page indicator text ("Page 1 of 1"), generation timestamp
384
+ - Use **sample data rows** (5-10 rows) with realistic placeholder values matching model constraints
385
+ - Apply the design system colors from Step 2 for header background, borders, and accents
386
+ - For landscape reports (wide tables with many columns), use `style="width: 297mm; min-height: 210mm;"`
387
+
388
+ **Report parameter section**: Above the report data, include a gray-shaded "Parameters" box
389
+ showing the filter criteria used to generate the report (e.g., Date Range: 2025-01-01 to
390
+ 2025-12-31, Department: All, Status: Active).
391
+
392
+ **Add to MOCKUP.html**: Include a "Reports" section at the bottom of each role's screen cards
393
+ (after all module cards) listing the report layout links. Report links open in new tabs
394
+ pointing to the hub's static route `/{app_slug}/reports/{report_file}.html`. Also list the
395
+ report file names in the manifest's `reports` array.
396
+
397
+ **Add to sidebar**: If reports are present, add a "Reports" navigation group in each role's
398
+ sidebar with links opening report layouts in new tabs.
399
+
400
+ #### 3c: Tabbed Pages
401
+
402
+ If a module page contains tabs (e.g., a detail page with Overview, Documents, History tabs),
403
+ use shadcn/ui `<Tabs>` component **within the same page component**. Only create separate
404
+ page component files for tabs if the tab content is substantial (more than ~100 lines).
405
+ Use the naming convention for separate files: `{module}-tab-{tab_name}.tsx`
406
+
407
+ Example: `employer-tab-overview.tsx`, `employer-tab-documents.tsx`, `employer-tab-history.tsx`
408
+
409
+ #### 3d: Page File Naming Convention
410
+
411
+ Convert names to kebab-case for file names, PascalCase for component names.
412
+ Example: "Location Information" → file: `location-information.tsx`, component: `LocationInformation`
413
+
414
+ #### 3e: Build Screen Plan
415
+
416
+ Build a **complete** screen plan. Every entry must map to a generated file:
417
+
418
+ | Role | Folder Name | Page File | Source | Description |
419
+ |------|-------------|-----------|--------|-------------|
420
+ | Hub Administrator | hub-administrator | home.tsx | Common | Dashboard home |
421
+ | Hub Administrator | hub-administrator | profile.tsx | Common | User profile |
422
+ | Hub Administrator | hub-administrator | account.tsx | Common | Account settings |
423
+ | Hub Administrator | hub-administrator | notifications.tsx | Common | Notifications list |
424
+ | Hub Administrator | hub-administrator | location-information.tsx | Module | USHM00006, USHM00009 |
425
+ | Hub Administrator | hub-administrator | location-information-detail.tsx | Sub-page | View location details |
426
+ | Hub Administrator | hub-administrator | location-information-create.tsx | Sub-page | Add new location |
427
+ | Hub Operation Support | hub-operation-support | home.tsx | Common | Dashboard home |
428
+ | Hub Operation Support | hub-operation-support | profile.tsx | Common | User profile |
429
+ | Hub Operation Support | hub-operation-support | account.tsx | Common | Account settings |
430
+ | Hub Operation Support | hub-operation-support | notifications.tsx | Common | Notifications list |
431
+ | Hub Operation Support | hub-operation-support | employer.tsx | Module | USHM00021-USHM00033 |
432
+ | Hub Operation Support | hub-operation-support | employer-detail.tsx | Sub-page | View employer details |
433
+ | Hub Operation Support | hub-operation-support | employer-create.tsx | Sub-page | Register new employer |
434
+
435
+ ### Step 4: Create Output Folder Structure
436
+
437
+ **Module filter**: When a module argument is active, skip this step entirely — the folder
438
+ structure already exists from a previous full generation. Only page components for the target
439
+ module will be written in Step 6e.
440
+
441
+ Create the mockup folder at the auto-resolved mockup output path (full generation only):
442
+
443
+ ```
444
+ <app_folder>/context/
445
+ mockup/
446
+ .gitignore
447
+ package.json
448
+ vite.config.ts
449
+ tsconfig.json
450
+ tsconfig.app.json
451
+ tsconfig.node.json
452
+ tailwind.config.js
453
+ postcss.config.js
454
+ components.json # shadcn/ui configuration
455
+ index.html # Vite entry HTML
456
+ MOCKUP.html # Per-app screen index (served by hub at /{app_slug})
457
+ mockup-manifest.json # Hub discovery manifest (app, stack, roles, version)
458
+ dist/ # Built output served by the hub (npm run build; gitignored)
459
+ public/
460
+ reports/ # Report layout files (if applicable)
461
+ src/
462
+ main.tsx # React entry point
463
+ App.tsx # Router configuration
464
+ index.css # Tailwind directives + shadcn/ui CSS variables
465
+ lib/
466
+ utils.ts # cn() utility
467
+ components/
468
+ ui/ # shadcn/ui components
469
+ button.tsx
470
+ card.tsx
471
+ table.tsx
472
+ badge.tsx
473
+ input.tsx
474
+ label.tsx
475
+ select.tsx
476
+ dialog.tsx
477
+ dropdown-menu.tsx
478
+ avatar.tsx
479
+ separator.tsx
480
+ tabs.tsx
481
+ switch.tsx
482
+ tooltip.tsx
483
+ breadcrumb.tsx
484
+ pagination.tsx
485
+ sheet.tsx
486
+ layout/
487
+ app-layout.tsx # Shared layout with sidebar + header + footer
488
+ app-header.tsx # Top header component
489
+ app-sidebar.tsx # Sidebar nav component (role-aware)
490
+ app-footer.tsx # Footer component
491
+ sidebar-config.ts # Sidebar menu items per role
492
+ pages/
493
+ {role-kebab-case}/
494
+ home.tsx
495
+ profile.tsx
496
+ account.tsx
497
+ notifications.tsx
498
+ {module-kebab-case}.tsx
499
+ {module-kebab-case}-detail.tsx
500
+ {module-kebab-case}-create.tsx
501
+ {module-kebab-case}-edit.tsx
502
+ ...
503
+ ```
504
+
505
+ ### Step 4b: Generate Project Config Files
506
+
507
+ **Module filter**: When a module argument is active, skip this step entirely.
508
+
509
+ Generate all config and entry files using the templates from
510
+ [references/admin-layout-template.md](references/admin-layout-template.md).
511
+
512
+ #### .gitignore
513
+
514
+ ```
515
+ node_modules/
516
+ dist/
517
+ .DS_Store
518
+ *.log
519
+ *.local
520
+ ```
521
+
522
+ Key project setup:
523
+ - `package.json` — Vite + React 19 + TypeScript + Tailwind CSS + shadcn/ui dependencies
524
+ - `vite.config.ts` — Vite config with React plugin, path aliases, and
525
+ `base: "/{app_slug}/"` (REQUIRED so the built app is servable by the hub at `/{app_slug}`)
526
+ - `tsconfig.json` / `tsconfig.app.json` / `tsconfig.node.json` — TypeScript configs with path aliases
527
+ - `tailwind.config.js` — Tailwind config with shadcn/ui integration and design system tokens
528
+ - `postcss.config.js` — PostCSS with Tailwind and autoprefixer
529
+ - `components.json` — shadcn/ui configuration (New York style, zinc base)
530
+ - `index.html` — Vite entry HTML with Google Fonts
531
+ - `src/main.tsx` — React root render with `<BrowserRouter basename="/{app_slug}">`
532
+ (REQUIRED to match the Vite `base`)
533
+ - `src/App.tsx` — React Router configuration with all role/page routes
534
+ - `src/index.css` — Tailwind directives + shadcn/ui CSS variables (light and dark)
535
+ - `src/lib/utils.ts` — `cn()` utility (clsx + tailwind-merge)
536
+
537
+ ### Step 4c: Generate shadcn/ui Component Files
538
+
539
+ **Module filter**: When a module argument is active, skip this step entirely.
540
+
541
+ Generate the shadcn/ui component files directly into `src/components/ui/`. These follow the
542
+ standard shadcn/ui "New York" style patterns. The components are owned by the project — they
543
+ are NOT imported from npm.
544
+
545
+ **Required components** (generate all of these):
546
+
547
+ | Component | File | Primary Usage |
548
+ |-----------|------|--------------|
549
+ | Button | `button.tsx` | Actions, navigation, form submission |
550
+ | Card | `card.tsx` | Content containers, stat cards, detail panels |
551
+ | Table | `table.tsx` | Data lists, records, audit logs |
552
+ | Badge | `badge.tsx` | Status indicators, tags, enum values |
553
+ | Input | `input.tsx` | Text fields, search, filters |
554
+ | Label | `label.tsx` | Form field labels |
555
+ | Select | `select.tsx` | Dropdowns, enum selectors, page size |
556
+ | Dialog | `dialog.tsx` | Delete confirmations, modals |
557
+ | DropdownMenu | `dropdown-menu.tsx` | Header user menu, notification dropdown |
558
+ | Avatar | `avatar.tsx` | User avatars in header and profile |
559
+ | Separator | `separator.tsx` | Visual dividers |
560
+ | Tabs | `tabs.tsx` | Detail page sections, notification filters |
561
+ | Switch | `switch.tsx` | Boolean toggles, notification preferences |
562
+ | Tooltip | `tooltip.tsx` | Field hints, readonly explanations |
563
+ | Breadcrumb | `breadcrumb.tsx` | Page navigation trail |
564
+ | Pagination | `pagination.tsx` | Table/list pagination |
565
+ | Sheet | `sheet.tsx` | Mobile sidebar overlay |
566
+
567
+ Each component follows the standard shadcn/ui implementation pattern:
568
+ - Uses `@radix-ui/*` primitives for accessibility
569
+ - Styled with Tailwind CSS utility classes
570
+ - Supports `className` prop via `cn()` utility
571
+ - Uses `cva` (class-variance-authority) for variants where applicable
572
+ - Forwards refs properly
573
+
574
+ ### Step 4d: Write mockup-manifest.json and Ensure the Mockup Hub
575
+
576
+ **Always runs** (full AND module-filtered generation; in module-filtered mode UPDATE the
577
+ existing manifest — version, generatedAt, per-role screen counts).
578
+
579
+ 1. Write `<app_folder>/context/mockup/mockup-manifest.json` following the schema in
580
+ [references/mockup-hub-template.md](references/mockup-hub-template.md):
581
+
582
+ ```json
583
+ {
584
+ "app": "{app_slug}",
585
+ "appName": "{App Name}",
586
+ "description": "{short description from PRD.md}",
587
+ "stack": "shadcn",
588
+ "version": "{target version}",
589
+ "generatedAt": "{YYYY-MM-DD}",
590
+ "roles": [
591
+ { "name": "{Role Name}", "slug": "{role-kebab-case}", "screens": {count} }
592
+ ],
593
+ "reports": ["{report_file}.html"]
594
+ }
595
+ ```
596
+
597
+ (`reports` only when report layouts were generated.) The hub reads this manifest to
598
+ route the app and render its landing-page card; without it the app shows as "Not
599
+ generated yet" and its roles are unclickable.
600
+
601
+ 2. Ensure the shared hub exists at `<root>/mockup/` per the Ensure-Hub rules in
602
+ [references/mockup-hub-template.md](references/mockup-hub-template.md): create
603
+ `server.js`, `package.json`, `mockup.config.json`, and `.gitignore` if missing;
604
+ upgrade `server.js`/`package.json` only when the existing `HUB_VERSION` is lower;
605
+ never overwrite an existing `mockup.config.json` or `.gitignore`. All hub artifacts
606
+ (config, logs, any `node_modules/`) live inside `<root>/mockup/` and are gitignored
607
+ there.
608
+
609
+ ### Step 5: Generate MOCKUP.html Index
610
+
611
+ **Module filter**: When a module argument is active, do NOT regenerate the full MOCKUP.html.
612
+ Instead, apply a **partial update** as described in Step 1c: update only the target module's
613
+ screen cards, the version badge, and the per-role screen count. Leave all other content
614
+ unchanged.
615
+
616
+ Create the index page using the template in [references/mockup-index-template.md](references/mockup-index-template.md).
617
+
618
+ MOCKUP.html is this app's screen index, served by the hub at `/{app_slug}`. It shows:
619
+ - Hub startup banner with instructions (`cd <root>/mockup && npm start` — no install
620
+ needed; port configurable via `PORT` env var or `mockup.config.json`) and a reminder
621
+ that the app must be built (`npm run build`) before screens open
622
+ - Application name and description
623
+ - **Target version** used for generation
624
+ - Number of excluded items for transparency
625
+ - For each role: role name, list of screen cards with links
626
+ - **ALL screen links use `target="_blank" rel="noopener noreferrer"`** with
627
+ **root-relative** URLs `/{app_slug}/{role}/{page}` (never hardcode
628
+ `http://localhost:<port>` the hub port is user-configurable) so they open in new
629
+ tabs via the running hub (SPA fallback serves `dist/index.html`, React Router resolves
630
+ the route)
631
+ - A "Open Role Dashboard" quick-launch link per role section
632
+
633
+ ### Step 6: Generate Layout Components and Page Components
634
+
635
+ Use templates from [references/admin-layout-template.md](references/admin-layout-template.md).
636
+
637
+ **Apply the design system** from Step 2 (colors, typography, spacing) to all components via
638
+ the CSS variables in `src/index.css` and the Tailwind config.
639
+
640
+ **Module filter**: When a module argument is active, skip steps 6a–6d (layout components).
641
+ Proceed directly to **6e** for the target module's page components only. Also update the
642
+ footer version string in `app-footer.tsx` if the version changed.
643
+
644
+ #### 6a: Generate src/components/layout/app-layout.tsx
645
+
646
+ Shared layout component using React Router `<Outlet>`. Contains:
647
+ - `<AppHeader>` at the top (fixed)
648
+ - `<AppSidebar>` on the left (fixed, collapsible)
649
+ - `<Outlet>` for page content (scrollable)
650
+ - `<AppFooter>` at the bottom
651
+ - ThemeProvider wrapping for dark mode support
652
+ - Sidebar state management (expanded/collapsed)
653
+
654
+ #### 6b: Generate src/components/layout/app-header.tsx
655
+
656
+ Header component containing:
657
+ - Logo + App Name (left) — `<Link>` to home
658
+ - Notification bell with shadcn/ui `<DropdownMenu>` and `<Badge>` count
659
+ - Globe/locale selector with shadcn/ui `<DropdownMenu>`
660
+ - Dark mode toggle button using next-themes `useTheme()`
661
+ - User `<Avatar>` with `<DropdownMenu>` (Profile, Account, Logout)
662
+ - All Profile/Account/Notifications links use React Router `<Link>` / `useNavigate()`
663
+ - Lucide React icons throughout (Bell, Globe, Moon, Sun, User, LogOut, Settings)
664
+
665
+ #### 6c: Generate src/components/layout/app-footer.tsx
666
+
667
+ Simple footer with copyright year and version string using `<Separator>` divider.
668
+
669
+ #### 6d: Generate src/components/layout/sidebar-config.ts and app-sidebar.tsx
670
+
671
+ **sidebar-config.ts**: Export a configuration object mapping each role to its sidebar menu items:
672
+ ```typescript
673
+ export type SidebarItem = {
674
+ title: string;
675
+ path: string;
676
+ icon: string; // Lucide icon name
677
+ };
678
+
679
+ export type SidebarConfig = {
680
+ [role: string]: {
681
+ label: string;
682
+ items: SidebarItem[];
683
+ reports?: { title: string; href: string }[];
684
+ };
685
+ };
686
+ ```
687
+
688
+ **app-sidebar.tsx**: Sidebar component that:
689
+ - Reads the current role from React Router `useParams()`
690
+ - Renders menu items from sidebar-config.ts for that role
691
+ - Highlights the active menu item using `useLocation().pathname`
692
+ - Uses React Router `<Link>` for navigation (not HTMX)
693
+ - Uses Lucide React icons dynamically based on config
694
+ - Supports collapsed state (icons only) via context/state
695
+ - Has a collapsible toggle button
696
+
697
+ #### 6e: Generate page components (src/pages/{role-kebab-case}/{page}.tsx)
698
+
699
+ Each page component is a **standard React functional component** that returns JSX.
700
+ Pages use shadcn/ui components for all UI elements.
701
+
702
+ **All navigation within page components uses React Router** `<Link>` or `useNavigate()`.
703
+
704
+ **Breadcrumbs**: Use shadcn/ui `<Breadcrumb>` component. Home link is a `<Link>`,
705
+ module link is a `<Link>`, current page is `<BreadcrumbPage>` (non-interactive).
706
+
707
+ #### Admin Layout: Screen Content Generation
708
+
709
+ For each module page, analyze the user stories and generate appropriate UI mockup elements:
710
+
711
+ | User Story Pattern | UI Element |
712
+ |-------------------|------------|
713
+ | "search for X based on parameters" | Filter `<Card>` with `<Input>`/`<Select>` + `<Table>` results |
714
+ | "view details of X" | Detail `<Card>` with labeled fields in grid layout |
715
+ | "manage X" / "configure X" | `<Table>` with Add/Edit/Delete action `<Button>` components |
716
+ | "view history/changes" | `<Table>` with timestamps and `<Badge>` change types |
717
+ | "map X to Y" | Two-panel mapping interface or matrix `<Table>` |
718
+ | "activate/deactivate X" | `<Switch>` toggles in table rows or config panel |
719
+ | "view associated X" | Related records `<Table>` or linked `<Card>` sections |
720
+
721
+ #### Model-Driven Field Usage (MANDATORY when model file exists)
722
+
723
+ When a module model was loaded in Step 1b, use its actual field definitions — not generic placeholders — to populate every page. Generic field names like "Field 1" or "Description" are not acceptable when a model is available.
724
+
725
+ **Field type → shadcn/ui component mapping:**
726
+
727
+ | Model Type | Form Component | Notes |
728
+ |------------|---------------|-------|
729
+ | `String` | `<Input type="text">` with `<Label>` | Use `maxLength` if constraints specify length |
730
+ | `Number` | `<Input type="number">` with `<Label>` | |
731
+ | `Boolean` | `<Switch>` with `<Label>` | |
732
+ | `ISODate` | `<Input type="date">` or `<Input type="datetime-local">` | |
733
+ | `ObjectId` (reference) | `<Input readOnly>` or lookup widget with `<Tooltip>` | Display as read-only ID reference |
734
+ | Enum (Section 7 match) | `<Select>` with all enum values as `<SelectItem>` | Show enum value descriptions as item text |
735
+ | Embedded Object | `<Card>` section grouping sub-fields | Title the card with embedded type name |
736
+ | Embedded Array (`[]`) | Repeatable `<Card>` section with `<Button>` "+ Add" / "Remove" | Show one pre-filled example row |
737
+
738
+ **List / Search pages** (`{module}.tsx`):
739
+ - **Filter section**: `<Card>` with filter inputs only for fields in Index Recommendations (Section 9). Use the correct component per the mapping above. Enum-indexed fields use `<Select>`. Date-indexed fields use date range pickers.
740
+ - **Results table**: shadcn/ui `<Table>` with 5–7 most identifying non-system fields as columns. For embedded objects, show as a single column (e.g., "Company Name"). Null/optional fields shown with a dash (`—`).
741
+ - **Table row actions**: View → `<Link>` to `{module}-detail`, Edit → `<Link>` to `{module}-edit`, Delete → shadcn/ui `<Dialog>` confirm
742
+ - **Pagination** (MANDATORY): Every results table MUST include shadcn/ui `<Pagination>` directly below the table. Requirements:
743
+ - Default page size: **10 items per page**
744
+ - Show "Showing X–Y of Z results" summary text on the left
745
+ - Show page size `<Select>` with options 10, 25, 50 on the right (default 10)
746
+ - Show Previous / Next and page number buttons using `<Pagination>` component
747
+ - Page state managed via React `useState` (`currentPage`, `pageSize`, `totalItems`)
748
+ - Previous/Next buttons are disabled when at first/last page
749
+ - Use sample data: populate exactly 10 visible rows in the table (matching the default page size)
750
+
751
+ **Detail pages** (`{module}-detail.tsx`):
752
+ - Show ALL non-system fields, grouped logically:
753
+ - Basic fields: flat primitive fields in a 2-column grid `<Card>`
754
+ - Embedded objects (e.g., `address`, `contact`): each in its own labeled sub-`<Card>`
755
+ - Embedded arrays (e.g., `personsInCharge`): rendered as a sub-`<Table>` with a row per item
756
+ - Enum fields: display value wrapped in a `<Badge>` with appropriate variant
757
+ - ISODate fields: formatted as `DD MMM YYYY HH:mm` in sample data
758
+ - Boolean fields: show as a `<Badge>` ("Active" variant=default / "Inactive" variant=secondary)
759
+ - Include Edit `<Button>`, Delete `<Dialog>` confirm, and Back to List `<Button>` actions
760
+
761
+ **Create pages** (`{module}-create.tsx`):
762
+ - Include ALL `Required: Yes` non-system fields as mandatory inputs (mark with `*` via `<Label>`)
763
+ - Include `Required: No` fields as optional inputs where they make sense for initial creation
764
+ - Group embedded objects as `<Card>` sections with a title
765
+ - For embedded arrays: show one empty repeatable row with a `<Button>` "+ Add"
766
+ - Submit `<Button>` and Cancel `<Button>` (Cancel navigates back to `{module}` list via `useNavigate()`)
767
+
768
+ **Edit pages** (`{module}-edit.tsx`):
769
+ - Same structure as create page but with sample data pre-filled in all inputs
770
+ - Fields that serve as unique identity keys (e.g., `companyRegistrationNumber`) must be rendered as `<Input readOnly>` with a `<Tooltip>` explaining they cannot be changed
771
+ - Save `<Button>` and Cancel `<Button>`
772
+
773
+ **History / Audit pages** (`{module}-history.tsx`):
774
+ - Use fields from the **audit/history collection** (the non-root collection in the Collection Catalog):
775
+ - `changeType` → `<Badge>` using enum values from Section 7 with variant mapping
776
+ - `fieldChanged` → `<code>` styled text
777
+ - `previousValue` / `newValue` → inline diff or truncated display
778
+ - `changedAt` → formatted timestamp
779
+ - `changedBy` → plain text (e.g., "SYSTEM" or username)
780
+ - Render as a `<Table>`, newest first
781
+ - **Pagination** (MANDATORY): Include `<Pagination>` below the history table. Default 10 items per page.
782
+
783
+ **Sample data alignment**: Placeholder values in pages must be consistent with field constraints:
784
+ - `countryCode` → use actual allowed values (e.g., "MYS", "BHR", "MDV") per constraints if present
785
+ - Enum fields → use one of the defined enum values (not arbitrary strings)
786
+ - `companyRegistrationNumber` → e.g., "201901012345 (1234567-X)"
787
+ - `ISODate` fields → use realistic ISO dates (e.g., "2025-08-15T10:30:00Z")
788
+
789
+ ---
790
+
791
+ #### Link Integrity Rules (CRITICAL)
792
+
793
+ **Every clickable element MUST navigate to a real route. No dead-end links allowed.**
794
+
795
+ 1. **Table row actions** (View, Edit, Delete):
796
+ - "View" / "Details" → React Router `<Link to="/{role}/{module}-detail">`
797
+ - "Edit" → React Router `<Link to="/{role}/{module}-edit">`
798
+ - "Delete" → shadcn/ui `<Dialog>` confirm (no navigation, inline confirm)
799
+ - "Add New" / "Create" → React Router `<Link to="/{role}/{module}-create">`
800
+
801
+ 2. **Tabs within a page**:
802
+ - Use shadcn/ui `<Tabs>` component with `<TabsContent>` for inline tabs
803
+ - If tabs are separate page files, each tab header is a `<Link>` to the tab route
804
+
805
+ 3. **Header links**:
806
+ - Notification bell icon → React Router `<Link>` to `notifications`
807
+ - Notification dropdown "View all notifications" → React Router `<Link>` to `notifications`
808
+ - Locale dropdown options → no-op handler (static language switcher mockup)
809
+ - Dark mode toggle → `useTheme().setTheme()` (no navigation)
810
+ - Profile dropdown → React Router `<Link>` to `profile`
811
+ - Account dropdown → React Router `<Link>` to `account`
812
+ - Logout → plain `<a href="/">` (escapes the SPA to the hub landing page — a React
813
+ Router `<Link to="/">` would only reach the app's own root because of the basename)
814
+
815
+ 4. **Sidebar links**: React Router `<Link>` to correct module routes
816
+
817
+ 5. **Breadcrumb links**: shadcn/ui `<Breadcrumb>`
818
+ - Home → `<Link to="/{role}/home">`
819
+ - Module → `<Link to="/{role}/{module}">`
820
+ - Detail / current → `<BreadcrumbPage>` (non-interactive)
821
+
822
+ 6. **Pagination links**: shadcn/ui `<Pagination>` with React `useState` for page state — navigation is in-component state, not route-based
823
+
824
+ 7. **Back / Cancel buttons**: React Router `useNavigate()` or `<Link>` to the parent page
825
+
826
+ 8. **Images** (inline previews, thumbnails, etc.):
827
+ - Must open the full image in a **new tab** via `<a href="..." target="_blank" rel="noopener noreferrer">`
828
+ - Use placeholder image URLs like `https://placehold.co/800x600`
829
+
830
+ 9. **PDFs and documents** (download/view links):
831
+ - Must open in a **new tab** via `<a href="..." target="_blank" rel="noopener noreferrer">`
832
+ - Never render PDFs inline within the mockup
833
+
834
+ **Content guidelines:**
835
+ - Use placeholder/sample data that reflects the module context
836
+ - Include appropriate form fields based on NFRs and constraints
837
+ - Show the user story tags with their version as JSX comments for traceability
838
+ (e.g., `{/* USHM00012 [v1.0.1] */}`)
839
+ - All interactive elements use React state and shadcn/ui components
840
+ - Use Tailwind utility classes for layout and custom styling
841
+ - Use Lucide React icons (`import { IconName } from "lucide-react"`)
842
+
843
+ #### Common Pages Content
844
+
845
+ **home.tsx**: Dashboard home page showing:
846
+ - Welcome message with user role
847
+ - Summary stat `<Card>` grid (one per module: total count, recent activity)
848
+ - Recent activity `<Table>` with recent actions across modules
849
+
850
+ **profile.tsx**: User profile page showing:
851
+ - User `<Avatar>`, full name, email, role `<Badge>`
852
+ - Personal information `<Card>` (read-only display): Name, Email, Phone, Department
853
+ - "Edit Profile" `<Button>` (navigates to self since it's a mockup)
854
+
855
+ **account.tsx**: Account settings page showing:
856
+ - Change Password `<Card>` (current password, new password, confirm password `<Input>` fields)
857
+ - Notification Preferences `<Card>` (`<Switch>` toggles for email/SMS)
858
+ - Language/Locale `<Select>`
859
+ - Session Management `<Card>` (active sessions `<Table>`)
860
+
861
+ **notifications.tsx**: Notifications list page showing:
862
+ - shadcn/ui `<Tabs>`: All, Unread, Read
863
+ - List of notification `<Card>` items with: Lucide icon, title, message preview, timestamp, read/unread dot
864
+ - Mark all as read `<Button>`
865
+ - **Pagination** (MANDATORY): `<Pagination>` below the notification list, default 10 items per page.
866
+
867
+ #### Sub-Page Content
868
+
869
+ **{module}-detail.tsx**: Record detail page showing:
870
+ - Page title with record identifier
871
+ - Back `<Button>` (React Router `<Link>` to `{module}`)
872
+ - Detail `<Card>` panels with all relevant fields from user stories
873
+ - Action buttons: Edit `<Button>` (`<Link>` to `{module}-edit`), Delete `<Dialog>`, Back to List
874
+ - Related data sections if applicable
875
+ - If the entity has sub-entities, show them in shadcn/ui `<Tabs>` or sectioned `<Card>` groups
876
+
877
+ **{module}-create.tsx**: Create/add form page showing:
878
+ - Page title: "Add New {Entity}"
879
+ - `<Breadcrumb>`: Home > {Module} > Add New
880
+ - Form `<Card>` with all required fields derived from user stories
881
+ - Submit and Cancel `<Button>` (Cancel: `<Link>` to `{module}`)
882
+
883
+ **{module}-edit.tsx**: Edit form page showing:
884
+ - Page title: "Edit {Entity}"
885
+ - `<Breadcrumb>`: Home > {Module} > Edit
886
+ - Pre-filled form `<Card>` with sample data
887
+ - Save and Cancel `<Button>` (Cancel: `<Link>` to `{module}-detail` or `{module}`)
888
+
889
+ ### Step 6f: Build for Hub Serving (MANDATORY)
890
+
891
+ The hub serves this app from its built `dist/` folder — an unbuilt app appears on the hub
892
+ landing page as "Build required" with unclickable roles.
893
+
894
+ 1. Run in `<app_folder>/context/mockup/`:
895
+ ```bash
896
+ npm install
897
+ npm run build
898
+ ```
899
+ 2. Verify `dist/index.html` exists and its asset URLs start with `/{app_slug}/`.
900
+ 3. If the build fails or cannot run (e.g., no network for `npm install`), report it in the
901
+ output summary with the exact command the user must run — the hub landing page will show
902
+ the app as "Build required" until then.
903
+ 4. **Module-filtered runs**: rebuilding is still REQUIRED the previous `dist/` does not
904
+ contain the new/updated page components.
905
+
906
+ The Vite dev server (`npm run dev`) remains available for design iteration; it serves the
907
+ app at `http://localhost:5173/{app_slug}/` because of the `base` setting.
908
+
909
+ ### Step 7: Output Summary
910
+
911
+ After generation, print a summary:
912
+
913
+ ```
914
+ Mockup Generation Complete
915
+ ===========================
916
+ Application: {App Name} ({Initials})
917
+ Target Version: {version or "latest (all versions)"}
918
+ Module Filter: {module name or "all modules"}
919
+ Output: {path}/mockup/
920
+
921
+ Filtering Summary:
922
+ - User stories included: {count}
923
+ - User stories excluded (strikethrough): {count}
924
+ - User stories excluded (version filter): {count}
925
+ - User stories excluded (module filter): {count}
926
+ - NFRs/Constraints included: {count}
927
+ - NFRs/Constraints excluded: {count}
928
+
929
+ | Role | Pages | Page Folder |
930
+ |-----------------------|-------|--------------------------------------|
931
+ | Hub Administrator | 8 | src/pages/hub-administrator/ |
932
+ | Hub Operation Support | 6 | src/pages/hub-operation-support/ |
933
+
934
+ Files generated:
935
+ - Config: .gitignore, package.json, vite.config.ts, tsconfig.json, tailwind.config.js, etc.
936
+ - shadcn/ui: {N} component files in src/components/ui/
937
+ - Layout: app-layout.tsx, app-header.tsx, app-sidebar.tsx, app-footer.tsx, sidebar-config.ts
938
+ - Pages: {N} page component files
939
+ - MOCKUP.html (per-app screen index) + mockup-manifest.json
940
+ - Build: dist/ {built successfully | BUILD REQUIRED — run npm install && npm run build}
941
+ - Mockup Hub: {created at <root>/mockup | upgraded to v{N} | already present}
942
+
943
+ Total: {N} files
944
+
945
+ Quick Start
946
+ ===========
947
+ 1. cd <root>/mockup
948
+ 2. npm start (zero dependencies no npm install required)
949
+ 3. Open http://localhost:{port} in your browser (first unused port from 4000 —
950
+ the exact URL is printed on start)
951
+ - Landing page lists ALL applications and roles
952
+ - This app's screen index: http://localhost:{port}/{app_slug}
953
+ 4. Change port: the landing page's Port input, PORT=4100 npm start, or edit
954
+ <root>/mockup/mockup.config.json — or use Compound Context Studio's Mockup page
955
+ (topbar port input + Start/Stop Hub)
956
+
957
+ Design iteration (optional): cd {mockup folder path} && npm run dev
958
+ → http://localhost:5173/{app_slug}/
959
+ ```
960
+
961
+ ### Step 7b: Route Integrity Validation (MANDATORY)
962
+
963
+ Before finalizing output, perform a route integrity check across ALL generated files:
964
+
965
+ 1. **Scan every generated page and layout component** for all `<Link to="...">`, `useNavigate("...")`,
966
+ and `<a href="...">` references
967
+ 2. **Build a route registry**: map every route reference to the page component that handles it
968
+ 3. **Verify each React Router route** has a corresponding page component:
969
+ - `<Link to="/{role}/{page}">` → verify `src/pages/{role}/{page}.tsx` exists
970
+ - plain `<a href="/">` → acceptable for logout (hub landing); a `<Link to="/">` is NOT
971
+ equivalent (basename keeps it inside the app)
972
+ - `target="_blank"` links → acceptable for images, PDFs, external resources
973
+ - `href="#"` or dead-end `<Link>` → **NOT ALLOWED** — must be fixed
974
+ 4. **Verify App.tsx routes**: every page component must have a corresponding route definition
975
+ 5. **For any missing page file**, either:
976
+ - Generate the missing page component, OR
977
+ - Update the link to point to an existing route
978
+ 6. **Report any fixes** made during validation in the output summary
979
+
980
+ If any dead-end link is found in the final output, the generation is **incomplete**.
981
+
982
+ ## Changelog Append
983
+
984
+ After all mockup files are successfully generated, append an entry to `CHANGELOG.md` in the application folder (`<app_folder>/CHANGELOG.md`):
985
+
986
+ 1. Read `<app_folder>/CHANGELOG.md`. If it does not exist, create it with:
987
+ ```markdown
988
+ # Changelog
989
+
990
+ - This file tracks all skill executions by version for this application.
991
+ - The highest version recorded here is the current application version.
992
+ - Skills MUST NOT execute for a version lower than the highest version in this file.
993
+
994
+ ---
995
+ ```
996
+ 2. Search for a `## {version}` heading matching the current version.
997
+ 3. If the section **exists**: append a new row to its table.
998
+ 4. If the section **does not exist**: insert a new section after the `---` below the context header and before any existing `## vX.Y.Z` section (newest-first ordering), with a new table header and the first row.
999
+ 5. Row format: `| {YYYY-MM-DD} | {application_name} | mockgen-shadcn | {module or "All"} | Generated React + shadcn/ui mockup screens |`
1000
+ 6. **Never modify or delete existing rows.**
1001
+
1002
+ ## Important Rules
1003
+
1004
+ - **Module filter is additive, not destructive**: When `module:` is specified, only the named
1005
+ module's page components are written/overwritten. All other files (layout components, other module
1006
+ pages, config files) remain untouched. If the target module does not exist in PRD.md,
1007
+ stop and report available module names before doing any file writes.
1008
+ - **Version + module are independent axes**: Both may be combined freely. `module:Employer
1009
+ v1.0.2` means "generate Employer module pages as they exist at v1.0.2". Version filtering
1010
+ and module filtering each apply independently; a story must satisfy BOTH to be included.
1011
+ - **Base path is mandatory**: `vite.config.ts` MUST set `base: "/{app_slug}/"` and
1012
+ `main.tsx` MUST set `<BrowserRouter basename="/{app_slug}">` without them the built
1013
+ app cannot be served by the hub at `/{app_slug}`.
1014
+ - **No per-app server for viewing**: reviewers use ONLY the shared hub at `<root>/mockup/`
1015
+ (ensure it per Step 4d). The Vite dev server is for design iteration only.
1016
+ - **Manifest is mandatory**: every run writes/updates `mockup-manifest.json` without it
1017
+ the hub cannot route the app and the landing page shows it as not ready.
1018
+ - **Build is mandatory**: every run ends with `npm run build` (Step 6f) so the hub can
1019
+ serve `dist/`; an unbuilt app shows as "Build required" with unclickable roles.
1020
+ - **Root-relative links only in MOCKUP.html**: never hardcode `http://localhost:<port>`
1021
+ the hub port is user-configurable.
1022
+ - **ZERO dead links**: Every `<Link>`, `useNavigate()`, and `<a href>` in every file must resolve. No `href="#"`
1023
+ - **Pagination on every list** (MANDATORY): Every page that renders a `<Table>` of records MUST include
1024
+ shadcn/ui `<Pagination>` below it. Default page size is **10 items per page**. Applies to: module list
1025
+ pages, history/audit pages, notifications page, and any embedded sub-tables within detail pages
1026
+ that may grow unbounded. Use React `useState` for page state. Omitting pagination from any list
1027
+ is a generation error.
1028
+ - **Layout components for structure**: Header, footer, and sidebar are React components composed in a
1029
+ shared layout route — NOT duplicated inline in each page
1030
+ - **Page components are content only**: Role page files return only the page content JSX — the
1031
+ layout wrapper is handled by `AppLayout` via React Router `<Outlet>`
1032
+ - **React Router for navigation**: All in-app navigation uses `<Link>` or `useNavigate()` — no
1033
+ `window.location` assignments, no `<a href>` for internal routes
1034
+ - **shadcn/ui for all UI elements**: Buttons, inputs, tables, dialogs, dropdowns, badges, tabs,
1035
+ avatars, etc. MUST use the generated shadcn/ui components — not raw HTML elements
1036
+ - **Lucide React for all icons**: Use `import { IconName } from "lucide-react"` — no inline SVG,
1037
+ no icon CDN dependencies
1038
+ - **Images open in new tab**: Any image link or image view action uses `target="_blank"`
1039
+ - **PDFs open in new tab**: Any PDF/document view link uses `target="_blank" rel="noopener noreferrer"`
1040
+ - **MOCKUP.html links open in new tab**: All screen card links in the index use `target="_blank"`
1041
+ - No external image dependencies; use `https://placehold.co/` for placeholder images
1042
+ - Sidebar navigation must link between pages within the same role using React Router `<Link>`
1043
+ - Header navigation (notification, profile, account) links use React Router
1044
+ - Table action buttons (View, Edit, Add) use React Router navigation
1045
+ - Tabs within pages use shadcn/ui `<Tabs>` component
1046
+ - Back/Cancel buttons use React Router `useNavigate()` or `<Link>` to the parent page
1047
+ - Preserve traceability: include user story tags with version as JSX comments in each page
1048
+ (e.g., `{/* USHM00012 [v1.0.1] */}`)
1049
+ - Do not generate pages for modules that have no user stories for a given role
1050
+ - Common pages (home, profile, account, notifications) are generated for EVERY role
1051
+ - Use consistent color scheme from the design system via CSS variables and Tailwind config
1052
+ - The version displayed in footer should be the target version if specified, or the latest version
1053
+ found in PRD.md
1054
+ - **Strikethrough items MUST always be excluded** — lines wrapped in `~~` are deprecated/removed
1055
+ - **Version filtering**: When a target version is provided, only include items from sections
1056
+ with version tags <= target version
1057
+ - **Model-driven pages**: When a module model file exists at `model/{kebab-module}/model.md`,
1058
+ use the actual field definitions (field names, types, required/nullable, enums) for all
1059
+ form inputs, table columns, and detail panels. Generic placeholder field names are NOT
1060
+ acceptable when a model is available. See Step 1b and the "Model-Driven Field Usage" section.
1061
+ - **Enum accuracy**: Enum `<Select>` options must use the exact values from the model's Enum
1062
+ Definitions (Section 7), not inferred strings
1063
+ - **Constraint-aware sample data**: Sample values must respect field constraints noted in the
1064
+ model (e.g., use `MYS`, `BHR`, `MDV` for countryCode fields constrained by CONSHM018)
1065
+ - **Report layouts**: When PRD.md contains report-related NFRs or user stories, generate
1066
+ standalone HTML report layout files in `public/reports/` subfolder. These are self-contained A4
1067
+ mockups (not React components) for stakeholder review of report structure before coding.
1068
+ Use actual module model fields for column headers and realistic sample data rows. See
1069
+ Step 3f for full report layout generation rules.
1070
+ - **Dark mode support**: All pages and components must support dark mode via next-themes and
1071
+ Tailwind `dark:` variant classes. shadcn/ui components handle this automatically through CSS variables.
1072
+ - **TypeScript**: All generated `.tsx` files must be valid TypeScript. Use proper type annotations
1073
+ for component props, state, and event handlers. Avoid `any` types.