@atlashub/smartstack-cli 4.33.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.
@@ -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}/`