@atlashub/smartstack-cli 4.32.0 → 4.34.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.
Files changed (46) hide show
  1. package/.documentation/index.html +2 -2
  2. package/.documentation/init.html +358 -174
  3. package/dist/index.js +45 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/mcp-entry.mjs +271 -44
  6. package/dist/mcp-entry.mjs.map +1 -1
  7. package/package.json +1 -1
  8. package/templates/mcp-scaffolding/controller.cs.hbs +54 -128
  9. package/templates/project/README.md +19 -0
  10. package/templates/project/claude-md/api.CLAUDE.md.template +315 -0
  11. package/templates/project/claude-md/application.CLAUDE.md.template +181 -0
  12. package/templates/project/claude-md/domain.CLAUDE.md.template +125 -0
  13. package/templates/project/claude-md/infrastructure.CLAUDE.md.template +168 -0
  14. package/templates/project/claude-md/root.CLAUDE.md.template +339 -0
  15. package/templates/project/claude-md/web.CLAUDE.md.template +339 -0
  16. package/templates/skills/apex/SKILL.md +16 -10
  17. package/templates/skills/apex/_shared.md +1 -1
  18. package/templates/skills/apex/references/checks/architecture-checks.sh +154 -0
  19. package/templates/skills/apex/references/checks/backend-checks.sh +194 -0
  20. package/templates/skills/apex/references/checks/frontend-checks.sh +448 -0
  21. package/templates/skills/apex/references/checks/infrastructure-checks.sh +255 -0
  22. package/templates/skills/apex/references/checks/security-checks.sh +153 -0
  23. package/templates/skills/apex/references/checks/seed-checks.sh +536 -0
  24. package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +49 -192
  25. package/templates/skills/apex/references/post-checks.md +124 -2156
  26. package/templates/skills/apex/references/smartstack-api.md +160 -957
  27. package/templates/skills/apex/references/smartstack-frontend.md +134 -1022
  28. package/templates/skills/apex/references/smartstack-layers.md +12 -6
  29. package/templates/skills/apex/steps/step-00-init.md +81 -238
  30. package/templates/skills/apex/steps/step-03-execute.md +25 -752
  31. package/templates/skills/apex/steps/step-03a-layer0-domain.md +118 -0
  32. package/templates/skills/apex/steps/step-03b-layer1-seed.md +91 -0
  33. package/templates/skills/apex/steps/step-03c-layer2-backend.md +240 -0
  34. package/templates/skills/apex/steps/step-03d-layer3-frontend.md +300 -0
  35. package/templates/skills/apex/steps/step-03e-layer4-devdata.md +44 -0
  36. package/templates/skills/apex/steps/step-04-examine.md +70 -150
  37. package/templates/skills/application/references/frontend-i18n-and-output.md +2 -2
  38. package/templates/skills/application/references/frontend-route-naming.md +5 -1
  39. package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +49 -198
  40. package/templates/skills/application/references/frontend-verification.md +11 -11
  41. package/templates/skills/application/steps/step-05-frontend.md +26 -15
  42. package/templates/skills/application/templates-frontend.md +4 -0
  43. package/templates/skills/cli-app-sync/SKILL.md +2 -2
  44. package/templates/skills/cli-app-sync/references/comparison-map.md +1 -1
  45. package/templates/skills/controller/references/controller-code-templates.md +70 -67
  46. package/templates/skills/controller/references/mcp-scaffold-workflow.md +5 -1
@@ -0,0 +1,339 @@
1
+ # {{ProjectName}} - Claude Instructions
2
+
3
+ > **{{ProjectName}}** is built on the SmartStack platform (NuGet backend + npm frontend).
4
+ > It extends SmartStack via the **Extensions pattern**: own DbContext, own schema, own modules.
5
+ >
6
+ > 1. SmartStack provides the core platform (auth, navigation, multi-tenant, licensing)
7
+ > 2. {{ProjectName}} adds business-specific modules via `ExtensionsDbContext`
8
+ > 3. Pages are registered via `PageRegistry.register()` — DynamicRouter resolves routes automatically
9
+ > 4. Navigation is managed in DB (admin UI or seed data)
10
+
11
+ > **Priority**: Read sections in order. Earlier sections override later ones.
12
+
13
+ ---
14
+
15
+ ## 1. GOLDEN RULES (ALWAYS APPLY)
16
+
17
+ | # | Rule | Enforcement |
18
+ |---|------|-------------|
19
+ | 1 | **Domain layer has ZERO dependencies** | NEVER import from Application/Infrastructure/Api in Domain |
20
+ | 2 | **Route = Permission path** | `/module/section` → `module.section.*` |
21
+ | 3 | **All GUIDs MUST be random** | Generate via `[guid]::NewGuid()` - NEVER invent patterns |
22
+ | 4 | **SQL objects via SqlObjectHelper** | TVFs/views use `SqlObjectHelper` + embedded `.sql` files. No other raw SQL. |
23
+ | 5 | **Tables use domain prefix** | `ext_Orders`, `ext_Products` in `extensions` schema |
24
+ | 6 | **Auto BugFix Issue after /debug** | After completing a `/debug` skill, ALWAYS run `/bugfix-issue` |
25
+ | 7 | **One migration per feature branch** | Use `/efcore:migration` to manage |
26
+ | 8 | **All code MUST have unit tests** | Backend: xUnit + FluentAssertions. Frontend: Vitest. No PR without tests |
27
+
28
+ ---
29
+
30
+ ## 2. GIT RESTRICTIONS
31
+
32
+ ### NEVER Execute Directly (propose to user)
33
+ ```
34
+ git commit | git push | git merge | git rebase | git cherry-pick | git reset | git revert
35
+ ```
36
+
37
+ ### EXCEPTION: GitFlow Skills
38
+ When user invokes `/gitflow:*` commands → **FOLLOW the skill instructions** and execute git commands as defined by that skill.
39
+
40
+ | Context | Action |
41
+ |---------|--------|
42
+ | Manual git commands | **PROPOSE** only |
43
+ | `/gitflow:*` skills | **FOLLOW skill** and execute |
44
+
45
+ **GitFlow Rule**: Skills define a workflow. Execute commands **as specified by the skill**, not as an automatic pipeline.
46
+
47
+ ### Allowed (read-only)
48
+ `git status` | `git log` | `git diff` | `git branch` | `git fetch` | `git worktree list`
49
+
50
+ ---
51
+
52
+ ## 3. ARCHITECTURE
53
+
54
+ ```
55
+ {{ProjectName}}.sln
56
+ ├── src/
57
+ │ ├── {{ProjectName}}.Domain → Business logic (NO dependencies)
58
+ │ ├── {{ProjectName}}.Application → CQRS, use cases (→ Domain)
59
+ │ ├── {{ProjectName}}.Infrastructure → EF Core, repositories, external services (→ Domain, Application)
60
+ │ └── {{ProjectName}}.Api → REST entry point (→ Application, Infrastructure)
61
+ │ └── Controllers/ → Organized by Application/Module
62
+ ├── tests/
63
+ │ └── {{ProjectName}}.Tests.Unit → xUnit + FluentAssertions + Moq
64
+ └── web/{{ProjectNameLower}}-web → React + TypeScript + Vite
65
+ ├── tests/ → Vitest unit tests (NOT in src/)
66
+ └── src/
67
+ ├── pages/ → Organized by Application/Module
68
+ └── components/
69
+ ```
70
+
71
+ **Dependency flow**: `Domain ← Application ← Infrastructure ← Api`
72
+
73
+ > **Note**: Application references `Microsoft.EntityFrameworkCore` for `DbSet<T>` (used by `IExtensionsDbContext`),
74
+ > `IQueryable<T>` async extensions, and `QueryableExtensions`.
75
+ > This is an intentional architectural tradeoff — the `IExtensionsDbContext` interface remains the abstraction boundary.
76
+
77
+ ### Tech Stack
78
+ | Layer | Tech | Version |
79
+ |-------|------|---------|
80
+ | Runtime | .NET | 10.0 |
81
+ | ORM | EF Core | 10.0.1 |
82
+ | Database | SQL Server | Latest |
83
+ | Frontend | React + Vite | 19.x |
84
+ | Language | TypeScript | 5.x |
85
+
86
+ ---
87
+
88
+ ## 4. NAVIGATION HIERARCHY
89
+
90
+ ```
91
+ Application → Module → Section → Resource
92
+ ↓ ↓
93
+ myapp orders
94
+ │ │
95
+ └───────────┴──→ Route: /myapp/orders
96
+ Permission: myapp.orders.{action}
97
+ ```
98
+
99
+ > **Note**: Applications have an `ApplicationZone` property (enum: `Platform`, `Personal`, `Business`) used for UI layout grouping only. It does NOT appear in routes or permissions.
100
+
101
+ ### Permission Actions
102
+ `access` | `read` | `create` | `update` | `delete` | `export` | `import` | `approve` | `reject` | `assign` | `execute`
103
+
104
+ ### Adding Navigation
105
+ 1. Add HasData in `Navigation*Configuration.cs` (include `ComponentKey` for DynamicRouter)
106
+ 2. Run `/efcore:migration AddXxx`
107
+ 3. Register page in `componentRegistry.generated.ts` via `PageRegistry.register()`
108
+ 4. Add i18n in `navigation.json` (fr/en/it/de — all 4 languages)
109
+ 5. Create page component
110
+
111
+ ---
112
+
113
+ ## 5. DATABASE CONVENTIONS
114
+
115
+ ### Table Naming
116
+ Format: `extensions.{prefix}_{TableName}`
117
+
118
+ > **Note**: {{ProjectName}} uses the `extensions` schema, NOT the `core` schema (which belongs to SmartStack platform).
119
+
120
+ ### EF Core Config Pattern
121
+ ```csharp
122
+ builder.ToTable("ext_Orders", SchemaConstants.Extensions); // ✅ CORRECT
123
+ builder.ToTable("Orders", "ext"); // ❌ WRONG
124
+ ```
125
+
126
+ ### Migration Naming
127
+ Format: `extensions_v{version}_{sequence}_{Description}`
128
+
129
+ | Example |
130
+ |---------|
131
+ | `extensions_v1.0.0_001_CreateOrders` |
132
+ | `extensions_v1.0.0_002_AddOrderItems` |
133
+
134
+ > **Note**: Use `/efcore:migration` which calls MCP `suggest_migration` for automatic naming.
135
+
136
+ ---
137
+
138
+ ## 6. CODE CONVENTIONS
139
+
140
+ ### Naming
141
+ | Type | Pattern | Example |
142
+ |------|---------|---------|
143
+ | Entity | Singular PascalCase | `Order`, `Product` |
144
+ | Command | `{Action}{Entity}Command` | `CreateOrderCommand` |
145
+ | Query | `Get{Entity}Query` | `GetOrderByIdQuery` |
146
+ | Handler | `{Command/Query}Handler` | `CreateOrderCommandHandler` |
147
+ | DTO | `{Entity}Dto` | `OrderDto`, `OrderResponseDto` |
148
+
149
+ ### Backend Patterns
150
+ - **CQRS**: Commands/Queries in Application layer
151
+ - **Repository**: Interfaces in Application, impl in Infrastructure
152
+ - **DI**: Register in each layer's `DependencyInjection.cs`
153
+ - **Domain Events**: Raise in Domain, handle in Application
154
+
155
+ ### Frontend Patterns
156
+ - **Feature-based structure**: Group by feature
157
+ - **Custom hooks**: `use*.ts` for logic
158
+ - **API layer**: Centralized in `services/api/`
159
+ - **Placeholder pages**: Use `UnderDevelopment` component for WIP sections
160
+
161
+ ---
162
+
163
+ ## 7. COMMANDS
164
+
165
+ ```bash
166
+ # Build & Run
167
+ dotnet build
168
+ cd src/{{ProjectName}}.Api && dotnet run
169
+ cd web/{{ProjectNameLower}}-web && npm run dev
170
+
171
+ # Tests (MANDATORY before commit)
172
+ dotnet test tests/{{ProjectName}}.Tests.Unit
173
+ cd web/{{ProjectNameLower}}-web && npm test
174
+
175
+ # EF Core
176
+ /efcore:migration <Name> # Create migration (auto -o)
177
+ /efcore:db-deploy # Apply migrations
178
+ /efcore:db-status # Check status
179
+
180
+ # GitFlow
181
+ /gitflow commit # Commit with validation
182
+ /gitflow pr # Create PR
183
+ ```
184
+
185
+ ---
186
+
187
+ ## 8. API MANAGEMENT
188
+
189
+ Claude MAY start/stop API as needed.
190
+
191
+ ```bash
192
+ # Start (background)
193
+ cd src/{{ProjectName}}.Api && dotnet run &
194
+
195
+ # Stop
196
+ taskkill /F /IM {{ProjectName}}.Api.exe 2>nul || pkill -f {{ProjectName}}.Api
197
+ ```
198
+
199
+ **Rules**: Stop API when done. Stop before rebuild if files locked. Restart after code changes.
200
+
201
+ ---
202
+
203
+ ## 9. SECURITY RULES
204
+
205
+ ### GUID Generation (MANDATORY)
206
+ ```powershell
207
+ # ALWAYS generate via PowerShell
208
+ [guid]::NewGuid().ToString()
209
+ 1..10 | ForEach-Object { [guid]::NewGuid().ToString() } # Multiple
210
+ ```
211
+
212
+ **FORBIDDEN patterns**:
213
+ - Repeated: `a1a1a1a1-b1b1-...`
214
+ - Sequential: `00000001-0001-...`
215
+ - Predictable: `a1b2c3d4-1111-2222-...`
216
+
217
+ ### Why
218
+ - Predictable GUIDs enable enumeration attacks
219
+ - OWASP requires cryptographically random identifiers
220
+
221
+ ---
222
+
223
+ ## 10. ENTITY HOOKS
224
+
225
+ | Interface | When | Use Case |
226
+ |-----------|------|----------|
227
+ | `IBeforeCreate<T>` | Pre-create | Validation |
228
+ | `IAfterCreate<T>` | Post-commit | Notifications |
229
+ | `IBeforeUpdate<T>` | Pre-update | Validation |
230
+ | `IAfterUpdate<T>` | Post-commit | Notifications |
231
+ | `IBeforeDelete<T>` | Pre-delete | Can cancel |
232
+ | `IAfterDelete<T>` | Post-commit | Cleanup |
233
+
234
+ ```csharp
235
+ // Register in DependencyInjection.cs
236
+ services.AddScoped<IAfterCreate<Order>, OrderCreatedNotificationHook>();
237
+ ```
238
+
239
+ ---
240
+
241
+ ## 11. LOGGING
242
+
243
+ ### Backend (Serilog)
244
+ | Level | Usage |
245
+ |-------|-------|
246
+ | Critical | Security breaches, unauthorized access |
247
+ | Error | Unhandled exceptions |
248
+ | Warning | Validation failures |
249
+ | Information | HTTP requests, user actions |
250
+ | Debug | SQL queries (dev only) |
251
+
252
+ ### Frontend
253
+ ```typescript
254
+ import { logService } from '@/services/logging/logService';
255
+ logService.logError(error, 'ComponentName');
256
+ logService.logCritical(error, 'ComponentName'); // Immediate send
257
+ ```
258
+
259
+ ---
260
+
261
+ ## 12. TESTING (MANDATORY)
262
+
263
+ ### Rule
264
+ **Every new feature, entity, service, or utility MUST have corresponding unit tests.** No pull request should be merged without tests.
265
+
266
+ ### Backend Tests (xUnit v3 + FluentAssertions 8.x + Moq)
267
+
268
+ | Layer | What to Test | Location |
269
+ |-------|-------------|----------|
270
+ | Domain | Entity creation, validation, state transitions | `tests/{{ProjectName}}.Tests.Unit/Domain/` |
271
+ | Application | Behaviors, mappings, DTOs | `tests/{{ProjectName}}.Tests.Unit/Application/` |
272
+ | Infrastructure | Services (JWT, FileStorage, etc.) | `tests/{{ProjectName}}.Tests.Unit/Services/` |
273
+ | API | Controller responses, authorization | `tests/{{ProjectName}}.Tests.Unit/Controllers/` |
274
+
275
+ ```bash
276
+ dotnet test tests/{{ProjectName}}.Tests.Unit
277
+ ```
278
+
279
+ **Conventions:**
280
+ - Test file naming: `{ClassName}Tests.cs`
281
+ - Use factory methods (private constructors) - NEVER `new Entity { ... }`
282
+ - Use `Guid.NewGuid()` for all Guid parameters - NEVER hardcode or use strings
283
+
284
+ **FluentAssertions 8.x Gotchas:**
285
+ - DateTime: `BeOnOrAfter()` / `BeBefore()` / `BeCloseTo(expected, TimeSpan.FromSeconds(5))` - NOT `BeGreaterThan()`
286
+ - Collections: `HaveCount(n)` - NOT `HaveLength(n)`
287
+ - String length: `content.Length.Should().BeGreaterThan(n)` - NOT `HaveLengthGreaterThan()`
288
+ - Nullable: use `.Value` explicitly
289
+ - `WithMessage("*keyword*")` wildcard OK - but do NOT pass `StringComparison` parameter
290
+
291
+ **Domain Entity Test Pattern:**
292
+ ```csharp
293
+ [Fact]
294
+ public void Create_WithValidData_SetsAllProperties()
295
+ {
296
+ var before = DateTime.UtcNow;
297
+ var entity = Entity.Create("name", "value");
298
+ entity.Name.Should().Be("name");
299
+ entity.CreatedAt.Should().BeOnOrAfter(before);
300
+ entity.Id.Should().NotBeEmpty();
301
+ }
302
+
303
+ [Fact]
304
+ public void Create_WithEmptyName_ThrowsDomainException()
305
+ {
306
+ var act = () => Entity.Create("", "value");
307
+ act.Should().Throw<DomainException>().WithMessage("*name*");
308
+ }
309
+ ```
310
+
311
+ ### Frontend Tests (Vitest + Testing Library)
312
+
313
+ | Category | What to Test | Location |
314
+ |----------|-------------|----------|
315
+ | Utils | Pure functions | `web/{{ProjectNameLower}}-web/tests/utils/` |
316
+ | Services | Business logic | `web/{{ProjectNameLower}}-web/tests/services/` |
317
+ | Hooks | Custom hooks | `web/{{ProjectNameLower}}-web/tests/hooks/` |
318
+ | Components | UI with interactions | `web/{{ProjectNameLower}}-web/tests/components/` |
319
+
320
+ ```bash
321
+ cd web/{{ProjectNameLower}}-web && npm test
322
+ cd web/{{ProjectNameLower}}-web && npm run test:watch
323
+ ```
324
+
325
+ **Conventions:**
326
+ - Test file naming: `{fileName}.test.ts` or `{fileName}.test.tsx`
327
+ - Tests in `web/{{ProjectNameLower}}-web/tests/` (NOT in `src/`)
328
+ - Import with `@/` alias
329
+ - Use `vi.mock()` for external dependencies
330
+
331
+ ### When to Write Tests
332
+
333
+ | Trigger | Action |
334
+ |---------|--------|
335
+ | New domain entity | Add `{Entity}Tests.cs` with factory, validation, state machine tests |
336
+ | New utility function | Add `{util}.test.ts` covering edge cases |
337
+ | New service | Add `{Service}Tests.cs` or `{service}.test.ts` with mocked dependencies |
338
+ | Bug fix | Add regression test that reproduces the bug BEFORE fixing |
339
+ | New API endpoint | Add controller test with auth and response validation |
@@ -0,0 +1,339 @@
1
+ # {{ProjectName}} Web - React Frontend Memory
2
+
3
+ ## Purpose
4
+
5
+ React SPA frontend. Communicates with {{ProjectName}}.Api via REST + SignalR.
6
+
7
+ ## Tech Stack
8
+
9
+ | Technology | Version | Purpose |
10
+ |------------|---------|---------|
11
+ | React | ^18 / ^19 | UI library |
12
+ | TypeScript | ~5.9.3 | Type safety (strict mode) |
13
+ | Vite | ^7.2 | Build tool + dev server |
14
+ | React Router | ^6 / ^7 | Routing (lazy-loaded) |
15
+ | Context API | - | Client + server state |
16
+ | Axios | ^1.13 | HTTP client |
17
+ | Tailwind CSS | ^4.1 | Styling |
18
+ | i18next | ^25.7 | Internationalization |
19
+ | SignalR | ^10.0 | Real-time updates |
20
+ | Lucide React | ^0.562 | Icons |
21
+
22
+ ---
23
+
24
+ ## CRITICAL: Internationalization (i18n) - 4 Languages Required
25
+
26
+ ### Rules
27
+
28
+ - **CRITICAL**: Every page MUST use translations via `useTranslation()` hook
29
+ - **CRITICAL**: All user-visible text MUST be in translation files (fr, en, it, de)
30
+ - **NEVER** hardcode text strings in components
31
+ - **ALWAYS** add translations to ALL 4 locales: `fr/`, `en/`, `it/`, `de/`
32
+
33
+ ### Supported Languages
34
+
35
+ | Language | Code | Folder |
36
+ |----------|------|--------|
37
+ | French | `fr` | `locales/fr/` |
38
+ | English | `en` | `locales/en/` |
39
+ | Italian | `it` | `locales/it/` |
40
+ | German | `de` | `locales/de/` |
41
+
42
+ ### Structure
43
+
44
+ ```
45
+ src/i18n/
46
+ ├── config.ts → i18next configuration
47
+ └── locales/
48
+ ├── en/
49
+ │ ├── common.json → Common UI (buttons, labels, errors)
50
+ │ ├── navigation.json → Menu and navigation
51
+ │ └── {feature}.json → Feature-specific translations
52
+ ├── fr/
53
+ │ └── ... → Same structure as en/
54
+ ├── it/
55
+ │ └── ... → Same structure as en/
56
+ └── de/
57
+ └── ... → Same structure as en/
58
+ ```
59
+
60
+ ### Usage in Pages
61
+
62
+ ```tsx
63
+ import { useTranslation } from 'react-i18next';
64
+
65
+ export function ExamplePage() {
66
+ const { t } = useTranslation('feature'); // Specify namespace
67
+
68
+ return (
69
+ <div>
70
+ <h1>{t('pageTitle')}</h1>
71
+ <p>{t('description')}</p>
72
+ <button>{t('common:save')}</button> {/* Cross-namespace */}
73
+ </div>
74
+ );
75
+ }
76
+ ```
77
+
78
+ ### Adding New Translations
79
+
80
+ **ALWAYS add to ALL 4 languages** (en, fr, it, de) with the same structure.
81
+
82
+ ### Translation Keys Convention
83
+
84
+ - Use **dot notation** for nested keys: `orders.pageTitle`
85
+ - Use **camelCase** for key names
86
+ - Group by feature/section: `orders.table.headerName`
87
+ - Common actions in `common` namespace: `common:save`, `common:cancel`
88
+
89
+ ---
90
+
91
+ ## Structure
92
+
93
+ ```
94
+ {{ProjectNameLower}}-web/
95
+ ├── src/
96
+ │ ├── main.tsx → Entry point
97
+ │ ├── App.tsx → Root component + providers + DynamicRouter
98
+ │ ├── i18n/ → Internationalization
99
+ │ │ ├── config.ts → i18next setup
100
+ │ │ └── locales/ → Translation files (fr/en/it/de)
101
+ │ ├── services/ → API client layer
102
+ │ │ └── api/
103
+ │ │ ├── apiClient.ts → Axios instance + interceptors
104
+ │ │ └── {feature}Api.ts → Feature-specific API modules
105
+ │ ├── components/ → Shared & domain components
106
+ │ │ ├── ui/ → Base UI components (DataTable, Modal, etc.)
107
+ │ │ ├── layout/ → Layout components
108
+ │ │ ├── routing/ → Route guards + dynamic routing
109
+ │ │ └── {feature}/ → Feature-specific components
110
+ │ ├── pages/ → Page components
111
+ │ │ └── {application}/{module}/ → Organized by navigation hierarchy
112
+ │ ├── contexts/ → React Context providers
113
+ │ ├── hooks/ → Custom hooks
114
+ │ ├── layouts/ → Layout wrappers
115
+ │ ├── utils/ → Utility functions
116
+ │ ├── types/ → Global types
117
+ │ ├── routes/ → Route definitions
118
+ │ └── extensions/ → Extension system (PageRegistry)
119
+ ├── tests/ → Vitest tests (NOT in src/)
120
+ │ ├── utils/ → Pure utility tests
121
+ │ ├── components/ → Component tests
122
+ │ ├── hooks/ → Hook tests
123
+ │ └── services/ → Service tests
124
+ ├── vite.config.ts
125
+ ├── vitest.config.ts
126
+ ├── tsconfig.json
127
+ └── eslint.config.js
128
+ ```
129
+
130
+ ## Patterns
131
+
132
+ ### Page Template with i18n
133
+
134
+ ```tsx
135
+ // src/pages/{module}/{PageName}Page.tsx
136
+ import { useTranslation } from 'react-i18next';
137
+
138
+ export function ExamplePage() {
139
+ const { t } = useTranslation('feature');
140
+
141
+ return (
142
+ <div className="container mx-auto p-4">
143
+ <h1 className="text-2xl font-bold">{t('example.pageTitle')}</h1>
144
+ <p className="text-muted-foreground">{t('example.description')}</p>
145
+
146
+ <div className="mt-4 flex gap-2">
147
+ <button className="btn-primary">{t('common:save')}</button>
148
+ <button className="btn-secondary">{t('common:cancel')}</button>
149
+ </div>
150
+ </div>
151
+ );
152
+ }
153
+ ```
154
+
155
+ ### API Client
156
+
157
+ ```typescript
158
+ // src/services/api/apiClient.ts — uses Axios instance
159
+ import { api } from '@/services/api/apiClient';
160
+
161
+ // Request interceptors automatically add:
162
+ // - Authorization: Bearer {token}
163
+ // - X-Tenant-Slug: {currentTenantSlug}
164
+ // - Accept-Language: {i18nextLng}
165
+ // - X-Correlation-ID: {UUID}
166
+
167
+ // Usage in service files:
168
+ const orders = await api.get<Order[]>('/orders');
169
+ const order = await api.post<Order>('/orders', { name, amount });
170
+ ```
171
+
172
+ ### API Service File Pattern
173
+
174
+ ```typescript
175
+ // src/services/api/{feature}Api.ts
176
+ import { api } from './apiClient';
177
+
178
+ export interface OrderDto {
179
+ id: string;
180
+ name: string;
181
+ amount: number;
182
+ isActive: boolean;
183
+ }
184
+
185
+ export const orderApi = {
186
+ getAll: (search?: string) =>
187
+ api.get<OrderDto[]>('/orders', { params: { search } }),
188
+
189
+ getById: (id: string) =>
190
+ api.get<OrderDto>(`/orders/${id}`),
191
+
192
+ create: (data: Partial<OrderDto>) =>
193
+ api.post<OrderDto>('/orders', data),
194
+
195
+ update: (id: string, data: Partial<OrderDto>) =>
196
+ api.put<OrderDto>(`/orders/${id}`, data),
197
+
198
+ delete: (id: string) =>
199
+ api.delete(`/orders/${id}`),
200
+ };
201
+ ```
202
+
203
+ ### Custom Hook Pattern
204
+
205
+ ```typescript
206
+ // src/hooks/useOrderDetail.ts
207
+ import { useState, useCallback } from 'react';
208
+ import { orderApi, OrderDto } from '@/services/api/orderApi';
209
+
210
+ export function useOrderDetail(id: string) {
211
+ const [data, setData] = useState<OrderDto | null>(null);
212
+ const [loading, setLoading] = useState(false);
213
+ const [error, setError] = useState<string | null>(null);
214
+
215
+ const load = useCallback(async () => {
216
+ setLoading(true);
217
+ setError(null);
218
+ try {
219
+ const result = await orderApi.getById(id);
220
+ setData(result);
221
+ } catch (err: unknown) {
222
+ setError(err instanceof Error ? err.message : 'Unknown error');
223
+ } finally {
224
+ setLoading(false);
225
+ }
226
+ }, [id]);
227
+
228
+ return { data, loading, error, load };
229
+ }
230
+ ```
231
+
232
+ ### Context Provider Pattern
233
+
234
+ ```typescript
235
+ // src/contexts/ExampleContext.tsx
236
+ import { createContext, useContext, useState, type ReactNode } from 'react';
237
+
238
+ interface ExampleContextType {
239
+ value: string;
240
+ setValue: (v: string) => void;
241
+ }
242
+
243
+ const ExampleContext = createContext<ExampleContextType | null>(null);
244
+
245
+ export function ExampleProvider({ children }: { children: ReactNode }) {
246
+ const [value, setValue] = useState('');
247
+ return (
248
+ <ExampleContext.Provider value={{ value, setValue }}>
249
+ {children}
250
+ </ExampleContext.Provider>
251
+ );
252
+ }
253
+
254
+ export function useExample() {
255
+ const ctx = useContext(ExampleContext);
256
+ if (!ctx) throw new Error('useExample must be used within ExampleProvider');
257
+ return ctx;
258
+ }
259
+ ```
260
+
261
+ ## UI Styling Patterns
262
+
263
+ ### Semantic Color Usage
264
+
265
+ | Color | CSS Variables | Usage |
266
+ |-------|---------------|-------|
267
+ | `blue` | `--info-*` | Totals, informational, in progress |
268
+ | `green` | `--success-*` | Completed, resolved, active |
269
+ | `yellow` | `--warning-*` | Pending, on hold, warnings |
270
+ | `red` | `--error-*` | Errors, critical, failed |
271
+ | `neutral` | `--bg-secondary`, `--text-primary` | Inactive, closed, disabled |
272
+
273
+ ---
274
+
275
+ ## Commands
276
+
277
+ ```bash
278
+ # Development
279
+ npm run dev # Start dev server (port 6173)
280
+
281
+ # Build
282
+ npm run build # Production build
283
+
284
+ # Tests (MANDATORY before commit)
285
+ npm test # Run all tests
286
+ npm run test:watch # Watch mode
287
+ npm run test:coverage # Coverage report
288
+
289
+ # Lint
290
+ npm run lint # ESLint check
291
+ npm run typecheck # TypeScript type check
292
+ ```
293
+
294
+ ## Routing
295
+
296
+ ### Lazy Loading
297
+
298
+ All non-critical pages use `React.lazy()` for code splitting:
299
+
300
+ ```tsx
301
+ const OrdersPage = lazy(() =>
302
+ import('@/pages/{module}/OrdersPage').then(m => ({ default: m.OrdersPage }))
303
+ );
304
+ ```
305
+
306
+ ### Route Guards (Layered)
307
+
308
+ ```
309
+ Auth check → Tenant transition → Permission check → Render
310
+ ```
311
+
312
+ ---
313
+
314
+ ## Rules
315
+
316
+ 1. **CRITICAL: i18n Required** - ALL pages must use `useTranslation()` with all 4 language files (fr/en/it/de)
317
+ 2. **Pages in `pages/`**, components in `components/`** - organized by application/module
318
+ 3. **Custom hooks for logic** - extract API calls and state management from components into `hooks/`
319
+ 4. **Context API for global state** - use `contexts/` for auth, tenant, navigation, theme, etc.
320
+ 5. **Axios API client** - all HTTP calls via `services/api/apiClient.ts`, never raw `fetch()`
321
+ 6. **TypeScript strict mode** - no `any` types
322
+ 7. **Tailwind for styling** - no CSS files, no inline styles (`style={{}}`)
323
+ 8. **Functional components only** - no class components
324
+ 9. **Composition over inheritance** - use props and children
325
+ 10. **Tests in `tests/`** - NOT in `src/`, use Vitest + Testing Library
326
+
327
+ ## CRITICAL: Tabs Must Persist in URL
328
+
329
+ When creating a page with tabs, **ALWAYS** persist the active tab in the URL query params (`?tab=xxx`).
330
+ Use the `useTabNavigation` hook.
331
+
332
+ ## When Adding New Feature
333
+
334
+ 1. Create page in `pages/{application}/{module}/`
335
+ 2. Create components in `components/{feature}/`
336
+ 3. Create API service in `services/api/{feature}Api.ts`
337
+ 4. Create custom hooks in `hooks/use{Feature}.ts`
338
+ 5. Register page via `PageRegistry.register()`
339
+ 6. **CRITICAL**: Add translations to ALL 4 locales: `i18n/locales/{fr,en,it,de}/`