@atlashub/smartstack-cli 4.31.0 → 4.33.0
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.
- package/.documentation/commands.html +952 -116
- package/.documentation/index.html +2 -2
- package/.documentation/init.html +358 -174
- package/dist/mcp-entry.mjs +271 -44
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/mcp-scaffolding/controller.cs.hbs +54 -128
- package/templates/project/README.md +19 -0
- package/templates/skills/apex/SKILL.md +16 -10
- package/templates/skills/apex/_shared.md +1 -1
- package/templates/skills/apex/references/checks/architecture-checks.sh +154 -0
- package/templates/skills/apex/references/checks/backend-checks.sh +194 -0
- package/templates/skills/apex/references/checks/frontend-checks.sh +448 -0
- package/templates/skills/apex/references/checks/infrastructure-checks.sh +255 -0
- package/templates/skills/apex/references/checks/security-checks.sh +153 -0
- package/templates/skills/apex/references/checks/seed-checks.sh +536 -0
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +49 -192
- package/templates/skills/apex/references/parallel-execution.md +18 -5
- package/templates/skills/apex/references/post-checks.md +124 -2156
- package/templates/skills/apex/references/smartstack-api.md +160 -957
- package/templates/skills/apex/references/smartstack-frontend-compliance.md +23 -1
- package/templates/skills/apex/references/smartstack-frontend.md +134 -1022
- package/templates/skills/apex/references/smartstack-layers.md +12 -6
- package/templates/skills/apex/steps/step-00-init.md +81 -238
- package/templates/skills/apex/steps/step-03-execute.md +25 -751
- package/templates/skills/apex/steps/step-03a-layer0-domain.md +118 -0
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +91 -0
- package/templates/skills/apex/steps/step-03c-layer2-backend.md +240 -0
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +300 -0
- package/templates/skills/apex/steps/step-03e-layer4-devdata.md +44 -0
- package/templates/skills/apex/steps/step-04-examine.md +70 -150
- package/templates/skills/application/references/frontend-i18n-and-output.md +2 -2
- package/templates/skills/application/references/frontend-route-naming.md +5 -1
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +49 -198
- package/templates/skills/application/references/frontend-verification.md +11 -11
- package/templates/skills/application/steps/step-05-frontend.md +26 -15
- package/templates/skills/application/templates-frontend.md +4 -0
- package/templates/skills/cli-app-sync/SKILL.md +2 -2
- package/templates/skills/cli-app-sync/references/comparison-map.md +1 -1
- package/templates/skills/controller/references/controller-code-templates.md +70 -67
- package/templates/skills/controller/references/mcp-scaffold-workflow.md +5 -1
|
@@ -48,8 +48,8 @@ Display generated frontend code organized by category:
|
|
|
48
48
|
|
|
49
49
|
### Routes
|
|
50
50
|
- Updated `navRoutes.generated.ts`
|
|
51
|
-
- Generated `
|
|
52
|
-
-
|
|
51
|
+
- Generated `componentRegistry.generated.ts` (PageRegistry registrations)
|
|
52
|
+
- Navigation seed data has matching componentKeys
|
|
53
53
|
|
|
54
54
|
### i18n
|
|
55
55
|
- `locales/fr/{entityCode}.json`
|
|
@@ -50,8 +50,12 @@ Navigation seed data:
|
|
|
50
50
|
Route = "/human-resources/time-management" // From ToKebabCase()
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
PageRegistry keys and seed data ComponentKeys must use kebab-case:
|
|
54
54
|
```tsx
|
|
55
|
+
// v3.7+ (DynamicRouter): componentKey uses dot-separated kebab-case
|
|
56
|
+
PageRegistry.register('human-resources.time-management', lazy(() => ...));
|
|
57
|
+
|
|
58
|
+
// Legacy (applicationRoutes): paths use kebab-case
|
|
55
59
|
const applicationRoutes: ApplicationRouteExtensions = {
|
|
56
60
|
'human-resources': [ // ← kebab-case
|
|
57
61
|
{ path: 'time-management', element: <TimeManagementPage /> }, // ← kebab-case
|
|
@@ -1,168 +1,70 @@
|
|
|
1
|
-
# Frontend: Route
|
|
1
|
+
# Frontend: Route Registration with PageRegistry + DynamicRouter
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **v3.7+** — Replaces the legacy Pattern A (mergeRoutes) and Pattern B (JSX routes) patterns.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## How It Works
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
1. **Backend seed data** defines navigation entries with `ComponentKey` values
|
|
10
|
+
(e.g., `administration.users`, `support.tickets.list`)
|
|
11
|
+
2. **`componentRegistry.generated.ts`** registers all page components into `PageRegistry`
|
|
12
|
+
via `PageRegistry.register('key', lazy(() => import(...)))`
|
|
13
|
+
3. **DynamicRouter** fetches the menu API, matches each entry's `componentKey` to a
|
|
14
|
+
`PageRegistry` entry, and generates `<Route>` elements at runtime
|
|
15
|
+
4. **Implicit routes** (detail, create, edit) are resolved by convention:
|
|
16
|
+
- `*.detail` → `.../:id`
|
|
17
|
+
- `*.create` → `.../create`
|
|
18
|
+
- `*.edit` → `.../:id/edit`
|
|
10
19
|
|
|
11
|
-
|
|
20
|
+
No manual App.tsx wiring is needed.
|
|
12
21
|
|
|
13
22
|
---
|
|
14
23
|
|
|
15
|
-
##
|
|
24
|
+
## For SmartStack Core Pages
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
`componentRegistry.generated.ts` is auto-generated by MCP `scaffold_routes`:
|
|
18
27
|
|
|
19
28
|
```tsx
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
// Auto-generated — DO NOT EDIT
|
|
30
|
+
import { lazy } from 'react';
|
|
31
|
+
import { PageRegistry } from '@/extensions/PageRegistry';
|
|
32
|
+
|
|
33
|
+
PageRegistry.register('administration.users', lazy(() =>
|
|
34
|
+
import('@/pages/platform/administration/users/UsersPage').then(m => ({ default: m.UsersPage }))
|
|
35
|
+
));
|
|
36
|
+
PageRegistry.register('administration.users.detail', lazy(() =>
|
|
37
|
+
import('@/pages/platform/administration/users/UserDetailPage').then(m => ({ default: m.UserDetailPage }))
|
|
38
|
+
));
|
|
39
|
+
// ... ~100 registrations
|
|
23
40
|
```
|
|
24
41
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## Step 4a.5: Import Generated Route Extensions (if scaffold_routes was used)
|
|
28
|
-
|
|
29
|
-
If `scaffold_routes` generated `applicationRoutes.generated.tsx`, import and spread:
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
import { applicationRouteExtensions } from '@/routes/applicationRoutes.generated';
|
|
33
|
-
|
|
34
|
-
const applicationRoutes: ApplicationRouteExtensions = {
|
|
35
|
-
...applicationRouteExtensions,
|
|
36
|
-
// additional manual routes if needed...
|
|
37
|
-
};
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
If no generated file exists, add routes directly to the existing `applicationRoutes` object.
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Step 4b: Detect App.tsx Routing Pattern
|
|
45
|
-
|
|
46
|
-
Read App.tsx and detect which pattern is used:
|
|
47
|
-
|
|
48
|
-
### Pattern A: applicationRoutes Object
|
|
49
|
-
|
|
50
|
-
**If App.tsx contains:** `applicationRoutes: ApplicationRouteExtensions`
|
|
51
|
-
|
|
52
|
-
→ Add routes to `applicationRoutes.{application}[]` with **RELATIVE** paths (no leading `/`)
|
|
53
|
-
|
|
54
|
-
```tsx
|
|
55
|
-
const applicationRoutes: ApplicationRouteExtensions = {
|
|
56
|
-
'human-resources': [
|
|
57
|
-
// existing routes...
|
|
58
|
-
{ path: '{module_kebab}/{section_kebab}', element: <{EntityName}ListPage /> },
|
|
59
|
-
{ path: '{module_kebab}/{section_kebab}/create', element: <Create{EntityName}Page /> },
|
|
60
|
-
{ path: '{module_kebab}/{section_kebab}/:id', element: <{EntityName}DetailPage /> },
|
|
61
|
-
{ path: '{module_kebab}/{section_kebab}/:id/edit', element: <Create{EntityName}Page /> },
|
|
62
|
-
|
|
63
|
-
// Parent redirect routes (MANDATORY — prevents /login redirect on parent navigation)
|
|
64
|
-
{ path: '{module_kebab}', element: <Navigate to="{module_kebab}/{first_section_kebab}" replace /> },
|
|
65
|
-
{ path: '', element: <Navigate to="{first_module_kebab}/{first_section_kebab}" replace /> },
|
|
66
|
-
],
|
|
67
|
-
};
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Routes are automatically injected into BOTH standard (`/{application}/...`) and tenant-prefixed (`/t/:slug/{application}/...`) route trees by `mergeRoutes()`. No manual duplication needed.
|
|
71
|
-
|
|
72
|
-
#### RULE — Route Ordering in applicationRoutes
|
|
73
|
-
|
|
74
|
-
> **CRITICAL:** Routes within each application key MUST follow static-before-dynamic order.
|
|
75
|
-
> React Router matches top-to-bottom — a `:id` route placed before a `dashboard` route
|
|
76
|
-
> will match `dashboard` as an `id` parameter → 404.
|
|
77
|
-
|
|
78
|
-
```tsx
|
|
79
|
-
const applicationRoutes: ApplicationRouteExtensions = {
|
|
80
|
-
'human-resources': [
|
|
81
|
-
// ✅ CORRECT ORDER — static before dynamic
|
|
82
|
-
{ path: 'employees', element: <EmployeesPage /> },
|
|
83
|
-
{ path: 'employees/create', element: <CreateEmployeePage /> },
|
|
84
|
-
{ path: 'employees/dashboard', element: <EmployeeDashboardPage /> },
|
|
85
|
-
{ path: 'employees/:id', element: <EmployeeDetailPage /> },
|
|
86
|
-
{ path: 'employees/:id/edit', element: <EditEmployeePage /> },
|
|
87
|
-
|
|
88
|
-
// Redirect routes ALWAYS LAST
|
|
89
|
-
{ path: '', element: <Navigate to="employees" replace /> },
|
|
90
|
-
],
|
|
91
|
-
};
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
```tsx
|
|
95
|
-
// ❌ FORBIDDEN — :id before static routes
|
|
96
|
-
'human-resources': [
|
|
97
|
-
{ path: 'employees/:id', element: <EmployeeDetailPage /> }, // ← WRONG: catches 'dashboard'
|
|
98
|
-
{ path: 'employees/dashboard', element: <DashboardPage /> }, // ← NEVER REACHED
|
|
99
|
-
]
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
See `smartstack-layers.md` "RULE — Frontend Route Ordering" for the full ordering specification.
|
|
103
|
-
POST-CHECK C49 detects and BLOCKS this anti-pattern.
|
|
104
|
-
|
|
105
|
-
#### Custom Applications (Pattern A)
|
|
106
|
-
|
|
107
|
-
Custom application keys (any key **not** in the built-in list: `administration`, `support`, `user`, `api`) are fully supported in `applicationRoutes`. `mergeRoutes()` automatically:
|
|
108
|
-
|
|
109
|
-
1. Creates a new route entry wrapped in `<AppLayout />`
|
|
110
|
-
2. Injects it into **both** standard (`/{app-key}/...`) and tenant-prefixed (`/t/:slug/{app-key}/...`) trees, inside `TenantRouteWrapper > RouteGuard > LicenseGuard`
|
|
111
|
-
3. Generates automatic parent redirect routes (e.g., `employees` → `employees/management`)
|
|
112
|
-
|
|
113
|
-
No need to use Pattern B for custom applications — Pattern A handles everything automatically.
|
|
114
|
-
|
|
115
|
-
### Pattern B: JSX Routes
|
|
116
|
-
|
|
117
|
-
**If App.tsx contains:** `<Route path="/{application}" element={<{Layout} />}>`
|
|
118
|
-
|
|
119
|
-
→ Insert `<Route>` children inside the Layout wrapper:
|
|
120
|
-
|
|
42
|
+
Imported once in `main.tsx`:
|
|
121
43
|
```tsx
|
|
122
|
-
|
|
123
|
-
{/* ... existing routes ... */}
|
|
124
|
-
<Route path="{module_kebab}" element={<{EntityName}Page />} />
|
|
125
|
-
</Route>
|
|
44
|
+
import './extensions/componentRegistry.generated';
|
|
126
45
|
```
|
|
127
46
|
|
|
128
|
-
**ALSO add the same routes inside the tenant-prefixed block:**
|
|
129
|
-
|
|
130
|
-
Find `<Route path="/t/:slug">` and add the **same route entries** there.
|
|
131
|
-
|
|
132
47
|
---
|
|
133
48
|
|
|
134
|
-
##
|
|
49
|
+
## For Client SDK Pages
|
|
135
50
|
|
|
136
|
-
|
|
51
|
+
Clients register their own pages directly:
|
|
137
52
|
|
|
138
|
-
✅ Correct:
|
|
139
53
|
```tsx
|
|
140
|
-
|
|
141
|
-
|
|
54
|
+
import { PageRegistry } from '@atlashub/smartstack';
|
|
55
|
+
import { lazy } from 'react';
|
|
142
56
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
57
|
+
PageRegistry.register('rh.time.dashboard', lazy(() => import('./pages/TimeDashboard')));
|
|
58
|
+
PageRegistry.register('rh.time.list', lazy(() => import('./pages/TimeList')));
|
|
59
|
+
PageRegistry.register('rh.time.detail', lazy(() => import('./pages/TimeDetail')));
|
|
146
60
|
```
|
|
147
61
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
**NEVER remove the `applicationRoutes` parameter or the `ApplicationRouteExtensions` import.**
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## Step 4c: Application-to-Layout Mapping
|
|
156
|
-
|
|
157
|
-
| Application prefix | Layout Component | Route path |
|
|
158
|
-
|---------|------------------|------------|
|
|
159
|
-
| `administration.*` | `AppLayout` | `/administration` |
|
|
160
|
-
| `*` (business apps) | `AppLayout` | `/{application}` |
|
|
161
|
-
| `myspace.*` | `AppLayout` | `/myspace` |
|
|
62
|
+
Navigation entries are created in DB (via admin UI or seed data).
|
|
63
|
+
DynamicRouter does the junction automatically.
|
|
162
64
|
|
|
163
65
|
---
|
|
164
66
|
|
|
165
|
-
##
|
|
67
|
+
## Verification
|
|
166
68
|
|
|
167
69
|
```
|
|
168
70
|
Tool: mcp__smartstack__validate_frontend_routes
|
|
@@ -170,68 +72,17 @@ Args:
|
|
|
170
72
|
scope: "routes"
|
|
171
73
|
```
|
|
172
74
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
**CRITICAL:** Without parent redirects, navigating to an application or module URL (e.g., `/human-resources` or `/human-resources/employees`) will cause a redirect to `/login` because no route matches.
|
|
180
|
-
|
|
181
|
-
For each application, you MUST add:
|
|
182
|
-
|
|
183
|
-
1. **Application root redirect** — redirects `/{application}` to the first module/section:
|
|
184
|
-
```tsx
|
|
185
|
-
{ path: '', element: <Navigate to="{first_module}/{first_section}" replace /> }
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
2. **Module redirect** (if modules have sections) — redirects `/{application}/{module}` to first section:
|
|
189
|
-
```tsx
|
|
190
|
-
{ path: '{module}', element: <Navigate to="{module}/{first_section}" replace /> }
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
**Example:** For NavRoutes `human-resources.employees.management` and `human-resources.employees.departments`:
|
|
194
|
-
```tsx
|
|
195
|
-
{ path: 'employees', element: <Navigate to="employees/management" replace /> },
|
|
196
|
-
{ path: '', element: <Navigate to="employees/management" replace /> },
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
The `to` prop is resolved relative to the **parent route** (`/{application}`), so always use the full path from the application root.
|
|
200
|
-
|
|
201
|
-
> Note: `scaffold_routes` with `outputFormat: "applicationRoutes"` generates these redirects automatically.
|
|
202
|
-
|
|
203
|
-
---
|
|
204
|
-
|
|
205
|
-
## Forbidden Patterns (BOTH patterns)
|
|
206
|
-
|
|
207
|
-
- Adding application routes to `clientRoutes[]` with absolute paths — `clientRoutes` is ONLY for routes outside SmartStack applications (e.g., `/about`, `/pricing`)
|
|
208
|
-
- Adding routes OUTSIDE the Layout wrapper (shell will not render)
|
|
209
|
-
- Using `createBrowserRouter` (SmartStack uses `useRoutes()` + `mergeRoutes()`)
|
|
210
|
-
- Adding custom application routes to `clientRoutes[]` with absolute paths:
|
|
211
|
-
```tsx
|
|
212
|
-
// ❌ WRONG — bypasses RouteGuard + TenantLayout + AppLayout → /login redirect
|
|
213
|
-
const clientRoutes: RouteConfig[] = [
|
|
214
|
-
{ path: '/human-resources/employees/management', element: <EmployeePage /> },
|
|
215
|
-
];
|
|
216
|
-
```
|
|
217
|
-
Custom application routes MUST go in `applicationRoutes` with RELATIVE paths:
|
|
218
|
-
```tsx
|
|
219
|
-
// ✅ CORRECT
|
|
220
|
-
const applicationRoutes: ApplicationRouteExtensions = {
|
|
221
|
-
'human-resources': [
|
|
222
|
-
{ path: 'employees/management', element: <EmployeePage /> },
|
|
223
|
-
],
|
|
224
|
-
};
|
|
225
|
-
```
|
|
226
|
-
- Removing the `applicationRoutes` 2nd parameter from `mergeRoutes()` — this silently breaks ALL custom routes
|
|
75
|
+
Checks:
|
|
76
|
+
- `componentRegistry.generated.ts` exists
|
|
77
|
+
- Each backend NavRoute has a `PageRegistry.register()` call
|
|
78
|
+
- `main.tsx` imports the generated file
|
|
79
|
+
- Implicit route keys (*.detail, *.create, *.edit) exist for CRUD pages
|
|
227
80
|
|
|
228
81
|
---
|
|
229
82
|
|
|
230
|
-
##
|
|
83
|
+
## Legacy Patterns (DEPRECATED)
|
|
231
84
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
- [ ] Page components are imported at top of App.tsx
|
|
237
|
-
- [ ] `mcp__smartstack__validate_frontend_routes` returns no issues
|
|
85
|
+
> The Pattern A (`mergeRoutes(clientRoutes, applicationRoutes)`) and Pattern B
|
|
86
|
+
> (JSX `<Route>` in App.tsx) patterns are deprecated since v3.7.
|
|
87
|
+
> They still work but are not recommended for new development.
|
|
88
|
+
> See git history for the legacy documentation.
|
|
@@ -73,21 +73,21 @@ Verify exactly **4 language files** exist with identical key structures:
|
|
|
73
73
|
|
|
74
74
|
### 5. Route Check (BLOCKING)
|
|
75
75
|
|
|
76
|
-
Verify routes are:
|
|
77
|
-
- **
|
|
78
|
-
- **
|
|
76
|
+
Verify routes are registered:
|
|
77
|
+
- **v3.7+ (DynamicRouter):** PageRegistry.register() exists in componentRegistry.generated.ts
|
|
78
|
+
- **Legacy:** inside Layout wrapper, nested, correct path convention
|
|
79
79
|
- Following path convention: `/{application_kebab}/{module_kebab}` (kebab-case)
|
|
80
80
|
|
|
81
81
|
### 5b. Route Wiring Check (BLOCKING)
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
**v3.7+ (DynamicRouter):** Verify PageRegistry registration:
|
|
84
84
|
|
|
85
|
-
1. Open `
|
|
86
|
-
2. Verify
|
|
87
|
-
3. Verify
|
|
88
|
-
4.
|
|
85
|
+
1. Open `componentRegistry.generated.ts`
|
|
86
|
+
2. Verify new pages have `PageRegistry.register()` calls with matching componentKeys
|
|
87
|
+
3. Verify `main.tsx` imports `./extensions/componentRegistry.generated`
|
|
88
|
+
4. DynamicRouter resolves routes automatically — no App.tsx wiring needed
|
|
89
89
|
|
|
90
|
-
**
|
|
90
|
+
**Legacy:** Verify routes are wired into App.tsx (inside Layout wrapper + tenant block).
|
|
91
91
|
|
|
92
92
|
Run validation:
|
|
93
93
|
```
|
|
@@ -96,7 +96,7 @@ Args:
|
|
|
96
96
|
scope: "routes"
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
If
|
|
99
|
+
If validation returns issues, fix before proceeding.
|
|
100
100
|
|
|
101
101
|
### 5c. Route Kebab-Case Check (BLOCKING)
|
|
102
102
|
|
|
@@ -110,7 +110,7 @@ Scan App.tsx route paths for non-kebab-case segments:
|
|
|
110
110
|
|
|
111
111
|
**Verification steps:**
|
|
112
112
|
|
|
113
|
-
1. Extract all route
|
|
113
|
+
1. Extract all route keys from `componentRegistry.generated.ts` (v3.7+) or App.tsx (`applicationRoutes` / `<Route path="...">`)
|
|
114
114
|
2. For each multi-word path segment, verify it uses hyphens (kebab-case)
|
|
115
115
|
3. Cross-reference route paths with navigation seed data routes to ensure exact match
|
|
116
116
|
4. Single-word segments are fine as-is (e.g., `employees`, `products`)
|
|
@@ -103,23 +103,33 @@ Args:
|
|
|
103
103
|
options:
|
|
104
104
|
includeGuards: true
|
|
105
105
|
generateRegistry: true
|
|
106
|
-
outputFormat: "
|
|
106
|
+
outputFormat: "componentRegistry"
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
This generates:
|
|
110
|
-
- `navRoutes.generated.ts`
|
|
111
|
-
- `
|
|
110
|
+
- `navRoutes.generated.ts` — Route registry (NavRoute to API/web path mapping)
|
|
111
|
+
- `componentRegistry.generated.ts` — PageRegistry.register() calls for DynamicRouter
|
|
112
112
|
|
|
113
|
-
### 4.
|
|
113
|
+
### 4. Verify PageRegistry Registration
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
115
|
+
After `scaffold_routes` generates the files:
|
|
116
|
+
|
|
117
|
+
1. **Verify `componentRegistry.generated.ts`** contains `PageRegistry.register()` calls
|
|
118
|
+
for each new page component
|
|
119
|
+
2. **Verify `main.tsx`** imports `./extensions/componentRegistry.generated`
|
|
120
|
+
(this should already be present — check once)
|
|
121
|
+
3. **Verify navigation seed data** has `ComponentKey` values matching the registered keys
|
|
122
|
+
(e.g., seed Route="/administration/users" → ComponentKey="administration.users")
|
|
123
|
+
|
|
124
|
+
No manual App.tsx wiring is needed — DynamicRouter resolves routes automatically
|
|
125
|
+
from the API menu response + PageRegistry at runtime.
|
|
126
|
+
|
|
127
|
+
Verification:
|
|
128
|
+
```
|
|
129
|
+
Tool: mcp__smartstack__validate_frontend_routes
|
|
130
|
+
Args:
|
|
131
|
+
scope: "routes"
|
|
132
|
+
```
|
|
123
133
|
|
|
124
134
|
### 5-6. Verify i18n & Present Output
|
|
125
135
|
|
|
@@ -157,10 +167,11 @@ See [references/frontend-verification.md](../references/frontend-verification.md
|
|
|
157
167
|
|
|
158
168
|
- React component generated
|
|
159
169
|
- API client generated with types
|
|
160
|
-
-
|
|
161
|
-
-
|
|
170
|
+
- PageRegistry entries generated (componentRegistry.generated.ts)
|
|
171
|
+
- navRoutes.generated.ts updated
|
|
172
|
+
- Navigation seed data has matching componentKeys
|
|
162
173
|
- i18n files created (4 languages)
|
|
163
|
-
- Post-generation verification passed
|
|
174
|
+
- Post-generation verification passed
|
|
164
175
|
- Proceeded to step-06-migration.md
|
|
165
176
|
|
|
166
177
|
## FAILURE MODES
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> These templates generate React/TypeScript code for new applications/modules.
|
|
4
4
|
|
|
5
|
+
> **DEPRECATED (v3.7+):** Pattern A (mergeRoutes) and Pattern B (JSX Routes) below
|
|
6
|
+
> are replaced by PageRegistry.register() + DynamicRouter.
|
|
7
|
+
> See references/frontend-route-wiring-app-tsx.md for the current pattern.
|
|
8
|
+
|
|
5
9
|
---
|
|
6
10
|
|
|
7
11
|
## FRONTEND ARCHITECTURE
|
|
@@ -113,7 +113,7 @@ COMPARISON POINTS: {total}
|
|
|
113
113
|
[OK] index.css — @custom-variant dark present
|
|
114
114
|
[OK] DependencyInjection.Application — MediatR warning present
|
|
115
115
|
[OK] DependencyInjection.Infrastructure — SQL Server pattern matches
|
|
116
|
-
[SKIP] App.tsx — Intentionally different (mergeRoutes
|
|
116
|
+
[SKIP] App.tsx — Intentionally different (client uses mergeRoutes legacy or PageRegistry+DynamicRouter)
|
|
117
117
|
[SKIP] ExtensionsDbContext — Intentionally simplified
|
|
118
118
|
|
|
119
119
|
--------------------------------------------------------------------------------
|
|
@@ -161,7 +161,7 @@ These differences are **by design** and should always be marked `[SKIP]`:
|
|
|
161
161
|
|
|
162
162
|
| File/Pattern | Reason |
|
|
163
163
|
|---|---|
|
|
164
|
-
| `App.tsx` — `mergeRoutes`
|
|
164
|
+
| `App.tsx` — routing pattern (`mergeRoutes` legacy or `PageRegistry`+`DynamicRouter` v3.7+) | Client projects use their own routing entry point, not platform routing |
|
|
165
165
|
| `ExtensionsDbContext` | Intentionally simplified vs `CoreDbContext` — different architectural role |
|
|
166
166
|
| `api.ts` | Re-exports SmartStack client — wrapper pattern is correct |
|
|
167
167
|
| `DependencyInjection.Infrastructure.cs` | SQL Server connection pattern identical by design |
|
|
@@ -208,7 +208,7 @@ These comparisons should **always** return `[SKIP]` — differences are by desig
|
|
|
208
208
|
|
|
209
209
|
| Item | Reason |
|
|
210
210
|
|---|---|
|
|
211
|
-
| `App.tsx` | Client uses `mergeRoutes`
|
|
211
|
+
| `App.tsx` | Client uses `mergeRoutes` (legacy) or `PageRegistry`+`DynamicRouter` (v3.7+); app uses direct routing |
|
|
212
212
|
| `api.ts` | Client re-exports SmartStack client — wrapper pattern is correct |
|
|
213
213
|
| `ExtensionsDbContext` | Intentionally simplified vs `CoreDbContext` |
|
|
214
214
|
| `GlobalUsings.cs` | App has platform-wide usings; client has minimal set |
|