@atlashub/smartstack-cli 2.5.3 → 2.6.1
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/business-analyse.html +4 -4
- package/.documentation/commands.html +2 -2
- package/.documentation/index.html +2 -2
- package/.documentation/js/app.js +2 -2
- package/dist/index.js +163 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/mcp-scaffolding/component.tsx.hbs +14 -14
- package/templates/mcp-scaffolding/controller.cs.hbs +6 -5
- package/templates/skills/_resources/docs-manifest-schema.md +3 -3
- package/templates/skills/_resources/mcp-validate-documentation-spec.md +6 -6
- package/templates/skills/apex/steps/step-04b-doc-sync.md +4 -4
- package/templates/skills/apex/steps/step-05-examine.md +1 -1
- package/templates/skills/apex/templates/04b-doc-sync.md +1 -1
- package/templates/skills/application/SKILL.md +33 -16
- package/templates/skills/application/steps/step-00-init.md +86 -3
- package/templates/skills/application/steps/step-01-navigation.md +34 -0
- package/templates/skills/application/steps/step-02-permissions.md +37 -0
- package/templates/skills/application/steps/step-03-roles.md +23 -2
- package/templates/skills/application/steps/step-03b-provider.md +251 -0
- package/templates/skills/application/steps/step-04-backend.md +75 -0
- package/templates/skills/application/steps/step-05-frontend.md +149 -10
- package/templates/skills/application/steps/step-06-migration.md +27 -15
- package/templates/skills/application/steps/step-07-tests.md +404 -0
- package/templates/skills/application/steps/step-08-documentation.md +137 -0
- package/templates/skills/application/templates-frontend.md +133 -26
- package/templates/skills/application/templates-seed.md +116 -0
- package/templates/skills/business-analyse/SKILL.md +1 -1
- package/templates/skills/business-analyse/questionnaire/07-ui.md +15 -0
- package/templates/skills/business-analyse/questionnaire/10-documentation.md +2 -2
- package/templates/skills/business-analyse/schemas/feature-schema.json +96 -7
- package/templates/skills/business-analyse/steps/step-03-specify.md +134 -5
- package/templates/skills/business-analyse/steps/step-05-handoff.md +61 -8
- package/templates/skills/business-analyse/templates/tpl-frd.md +1 -1
- package/templates/skills/business-analyse/templates-frd.md +8 -8
- package/templates/skills/business-analyse/templates-react.md +26 -26
- package/templates/skills/documentation/SKILL.md +6 -6
- package/templates/skills/documentation/data-schema.md +70 -44
- package/templates/skills/documentation/templates.md +6 -6
- package/templates/skills/ralph-loop/SKILL.md +1 -2
- package/templates/skills/ralph-loop/steps/step-01-task.md +1 -1
- package/templates/skills/ui-components/SKILL.md +33 -2
- package/templates/skills/ui-components/patterns/dashboard-chart.md +327 -0
- package/templates/skills/ui-components/style-guide.md +27 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: step-03b-provider
|
|
3
|
+
description: Generate IClientSeedDataProvider implementation for client projects
|
|
4
|
+
prev_step: steps/step-03-roles.md
|
|
5
|
+
next_step: steps/step-04-backend.md
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Step 3b: Client Seed Data Provider (Client Projects Only)
|
|
9
|
+
|
|
10
|
+
## CONDITION D'EXECUTION
|
|
11
|
+
|
|
12
|
+
> This step executes ONLY if `{seeding_strategy}` = "provider" (client project).
|
|
13
|
+
> If `{seeding_strategy}` = "hasdata", skip directly to step-04-backend.md.
|
|
14
|
+
|
|
15
|
+
## MANDATORY EXECUTION RULES
|
|
16
|
+
|
|
17
|
+
- ONLY execute for client projects (`{seeding_strategy}` = "provider")
|
|
18
|
+
- ALWAYS use factory methods (`NavigationModule.Create(...)`, etc.) - NEVER `new Entity()`
|
|
19
|
+
- ALWAYS implement idempotence (check existence before inserting)
|
|
20
|
+
- ALWAYS register the provider in DI
|
|
21
|
+
- ALWAYS consume the SeedData classes created in steps 01-03
|
|
22
|
+
|
|
23
|
+
## YOUR TASK
|
|
24
|
+
|
|
25
|
+
Generate the `IClientSeedDataProvider` implementation that wires the SeedData files
|
|
26
|
+
created in steps 01, 02, 03 into the SmartStack Core seeding pipeline.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## AVAILABLE STATE
|
|
31
|
+
|
|
32
|
+
From previous steps:
|
|
33
|
+
|
|
34
|
+
| Variable | Description |
|
|
35
|
+
|----------|-------------|
|
|
36
|
+
| `{level}` | context, application, module, or section |
|
|
37
|
+
| `{code}` | kebab-case identifier |
|
|
38
|
+
| `{full_path}` | Complete navigation path |
|
|
39
|
+
| `{labels}` | Object with fr, en, it, de |
|
|
40
|
+
| `{descriptions}` | Object with fr, en, it, de |
|
|
41
|
+
| `{icon}` | Lucide icon name |
|
|
42
|
+
| `{display_order}` | Numeric display order |
|
|
43
|
+
| `{navigation_guid}` | GUID of the navigation entity |
|
|
44
|
+
| `{permission_guids}` | GUIDs for generated permissions |
|
|
45
|
+
| `{project_type}` | "client" (guaranteed at this step) |
|
|
46
|
+
| `{seeding_strategy}` | "provider" (guaranteed at this step) |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## FILES TO GENERATE
|
|
51
|
+
|
|
52
|
+
### 1. The Provider Class
|
|
53
|
+
|
|
54
|
+
**Location:** `Infrastructure/Persistence/Seeding/{AppPascalName}SeedDataProvider.cs`
|
|
55
|
+
|
|
56
|
+
Where `{AppPascalName}` is derived from the application code (e.g., `free-bike` -> `FreeBike`).
|
|
57
|
+
|
|
58
|
+
**Pattern:**
|
|
59
|
+
|
|
60
|
+
```csharp
|
|
61
|
+
using Microsoft.EntityFrameworkCore;
|
|
62
|
+
using SmartStack.Application.Common.Interfaces;
|
|
63
|
+
using SmartStack.Domain.Navigation;
|
|
64
|
+
using SmartStack.Domain.Platform.Administration.Roles;
|
|
65
|
+
|
|
66
|
+
namespace {BaseNamespace}.Infrastructure.Persistence.Seeding;
|
|
67
|
+
|
|
68
|
+
/// <summary>
|
|
69
|
+
/// Seeds {AppLabel} navigation, permissions, and role-permission data
|
|
70
|
+
/// into the SmartStack Core schema at application startup.
|
|
71
|
+
/// Implements <see cref="IClientSeedDataProvider"/> for runtime seeding
|
|
72
|
+
/// (no Core migrations required).
|
|
73
|
+
/// </summary>
|
|
74
|
+
public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
|
|
75
|
+
{
|
|
76
|
+
public int Order => 100;
|
|
77
|
+
|
|
78
|
+
public async Task SeedNavigationAsync(ICoreDbContext context, CancellationToken ct)
|
|
79
|
+
{
|
|
80
|
+
// Check idempotence
|
|
81
|
+
var exists = await context.NavigationApplications
|
|
82
|
+
.AnyAsync(a => a.Code == "{app_code}", ct);
|
|
83
|
+
if (exists) return;
|
|
84
|
+
|
|
85
|
+
// 1. Retrieve the parent context ("business", "platform", etc.)
|
|
86
|
+
var parentContext = await context.NavigationContexts
|
|
87
|
+
.FirstAsync(c => c.Code == "{context_code}", ct);
|
|
88
|
+
|
|
89
|
+
// 2. Create the application
|
|
90
|
+
var app = NavigationApplication.Create(
|
|
91
|
+
parentContext.Id,
|
|
92
|
+
"{app_code}",
|
|
93
|
+
"{app_label_en}",
|
|
94
|
+
"{app_desc_en}",
|
|
95
|
+
"{app_icon}",
|
|
96
|
+
IconType.Lucide,
|
|
97
|
+
"/{context_code}/{app_code}",
|
|
98
|
+
{display_order});
|
|
99
|
+
context.NavigationApplications.Add(app);
|
|
100
|
+
await ((DbContext)context).SaveChangesAsync(ct);
|
|
101
|
+
|
|
102
|
+
// 3. Create modules
|
|
103
|
+
// Use GUIDs and data from {Module}NavigationSeedData.cs
|
|
104
|
+
foreach (var moduleData in GetModuleSeedEntries(app.Id))
|
|
105
|
+
{
|
|
106
|
+
var module = NavigationModule.Create(
|
|
107
|
+
moduleData.ApplicationId,
|
|
108
|
+
moduleData.Code,
|
|
109
|
+
moduleData.Label,
|
|
110
|
+
moduleData.Description,
|
|
111
|
+
moduleData.Icon,
|
|
112
|
+
IconType.Lucide,
|
|
113
|
+
moduleData.Route,
|
|
114
|
+
moduleData.DisplayOrder);
|
|
115
|
+
context.NavigationModules.Add(module);
|
|
116
|
+
}
|
|
117
|
+
await ((DbContext)context).SaveChangesAsync(ct);
|
|
118
|
+
|
|
119
|
+
// 4. Create translations (4 languages per entity)
|
|
120
|
+
// Use data from {Module}NavigationTranslationSeedData.cs
|
|
121
|
+
// ...
|
|
122
|
+
await ((DbContext)context).SaveChangesAsync(ct);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
public async Task SeedPermissionsAsync(ICoreDbContext context, CancellationToken ct)
|
|
126
|
+
{
|
|
127
|
+
// Check idempotence
|
|
128
|
+
var exists = await context.Permissions
|
|
129
|
+
.AnyAsync(p => p.Path == "{full_path}.*", ct);
|
|
130
|
+
if (exists) return;
|
|
131
|
+
|
|
132
|
+
// Retrieve modules by Code for FK resolution
|
|
133
|
+
// Use data from {Module}PermissionSeedData.cs
|
|
134
|
+
// Create via Permission.CreateForModule(...) and Permission.CreateWildcard(...)
|
|
135
|
+
// ...
|
|
136
|
+
await ((DbContext)context).SaveChangesAsync(ct);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public async Task SeedRolePermissionsAsync(ICoreDbContext context, CancellationToken ct)
|
|
140
|
+
{
|
|
141
|
+
// Check idempotence
|
|
142
|
+
var exists = await context.RolePermissions
|
|
143
|
+
.AnyAsync(rp => rp.Permission!.Path.StartsWith("{full_path}."), ct);
|
|
144
|
+
if (exists) return;
|
|
145
|
+
|
|
146
|
+
// Retrieve existing roles and created permissions
|
|
147
|
+
// Use data from {Module}RolePermissionSeedData.cs
|
|
148
|
+
// Create via RolePermission.Create(roleId, permissionId, "system")
|
|
149
|
+
// ...
|
|
150
|
+
await ((DbContext)context).SaveChangesAsync(ct);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Private helper methods fed by SeedData classes
|
|
154
|
+
// ...
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 2. DI Registration
|
|
159
|
+
|
|
160
|
+
Modify `Infrastructure/DependencyInjection.cs` of the client project:
|
|
161
|
+
|
|
162
|
+
```csharp
|
|
163
|
+
// Add using:
|
|
164
|
+
using SmartStack.Application.Common.Interfaces;
|
|
165
|
+
|
|
166
|
+
// In the registration method:
|
|
167
|
+
services.AddScoped<IClientSeedDataProvider, {AppPascalName}SeedDataProvider>();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## CRITICAL RULES
|
|
173
|
+
|
|
174
|
+
1. **Factory methods mandatory**: `NavigationModule.Create(...)`, `Permission.CreateForModule(...)`, `RolePermission.Create(...)` - NEVER `new Entity()`
|
|
175
|
+
2. **Idempotence**: Each Seed method checks existence before inserting
|
|
176
|
+
3. **SaveChangesAsync per group**: Navigation -> save -> Permissions -> save -> RolePermissions -> save
|
|
177
|
+
4. **Deterministic GUIDs**: Use IDs from SeedData classes (not Guid.NewGuid())
|
|
178
|
+
5. **Resolve FK by Code**: Parent modules are found by `Code`, not hardcoded GUID
|
|
179
|
+
6. **Order property**: Use `100` as default. If multiple providers exist, they run in Order sequence
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## EXECUTION SEQUENCE
|
|
184
|
+
|
|
185
|
+
### 1. Read SeedData files from steps 01-03
|
|
186
|
+
|
|
187
|
+
Identify all SeedData files created in previous steps:
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
Glob: **/Persistence/Seeding/Data/{Domain}/*SeedData.cs
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Expected files:
|
|
194
|
+
- `{Module}NavigationSeedData.cs` (from step 01)
|
|
195
|
+
- `{Module}NavigationTranslationSeedData.cs` (from step 01)
|
|
196
|
+
- `{Module}PermissionSeedData.cs` (from step 02)
|
|
197
|
+
- `{Module}RolePermissionSeedData.cs` (from step 03)
|
|
198
|
+
|
|
199
|
+
### 2. Generate Provider Class
|
|
200
|
+
|
|
201
|
+
Using the SeedData files as data sources, generate the `{AppPascalName}SeedDataProvider.cs` following the pattern above.
|
|
202
|
+
|
|
203
|
+
Adapt the template:
|
|
204
|
+
- Replace `{AppPascalName}` with the PascalCase application name
|
|
205
|
+
- Replace `{app_code}` with the kebab-case application code
|
|
206
|
+
- Replace `{context_code}` with the parent context code
|
|
207
|
+
- Fill in the actual navigation, permission, and role-permission creation logic
|
|
208
|
+
using the helper methods from the SeedData classes
|
|
209
|
+
|
|
210
|
+
### 3. Register in DI
|
|
211
|
+
|
|
212
|
+
Find and update `Infrastructure/DependencyInjection.cs`:
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
Glob: **/Infrastructure/DependencyInjection.cs
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Add the `IClientSeedDataProvider` registration.
|
|
219
|
+
|
|
220
|
+
### 4. Verify
|
|
221
|
+
|
|
222
|
+
Before proceeding to step-04, verify:
|
|
223
|
+
- [ ] Provider generated with 3 methods (SeedNavigationAsync, SeedPermissionsAsync, SeedRolePermissionsAsync)
|
|
224
|
+
- [ ] Registered in DI (`services.AddScoped<IClientSeedDataProvider, ...>()`)
|
|
225
|
+
- [ ] Consumes SeedData classes from steps 01-03
|
|
226
|
+
- [ ] Idempotent (check existence before insert)
|
|
227
|
+
- [ ] Uses factory methods (no `new Entity()`)
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## SUCCESS METRICS
|
|
232
|
+
|
|
233
|
+
- Provider class generated with all 3 seed methods
|
|
234
|
+
- DI registration added
|
|
235
|
+
- SeedData classes from steps 01-03 properly consumed
|
|
236
|
+
- All methods are idempotent
|
|
237
|
+
- Factory methods used throughout
|
|
238
|
+
- Proceeded to step-04-backend.md
|
|
239
|
+
|
|
240
|
+
## FAILURE MODES
|
|
241
|
+
|
|
242
|
+
- SeedData files not found from previous steps (return to step-01)
|
|
243
|
+
- DependencyInjection.cs not found (ask user for DI registration location)
|
|
244
|
+
- Missing IClientSeedDataProvider interface (verify SmartStack.Application reference)
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## NEXT STEP
|
|
249
|
+
|
|
250
|
+
After generating the provider and registering it in DI,
|
|
251
|
+
proceed to `./step-04-backend.md`
|
|
@@ -285,6 +285,80 @@ If MCP call fails:
|
|
|
285
285
|
|
|
286
286
|
---
|
|
287
287
|
|
|
288
|
+
## POST-GENERATION VERIFICATION (MANDATORY)
|
|
289
|
+
|
|
290
|
+
**Before proceeding to step-05, run these checks on ALL generated backend files:**
|
|
291
|
+
|
|
292
|
+
### Check 1: Backend Build (BLOCKING)
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
dotnet build {SolutionName}.sln --no-restore
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
IF build fails:
|
|
299
|
+
- Read the error output carefully
|
|
300
|
+
- Fix compilation errors in generated files (common: missing `using`, wrong namespace, type mismatch)
|
|
301
|
+
- Re-run build until it succeeds
|
|
302
|
+
- DO NOT proceed to step-05 until the backend builds successfully
|
|
303
|
+
|
|
304
|
+
### Check 2: DbSet Registration (BLOCKING)
|
|
305
|
+
|
|
306
|
+
Verify the entity DbSet is registered in the DbContext interface:
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
Search for: DbSet<{EntityName}>
|
|
310
|
+
In: **/I{DbContextName}.cs or **/{DbContextName}.cs
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
IF NOT found: Add the DbSet declaration immediately:
|
|
314
|
+
```csharp
|
|
315
|
+
public DbSet<{EntityName}> {EntityName}s => Set<{EntityName}>();
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Check 3: DI Registration (BLOCKING)
|
|
319
|
+
|
|
320
|
+
Verify the service is registered in the DI container:
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
Search for: I{EntityName}Service
|
|
324
|
+
In: **/DependencyInjection.cs
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
IF NOT found: Add the service registration immediately:
|
|
328
|
+
```csharp
|
|
329
|
+
services.AddScoped<I{EntityName}Service, {EntityName}Service>();
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Check 4: RequirePermission Attributes (BLOCKING)
|
|
333
|
+
|
|
334
|
+
Verify ALL controller actions have `[RequirePermission]` attributes:
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
Search for: [HttpGet], [HttpPost], [HttpPut], [HttpDelete]
|
|
338
|
+
In: **/Controllers/**/{EntityName}Controller.cs
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Each HTTP action MUST have a corresponding `[RequirePermission(Permissions.{Context}.{Application}.{Module}.{Action})]`.
|
|
342
|
+
IF any action is missing the attribute: Add it immediately.
|
|
343
|
+
|
|
344
|
+
### Check 5: Entity Configuration (BLOCKING)
|
|
345
|
+
|
|
346
|
+
Verify the EF Core configuration file exists and has correct structure:
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
Search for: {EntityName}Configuration
|
|
350
|
+
In: **/Persistence/Configurations/**/*Configuration.cs
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Verify:
|
|
354
|
+
- `builder.ToTable("{table_prefix}{EntityName}s")` uses the correct table prefix
|
|
355
|
+
- `builder.HasKey(e => e.Id)` is present
|
|
356
|
+
- `builder.HasIndex` is defined for unique fields (e.g., Code)
|
|
357
|
+
|
|
358
|
+
IF configuration is incomplete: Fix it before continuing.
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
288
362
|
## SUCCESS METRICS
|
|
289
363
|
|
|
290
364
|
- MCP scaffold_extension called successfully
|
|
@@ -293,6 +367,7 @@ If MCP call fails:
|
|
|
293
367
|
- NavRoute attribute included
|
|
294
368
|
- Entity seeding offered to user (SeedData.cs + DevDataSeeder if accepted)
|
|
295
369
|
- Entity info stored for frontend
|
|
370
|
+
- Post-generation verification passed (all 5 checks)
|
|
296
371
|
- Proceeded to step-05-frontend.md
|
|
297
372
|
|
|
298
373
|
## FAILURE MODES
|
|
@@ -89,7 +89,50 @@ Args:
|
|
|
89
89
|
|
|
90
90
|
This updates:
|
|
91
91
|
- `navRoutes.generated.ts` - Route registry
|
|
92
|
-
- `routes.tsx` - React Router configuration
|
|
92
|
+
- `routes.tsx` / `App.tsx` - React Router configuration
|
|
93
|
+
|
|
94
|
+
#### ⚠️ CRITICAL: Route Placement Inside Layout Wrapper
|
|
95
|
+
|
|
96
|
+
**BLOCKING RULE:** New routes MUST be added as **children** of the existing layout route for the target context. SmartStack layouts (`AdminLayout`, `BusinessLayout`, `UserLayout`) provide the shell (header with AvatarMenu, sidebar, navigation) via React Router's `<Outlet />`.
|
|
97
|
+
|
|
98
|
+
**If routes are placed OUTSIDE the layout wrapper, the entire shell (header, sidebar, AvatarMenu) will NOT render.**
|
|
99
|
+
|
|
100
|
+
| Context | Layout Route to find in App.tsx | Layout Component |
|
|
101
|
+
|---------|--------------------------------|------------------|
|
|
102
|
+
| `platform.*` | `<Route path="/platform" element={<AdminLayout />}>` | `AdminLayout` |
|
|
103
|
+
| `business.*` | `<Route path="/business" element={<BusinessLayout />}>` | `BusinessLayout` |
|
|
104
|
+
| `personal.*` | `<Route path="/personal/myspace" element={<UserLayout />}>` | `UserLayout` |
|
|
105
|
+
|
|
106
|
+
**Insertion rules:**
|
|
107
|
+
|
|
108
|
+
1. Open `App.tsx` (or `routes.tsx`)
|
|
109
|
+
2. Find the existing `<Route path="/{context}" element={<{Context}Layout />}>` block
|
|
110
|
+
3. Add the new routes **INSIDE** that block as children
|
|
111
|
+
4. Use **relative paths** (not absolute) since they are children of the context route
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
// ✅ CORRECT - Route added INSIDE the layout wrapper
|
|
115
|
+
<Route path="/business" element={<BusinessLayout />}>
|
|
116
|
+
{/* ... existing routes ... */}
|
|
117
|
+
<Route path="{application}/{module}" element={<{EntityName}Page />} />
|
|
118
|
+
</Route>
|
|
119
|
+
|
|
120
|
+
// ❌ FORBIDDEN - Route added OUTSIDE layout (AvatarMenu will disappear!)
|
|
121
|
+
<Route path="/business/{application}/{module}" element={<{EntityName}Page />} />
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**For new applications (no existing layout route for the context):**
|
|
125
|
+
|
|
126
|
+
If the context doesn't have a layout route yet, create one wrapping all child routes:
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
<Route path="/{context}/{application}" element={<{Context}Layout />}>
|
|
130
|
+
<Route index element={<Navigate to="{default_module}" replace />} />
|
|
131
|
+
<Route path="{module}" element={<{EntityName}Page />} />
|
|
132
|
+
</Route>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Remember:** Also add the routes inside the tenant-prefixed block (`/t/:slug/...`) if it exists.
|
|
93
136
|
|
|
94
137
|
### 4. Generate i18n Files
|
|
95
138
|
|
|
@@ -165,19 +208,37 @@ Repeat for en, it, de with appropriate translations.
|
|
|
165
208
|
|
|
166
209
|
## ROUTING RULES
|
|
167
210
|
|
|
168
|
-
|
|
211
|
+
### Rule 1: Routes MUST be inside Layout wrappers
|
|
212
|
+
|
|
213
|
+
**CRITICAL:** All routes MUST be nested inside the appropriate context layout. This is what provides the SmartStack shell (header with AvatarMenu, sidebar, navigation).
|
|
169
214
|
|
|
170
215
|
```tsx
|
|
171
|
-
// ✅ CORRECT -
|
|
172
|
-
<Route path="
|
|
173
|
-
<Route
|
|
174
|
-
<Route path="products" element={<ProductsPage />} />
|
|
175
|
-
<Route path="orders" element={<OrdersPage />} />
|
|
216
|
+
// ✅ CORRECT - Inside BusinessLayout (shell renders: header + AvatarMenu + sidebar)
|
|
217
|
+
<Route path="/business" element={<BusinessLayout />}>
|
|
218
|
+
<Route path="sales/products" element={<ProductsPage />} />
|
|
176
219
|
</Route>
|
|
177
220
|
|
|
178
|
-
// ❌ FORBIDDEN -
|
|
179
|
-
<Route path="sales" element={<
|
|
180
|
-
|
|
221
|
+
// ❌ FORBIDDEN - Outside layout (NO shell, NO header, NO AvatarMenu!)
|
|
222
|
+
<Route path="/business/sales/products" element={<ProductsPage />} />
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Rule 2: Use nested routes (not flat)
|
|
226
|
+
|
|
227
|
+
**CRITICAL:** SmartStack requires NESTED routes within the layout:
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
// ✅ CORRECT - Nested routes inside layout
|
|
231
|
+
<Route path="/business" element={<BusinessLayout />}>
|
|
232
|
+
<Route path="sales">
|
|
233
|
+
<Route index element={<Navigate to="products" replace />} />
|
|
234
|
+
<Route path="products" element={<ProductsPage />} />
|
|
235
|
+
<Route path="orders" element={<OrdersPage />} />
|
|
236
|
+
</Route>
|
|
237
|
+
</Route>
|
|
238
|
+
|
|
239
|
+
// ❌ FORBIDDEN - Flat routes (cause redirect issues + bypass layout)
|
|
240
|
+
<Route path="/business/sales" element={<Navigate to="products" />} />
|
|
241
|
+
<Route path="/business/sales/products" element={<ProductsPage />} />
|
|
181
242
|
```
|
|
182
243
|
|
|
183
244
|
---
|
|
@@ -200,12 +261,88 @@ locales/
|
|
|
200
261
|
|
|
201
262
|
---
|
|
202
263
|
|
|
264
|
+
## POST-GENERATION VERIFICATION (MANDATORY)
|
|
265
|
+
|
|
266
|
+
**Before proceeding to step-06, run these checks on ALL generated frontend files:**
|
|
267
|
+
|
|
268
|
+
### 1. CSS Variables Check (BLOCKING)
|
|
269
|
+
|
|
270
|
+
Scan all generated `.tsx` files for hardcoded Tailwind colors:
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
FORBIDDEN patterns: bg-blue-, bg-red-, bg-green-, bg-gray-, bg-amber-,
|
|
274
|
+
text-blue-, text-red-, text-green-, text-gray-, text-amber-,
|
|
275
|
+
border-blue-, border-red-, border-green-, border-gray-
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
If ANY hardcoded color is found → **FIX IT** using CSS variables from style-guide.md before continuing.
|
|
279
|
+
|
|
280
|
+
### 2. API Client Check (BLOCKING)
|
|
281
|
+
|
|
282
|
+
Verify all API service files use the configured client:
|
|
283
|
+
- **CORRECT:** `import { api } from '@/services/api/apiClient'` or `import api from '../api'`
|
|
284
|
+
- **FORBIDDEN:** `import axios from 'axios'`
|
|
285
|
+
|
|
286
|
+
### 3. EntityCard Check
|
|
287
|
+
|
|
288
|
+
If a grid/card view is generated, verify it uses `EntityCard` component (not custom divs).
|
|
289
|
+
|
|
290
|
+
### 4. i18n Check (BLOCKING)
|
|
291
|
+
|
|
292
|
+
Verify exactly **4 language files** exist with identical key structures:
|
|
293
|
+
- `fr/{entityCode}.json`
|
|
294
|
+
- `en/{entityCode}.json`
|
|
295
|
+
- `it/{entityCode}.json`
|
|
296
|
+
- `de/{entityCode}.json`
|
|
297
|
+
|
|
298
|
+
### 5. Route Check (BLOCKING)
|
|
299
|
+
|
|
300
|
+
Verify routes are:
|
|
301
|
+
- **INSIDE** the Layout wrapper (`BusinessLayout`, `AdminLayout`, or `UserLayout`)
|
|
302
|
+
- **NESTED** (not flat)
|
|
303
|
+
- Following path convention: `/{context}/{application}/{module}`
|
|
304
|
+
|
|
305
|
+
### 6. States Check
|
|
306
|
+
|
|
307
|
+
Verify the list page includes:
|
|
308
|
+
- Loading state (spinner)
|
|
309
|
+
- Error state (icon + message + retry button)
|
|
310
|
+
- Empty state (icon + message)
|
|
311
|
+
|
|
312
|
+
### 7. TypeScript Build Check (BLOCKING)
|
|
313
|
+
|
|
314
|
+
Run the frontend type check to verify all generated files compile:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
cd web && npx tsc --noEmit 2>&1 | head -50
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
OR if the project uses a build script:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
cd web && npm run build 2>&1 | head -80
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
IF type errors exist **in generated files**: Fix them before proceeding.
|
|
327
|
+
Common issues: missing imports, wrong interface names, incorrect prop types, missing hook return types.
|
|
328
|
+
|
|
329
|
+
IF type errors exist **in other pre-existing files**: NON-BLOCKING. Note them but proceed.
|
|
330
|
+
|
|
331
|
+
**Focus only on errors in files generated by this step:**
|
|
332
|
+
- `pages/{context}/{application}/{module}/*.tsx`
|
|
333
|
+
- `services/api/{entityCode}Api.ts`
|
|
334
|
+
- `types/{entityName}.types.ts`
|
|
335
|
+
- `hooks/use{EntityName}*.ts`
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
203
339
|
## SUCCESS METRICS
|
|
204
340
|
|
|
205
341
|
- React component generated
|
|
206
342
|
- API client generated with types
|
|
207
343
|
- Routes updated (nested structure)
|
|
208
344
|
- i18n files created (4 languages)
|
|
345
|
+
- Post-generation verification passed (all 7 checks including TypeScript build)
|
|
209
346
|
- Proceeded to step-06-migration.md
|
|
210
347
|
|
|
211
348
|
## FAILURE MODES
|
|
@@ -213,6 +350,8 @@ locales/
|
|
|
213
350
|
- Component generation failed (check entity name)
|
|
214
351
|
- API client generation failed (check navRoute)
|
|
215
352
|
- Route configuration failed (check existing routes)
|
|
353
|
+
- Hardcoded colors detected → Fix before continuing
|
|
354
|
+
- Missing language files → Generate all 4 before continuing
|
|
216
355
|
|
|
217
356
|
---
|
|
218
357
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: step-06-migration
|
|
3
3
|
description: Create EF Core migration and finalize application setup
|
|
4
4
|
prev_step: steps/step-05-frontend.md
|
|
5
|
-
next_step:
|
|
5
|
+
next_step: steps/step-07-tests.md
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Step 6: Migration & Finalization
|
|
@@ -37,6 +37,29 @@ From previous steps:
|
|
|
37
37
|
|
|
38
38
|
## EXECUTION SEQUENCE
|
|
39
39
|
|
|
40
|
+
### 0. Pre-Migration Build Verification (BLOCKING)
|
|
41
|
+
|
|
42
|
+
**CRITICAL:** The backend MUST build successfully before creating a migration.
|
|
43
|
+
EF Core tools compile the project internally; a build failure produces confusing errors
|
|
44
|
+
that do not point to the actual source file.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
dotnet build {SolutionName}.sln --no-restore
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
IF build fails:
|
|
51
|
+
- Fix all compilation errors before proceeding
|
|
52
|
+
- Common causes at this stage:
|
|
53
|
+
- Missing DbSet registration (should have been caught in step-04 Check 2)
|
|
54
|
+
- Missing DI registration (should have been caught in step-04 Check 3)
|
|
55
|
+
- Circular references between generated services
|
|
56
|
+
- Missing package references (e.g., FluentValidation)
|
|
57
|
+
- Frontend changes that modified shared files
|
|
58
|
+
- Re-run build until successful
|
|
59
|
+
- DO NOT attempt migration creation on a broken build
|
|
60
|
+
|
|
61
|
+
**After build succeeds:** Continue to migration name suggestion.
|
|
62
|
+
|
|
40
63
|
### 1. Get Migration Name Suggestion
|
|
41
64
|
|
|
42
65
|
```
|
|
@@ -168,23 +191,12 @@ cd web && rm -rf node_modules/.cache && npm run dev
|
|
|
168
191
|
|
|
169
192
|
## SUCCESS METRICS
|
|
170
193
|
|
|
194
|
+
- Pre-migration build verification passed
|
|
171
195
|
- Migration name suggested via MCP
|
|
172
196
|
- Migration created and applied
|
|
173
197
|
- All checklist items verified
|
|
174
198
|
- Application functional
|
|
175
199
|
|
|
176
|
-
##
|
|
177
|
-
|
|
178
|
-
The /application skill workflow is complete. The user now has:
|
|
179
|
-
- Full navigation structure
|
|
180
|
-
- RBAC permissions
|
|
181
|
-
- Backend CRUD API
|
|
182
|
-
- Frontend components
|
|
183
|
-
- i18n support
|
|
184
|
-
- Database migration
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## END OF WORKFLOW
|
|
200
|
+
## NEXT STEP
|
|
189
201
|
|
|
190
|
-
|
|
202
|
+
After migration is applied and verified, proceed to `./step-07-tests.md` for test generation.
|