@atlashub/smartstack-cli 4.75.0 → 4.79.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 (81) hide show
  1. package/dist/index.js +87 -41
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/project/claude-md/root.CLAUDE.md.template +1 -1
  5. package/templates/skills/ai-prompt/SKILL.md +64 -0
  6. package/templates/skills/ai-prompt/references/ai-agent-modes.md +89 -0
  7. package/templates/skills/ai-prompt/references/eval-framework.md +129 -0
  8. package/templates/skills/apex/SKILL.md +2 -2
  9. package/templates/skills/apex/references/checks/frontend-checks.sh +123 -11
  10. package/templates/skills/apex/references/checks/seed-checks.sh +81 -7
  11. package/templates/skills/apex/references/core-seed-data.md +27 -22
  12. package/templates/skills/apex/references/domain-events-pattern.md +45 -0
  13. package/templates/skills/apex/references/entity-hooks-pattern.md +68 -0
  14. package/templates/skills/apex/references/licensing-enforcement.md +52 -0
  15. package/templates/skills/apex/references/post-checks.md +18 -1
  16. package/templates/skills/apex/references/smartstack-api.md +116 -5
  17. package/templates/skills/apex/references/smartstack-frontend.md +1 -1
  18. package/templates/skills/apex/references/smartstack-layers.md +6 -6
  19. package/templates/skills/apex/steps/step-00-init.md +1 -1
  20. package/templates/skills/apex/steps/step-03b-layer1-seed.md +26 -0
  21. package/templates/skills/apex/steps/step-03d-layer3-frontend.md +124 -2
  22. package/templates/skills/apex/steps/step-04-examine.md +163 -0
  23. package/templates/skills/apex-verify/SKILL.md +110 -0
  24. package/templates/skills/apex-verify/references/audit-rules.md +50 -0
  25. package/templates/skills/apex-verify/steps/step-00-init.md +119 -0
  26. package/templates/skills/apex-verify/steps/step-01-nav-audit.md +96 -0
  27. package/templates/skills/apex-verify/steps/step-02-crud-audit.md +127 -0
  28. package/templates/skills/apex-verify/steps/step-03-perm-audit.md +119 -0
  29. package/templates/skills/apex-verify/steps/step-04-route-audit.md +98 -0
  30. package/templates/skills/apex-verify/steps/step-05-report.md +110 -0
  31. package/templates/skills/application/references/contexts-cheatsheet.md +86 -0
  32. package/templates/skills/application/references/extensions-system.md +158 -0
  33. package/templates/skills/application/references/frontend-route-naming.md +7 -5
  34. package/templates/skills/application/references/frontend-verification.md +7 -5
  35. package/templates/skills/application/references/provider-template.md +4 -2
  36. package/templates/skills/application/references/smartstack-provider.md +118 -0
  37. package/templates/skills/application/references/themes-db-driven.md +484 -0
  38. package/templates/skills/application/templates-frontend.md +2 -2
  39. package/templates/skills/application/templates-seed.md +4 -2
  40. package/templates/skills/audit-route/references/routing-pattern.md +3 -1
  41. package/templates/skills/business-analyse/SKILL.md +3 -3
  42. package/templates/skills/business-analyse/_shared.md +37 -0
  43. package/templates/skills/business-analyse/react/components.md +30 -28
  44. package/templates/skills/business-analyse/references/03-json-schemas.md +11 -3
  45. package/templates/skills/business-analyse/references/03-post-check-validation.md +64 -0
  46. package/templates/skills/business-analyse/references/canonical-json-formats.md +7 -3
  47. package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
  48. package/templates/skills/business-analyse/references/validation-checklist.md +5 -5
  49. package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +15 -4
  50. package/templates/skills/business-analyse/steps/step-03-specify.md +162 -4
  51. package/templates/skills/business-analyse/steps/step-04-consolidate.md +211 -1
  52. package/templates/skills/business-analyse/templates-react.md +15 -15
  53. package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +3 -0
  54. package/templates/skills/business-analyse-html/html/ba-interactive.html +198 -16
  55. package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +64 -0
  56. package/templates/skills/business-analyse-html/html/src/scripts/05-render-specs.js +80 -11
  57. package/templates/skills/business-analyse-html/html/src/scripts/06-render-consolidation.js +2 -2
  58. package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +6 -3
  59. package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +46 -0
  60. package/templates/skills/business-analyse-html/references/02-feature-data-building.md +4 -2
  61. package/templates/skills/business-analyse-html/references/data-build.md +2 -0
  62. package/templates/skills/business-analyse-html/references/data-mapping.md +88 -21
  63. package/templates/skills/business-analyse-html/steps/step-02-build-data.md +6 -0
  64. package/templates/skills/business-analyse-html/steps/step-04-verify.md +92 -3
  65. package/templates/skills/business-analyse-quick/SKILL.md +807 -0
  66. package/templates/skills/{sketch → business-analyse-quick}/references/domain-heuristics.md +59 -3
  67. package/templates/skills/business-analyse-quick/references/prd-schema.md +268 -0
  68. package/templates/skills/business-analyse-review/references/review-data-mapping.md +6 -0
  69. package/templates/skills/cli-app-sync/SKILL.md +105 -4
  70. package/templates/skills/cli-app-sync/references/comparison-map.md +13 -0
  71. package/templates/skills/cli-app-sync/references/diff-entities.md +162 -0
  72. package/templates/skills/dev-start/SKILL.md +7 -7
  73. package/templates/skills/documentation/templates.md +16 -16
  74. package/templates/skills/migrate/SKILL.md +312 -0
  75. package/templates/skills/migrate/references/v3.34-to-v3.46.md +289 -0
  76. package/templates/skills/sketch/SKILL.md +15 -153
  77. package/templates/skills/smoke-generation/SKILL.md +313 -0
  78. package/templates/skills/ui-components/SKILL.md +11 -1
  79. package/templates/skills/ui-components/patterns/data-table.md +1 -1
  80. package/templates/skills/ui-components/references/component-catalog.md +82 -0
  81. package/templates/skills/workflow/SKILL.md +70 -1
@@ -0,0 +1,484 @@
1
+ # Themes & Branding (DB-driven, Tailwind v4) — Canonical Reference
2
+
3
+ > **Reference for `application`, `ui-components`, `apex` skills** — the COMPLETE token map any generated UI must respect. SmartStack v3.46+ is theme-driven: every color, radius, shadow, and font in a generated component MUST come from one of the CSS variables below. Hardcoded Tailwind colors break dark mode and per-tenant branding.
4
+
5
+ ## When This Reference Applies
6
+
7
+ - The client wants several themes (light/dark + custom)
8
+ - The client wants per-tenant branding (logo, favicon, colors)
9
+ - You generate UI code that needs to consume theme tokens
10
+ - The user asks "how do I add a custom theme", "how do I change the logo per tenant", "what about Tailwind colors"
11
+
12
+ ---
13
+
14
+ ## TL;DR — 5 canonical rules
15
+
16
+ 1. **Always use CSS variables for color/border/radius/shadow.** `bg-[var(--bg-card)]` — not `bg-white`.
17
+ 2. **Never use `dark:` prefix.** SmartStack toggles a `.dark` class on `<html>`; CSS vars adapt automatically.
18
+ 3. **Status badges use the 4 status token sets** (`--success-*`, `--warning-*`, `--error-*`, `--info-*`).
19
+ 4. **Action buttons use the accent tokens** (`--color-accent-50..950` or `--accent-*`).
20
+ 5. **Reusable component classes go in `@layer components`** (one definition, not duplicated in every component).
21
+
22
+ ---
23
+
24
+ ## Section 1 — CSS Variables (canonical token map)
25
+
26
+ All variables are defined on `:root` (light defaults) and overridden by `.dark` for dark mode. They are exported by `@atlashub/smartstack/theme.css` (auto-imported when you import the SDK).
27
+
28
+ ### 1.1 Backgrounds
29
+
30
+ | Variable | Light | Dark | Use case |
31
+ |---|---|---|---|
32
+ | `--bg-app` | `#fafafa` | `#161618` | App root background, `<body>` |
33
+ | `--bg-primary` | `#ffffff` | `#1c1c1f` | Main containers, cards, page bodies |
34
+ | `--bg-secondary` | `#f4f4f5` | `#232326` | Secondary zones, hover surfaces |
35
+ | `--bg-tertiary` | `#e4e4e7` | `#2a2a2e` | Tertiary layers, distinct from secondary |
36
+ | `--bg-card` | `#ffffff` | `#1c1c1f` | Explicit card wrappers |
37
+ | `--bg-hover` | `#f4f4f5` | `#27272a` | Hover state on surfaces |
38
+ | `--bg-active` | `#e4e4e7` | `#3f3f46` | Active / selected state |
39
+
40
+ ### 1.2 Text
41
+
42
+ | Variable | Light | Dark | Use case |
43
+ |---|---|---|---|
44
+ | `--text-primary` | `#18181b` | `#e4e4e7` | Body text, headings |
45
+ | `--text-secondary` | `#52525b` | `#a1a1aa` | Subtitles, helper text |
46
+ | `--text-tertiary` | `#71717a` | `#71717a` | Hints, metadata |
47
+ | `--text-muted` | `#a1a1aa` | `#52525b` | Very muted text |
48
+ | `--text-inverse` | `#fafafa` | `#e4e4e7` | Text on dark surface (fallback) |
49
+
50
+ ### 1.3 Borders
51
+
52
+ | Variable | Light | Dark | Use case |
53
+ |---|---|---|---|
54
+ | `--border-color` | `#e4e4e7` | `#3f3f46` | Standard border |
55
+ | `--border-subtle` | `#f4f4f5` | `#27272a` | Very light divider |
56
+ | `--border-strong` | `#d4d4d8` | `#52525b` | Strong divider |
57
+ | `--border-width` | `1px` | `1px` | Border thickness (overridable per theme) |
58
+
59
+ ### 1.4 Status (4 sets — canonical for badges/banners/toasts)
60
+
61
+ | Variable | Light | Dark | Use case |
62
+ |---|---|---|---|
63
+ | `--success-bg` | `#f0fdfa` | `rgba(20,184,166,0.15)` | Success badge / banner background |
64
+ | `--success-text` | `#0f766e` | `#5eead4` | Success label text |
65
+ | `--success-border` | `#99f6e4` | `rgba(20,184,166,0.3)` | Success border |
66
+ | `--success-dot` | `#14b8a6` | `#14b8a6` | Status dot (always vivid) |
67
+ | `--warning-bg` | `#fffbeb` | `rgba(245,158,11,0.15)` | Warning bg |
68
+ | `--warning-text` | `#b45309` | `#fbbf24` | Warning text |
69
+ | `--warning-border` | `#fde68a` | `rgba(245,158,11,0.3)` | Warning border |
70
+ | `--warning-dot` | `#f59e0b` | `#f59e0b` | Warning dot |
71
+ | `--error-bg` | `#fff1f2` | `rgba(244,63,94,0.15)` | Error bg |
72
+ | `--error-text` | `#be123c` | `#fb7185` | Error text |
73
+ | `--error-border` | `#fecdd3` | `rgba(244,63,94,0.3)` | Error border |
74
+ | `--error-dot` | `#f43f5e` | `#f43f5e` | Error dot |
75
+ | `--info-bg` | `#f0f9ff` | `rgba(14,165,233,0.15)` | Info bg |
76
+ | `--info-text` | `#0369a1` | `#7dd3fc` | Info text |
77
+ | `--info-border` | `#bae6fd` | `rgba(14,165,233,0.3)` | Info border |
78
+ | `--info-dot` | `#0ea5e9` | `#0ea5e9` | Info dot |
79
+
80
+ ### 1.5 Accent (dynamic — set by ThemeContext from `selectedPreset.accentColorKey`)
81
+
82
+ | Variable | Default light (indigo) | Default dark (indigo) | Use case |
83
+ |---|---|---|---|
84
+ | `--color-accent-50` | `#eef2ff` | `#1e1b4b` | Lightest accent (badge bg) |
85
+ | `--color-accent-100` | `#e0e7ff` | `#312e81` | |
86
+ | `--color-accent-200` | `#c7d2fe` | `#3730a3` | |
87
+ | `--color-accent-300` | `#a5b4fc` | `#4338ca` | |
88
+ | `--color-accent-400` | `#818cf8` | `#4f46e5` | |
89
+ | `--color-accent-500` | `#6366f1` | `#6366f1` | Primary accent (icons, links) |
90
+ | `--color-accent-600` | `#4f46e5` | `#818cf8` | Action button bg |
91
+ | `--color-accent-700` | `#4338ca` | `#a5b4fc` | Hover for action button |
92
+ | `--color-accent-800` | `#3730a3` | `#c7d2fe` | |
93
+ | `--color-accent-900` | `#312e81` | `#e0e7ff` | |
94
+ | `--color-accent-950` | `#1e1b4b` | `#eef2ff` | Darkest accent |
95
+ | `--accent-bg` | `#eef2ff` | `rgba(99,102,241,0.15)` | Accent badge / hover background (semantic alias) |
96
+ | `--accent-text` | `#4338ca` | `#a5b4fc` | Accent label text |
97
+ | `--accent-border` | `#c7d2fe` | `rgba(99,102,241,0.3)` | Accent border |
98
+
99
+ ### 1.6 Border-radius (overridable per theme)
100
+
101
+ | Variable | Default | Use case |
102
+ |---|---|---|
103
+ | `--radius-card` | `12px` | Card corners |
104
+ | `--radius-button` | `8px` | Button corners |
105
+ | `--radius-badge` | `8px` | Badge / chip corners |
106
+ | `--radius-input` | `8px` | Input field corners |
107
+ | `--radius-modal` | `16px` | Modal corners |
108
+ | `--radius-menu-item` | `8px` | Sidebar / menu item corners |
109
+
110
+ ### 1.7 Item palette (depends on `selectedPreset.itemPaletteKey`)
111
+
112
+ | Variable | neutral light | neutral dark | Use case |
113
+ |---|---|---|---|
114
+ | `--item-color-light` | `#ffffff` | `#1c1c1f` | Item lightest tint |
115
+ | `--item-color-medium` | `#f4f4f5` | `#27272a` | Item medium tint |
116
+ | `--item-color-dark` | `#e4e4e7` | `#3f3f46` | Item darkest tint |
117
+ | `--item-color-border` | `#d4d4d8` | `#52525b` | Item border |
118
+
119
+ ### 1.8 Typography & shadows
120
+
121
+ | Variable | Default | Use case |
122
+ |---|---|---|
123
+ | `--font-sans` | `'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif` | Default font stack |
124
+ | `--shadow-sm` | `0 1px 2px 0 rgba(0,0,0,0.05)` | Subtle elevation |
125
+ | `--shadow-md` | `0 4px 6px -1px rgba(0,0,0,0.1)` | Medium elevation |
126
+ | `--shadow-lg` | `0 10px 15px -3px rgba(0,0,0,0.1)` | Large elevation |
127
+ | `--shadow-xl` | `0 20px 25px -5px rgba(0,0,0,0.1)` | Extra-large elevation |
128
+
129
+ ### 1.9 Tooltip variants
130
+
131
+ | Variable | Light | Dark | Use case |
132
+ |---|---|---|---|
133
+ | `--tooltip-info-bg` | `#eff6ff` | `#1a2c3b` | Info tooltip bg |
134
+ | `--tooltip-success-bg` | `#f0fdf4` | `#1a3329` | Success tooltip bg |
135
+ | `--tooltip-warning-bg` | `#fefce8` | `#3b2f1a` | Warning tooltip bg |
136
+ | `--tooltip-error-bg` | `#fef2f2` | `#3b1c1e` | Error tooltip bg |
137
+
138
+ ---
139
+
140
+ ## Section 2 — TypeScript tokens
141
+
142
+ ### 2.1 `ACCENT_COLORS` (13 palettes)
143
+
144
+ Defined in `web/smartstack-web/src/config/themePresets.ts`. Each palette exposes 11 shades (50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950).
145
+
146
+ **Neutrals:** `slate`, `gray`, `zinc`, `stone`
147
+ **Vibrants:** `indigo` (default primary), `violet`, `blue`, `cyan`, `teal`, `emerald`, `amber`, `orange`, `rose`, `pink`
148
+
149
+ ```ts
150
+ ACCENT_COLORS: Record<string, { name: string; shades: ColorShades }>
151
+ ColorShades = { 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950 }
152
+ ```
153
+
154
+ The user-selected key is stored in `UiPreset.accentColorKey` and applied at runtime by `ThemeContext.applyAccent()`, which writes the 11 shades to `--color-accent-50..950`.
155
+
156
+ ### 2.2 `ITEM_PALETTES` (6 palettes)
157
+
158
+ | Key | Label FR | Use case |
159
+ |---|---|---|
160
+ | `neutral` | Neutre | Default — CRUD tables, cards |
161
+ | `ocean` | Océan | Soft blues |
162
+ | `forest` | Forêt | Natural greens |
163
+ | `sunset` | Coucher de soleil | Warm oranges/amber |
164
+ | `lavender` | Lavande | Elegant purples |
165
+ | `rose` | Rose | Soft pinks |
166
+
167
+ Each palette ships `light` and `dark` color sets `{ light, medium, dark, border }`.
168
+
169
+ ### 2.3 `BORDER_RADIUS_VALUES` (6 presets)
170
+
171
+ | Key | px | Label FR |
172
+ |---|---|---|
173
+ | `none` | `0px` | Carré |
174
+ | `small` | `4px` | Léger |
175
+ | `medium` | `8px` | Moyen (default for buttons/badges) |
176
+ | `large` | `12px` | Arrondi (default for cards) |
177
+ | `xlarge` | `16px` | Très arrondi (default for modals) |
178
+ | `xxlarge` | `24px` | Pill |
179
+
180
+ ### 2.4 `UiTheme` JSON shape (backend → frontend contract)
181
+
182
+ ```ts
183
+ interface UiTheme {
184
+ backgroundsJson: string; // { app, primary, secondary, tertiary, card, hover, active }
185
+ textColorsJson: string; // { primary, secondary, tertiary, muted, inverse }
186
+ borderColorsJson: string; // { default, subtle, strong, width: number }
187
+ statusColorsJson: string; // { success/warning/error/info: { bg, text, border, dot } }
188
+ defaultBorderRadiusJson: string; // { card, button, badge, input, modal, menuItem }
189
+ defaultAccentColorKey: string; // e.g. "indigo" | hex like "#ff00aa"
190
+ defaultItemPaletteKey: string; // "neutral" | "ocean" | ...
191
+ }
192
+ interface UiPreset {
193
+ accentColorKey: string; // overrides theme.defaultAccentColorKey
194
+ itemPaletteKey: string | null; // overrides theme.defaultItemPaletteKey
195
+ borderRadiusJson: string | null; // overrides theme.defaultBorderRadiusJson
196
+ backgroundOverrideJson: string | null;
197
+ }
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Section 3 — Tailwind v4 setup (mandatory in client projects)
203
+
204
+ ### 3.1 `package.json`
205
+
206
+ ```json
207
+ {
208
+ "dependencies": {
209
+ "tailwindcss": "^4.1.18",
210
+ "@tailwindcss/vite": "^4.1.18"
211
+ }
212
+ }
213
+ ```
214
+
215
+ ### 3.2 `vite.config.ts`
216
+
217
+ ```ts
218
+ import tailwindcss from '@tailwindcss/vite';
219
+ import react from '@vitejs/plugin-react';
220
+ import { defineConfig } from 'vite';
221
+
222
+ export default defineConfig({
223
+ plugins: [react(), tailwindcss()],
224
+ });
225
+ ```
226
+
227
+ ### 3.3 `index.css` (minimum)
228
+
229
+ ```css
230
+ @import "tailwindcss";
231
+ @source "../node_modules/@atlashub/smartstack";
232
+ @custom-variant dark (&:where(.dark, .dark *));
233
+
234
+ @theme {
235
+ --color-primary-50: #eef2ff;
236
+ --color-primary-100: #e0e7ff;
237
+ /* ... 9 shades total ... */
238
+ --color-primary-950: #1e1b4b;
239
+
240
+ --color-accent-50: #f5f3ff;
241
+ /* ... 9 shades ... */
242
+ --color-accent-950: #2e1065;
243
+
244
+ --font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
245
+ }
246
+
247
+ /* Then optionally @layer components { .card { ... } } for shared classes */
248
+ ```
249
+
250
+ > Tailwind v4 has **no `tailwind.config.ts`** — tokens go in `@theme {}` blocks inside CSS.
251
+
252
+ ### 3.4 Dark mode
253
+
254
+ ```css
255
+ :root { /* light defaults already declared */ }
256
+
257
+ .dark {
258
+ color-scheme: dark;
259
+ --bg-app: #161618;
260
+ --text-primary: #e4e4e7;
261
+ /* ... overrides for all variables ... */
262
+ }
263
+ ```
264
+
265
+ Toggle from JS:
266
+
267
+ ```ts
268
+ document.documentElement.classList.toggle('dark', wantDark);
269
+ ```
270
+
271
+ `ThemeContext` does this automatically based on the luminance of `--bg-app` — never write the toggle yourself in components.
272
+
273
+ ---
274
+
275
+ ## Section 4 — className conventions (constated patterns)
276
+
277
+ ### Pattern A — Tailwind utility + CSS var (most common)
278
+
279
+ ```tsx
280
+ <p className="text-[var(--text-secondary)]">{subtitle}</p>
281
+ <div className="bg-[var(--bg-primary)]/80 backdrop-blur-lg border-b border-[var(--border-color)]" />
282
+ <button className="bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white px-4 py-2 rounded-[var(--radius-button)]">Save</button>
283
+ ```
284
+
285
+ ### Pattern B — Custom @layer components class
286
+
287
+ ```css
288
+ @layer components {
289
+ .card {
290
+ background: var(--bg-card);
291
+ border: 1px solid var(--border-color);
292
+ border-radius: var(--radius-card);
293
+ box-shadow: var(--shadow-sm);
294
+ }
295
+ .badge-success {
296
+ background: var(--success-bg);
297
+ color: var(--success-text);
298
+ border: 1px solid var(--success-border);
299
+ border-radius: var(--radius-badge);
300
+ padding: 0.125rem 0.5rem;
301
+ font-size: 0.75rem;
302
+ }
303
+ }
304
+ ```
305
+
306
+ ```tsx
307
+ <div className="card">...</div>
308
+ <span className="badge-success">OK</span>
309
+ ```
310
+
311
+ ### Pattern C — Inline style for dynamic gradients
312
+
313
+ ```tsx
314
+ const accentGradient: React.CSSProperties = {
315
+ background: 'linear-gradient(to bottom right, var(--color-accent-500), var(--color-accent-600))',
316
+ };
317
+ <div style={accentGradient}>{initials}</div>
318
+ ```
319
+
320
+ ### Pattern D — Variant mapping (modal/banner color)
321
+
322
+ ```tsx
323
+ const VARIANT_CONFIG = {
324
+ danger: { iconColor: 'text-[var(--error-text)]', buttonColor: 'bg-[var(--error-text)] hover:opacity-90', iconBg: 'bg-[var(--error-bg)]' },
325
+ warning: { iconColor: 'text-[var(--warning-text)]', buttonColor: 'bg-[var(--warning-text)] hover:opacity-90', iconBg: 'bg-[var(--warning-bg)]' },
326
+ info: { iconColor: 'text-[var(--info-text)]', buttonColor: 'bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)]', iconBg: 'bg-[var(--info-bg)]' },
327
+ };
328
+ ```
329
+
330
+ ---
331
+
332
+ ## Section 5 — Migration map (Tailwind hardcoded → CSS var)
333
+
334
+ Use this table when fixing a generated file that violates the theme.
335
+
336
+ | Hardcoded Tailwind | SmartStack CSS var |
337
+ |---|---|
338
+ | `bg-white` | `bg-[var(--bg-card)]` |
339
+ | `bg-gray-50` | `bg-[var(--bg-primary)]` |
340
+ | `bg-gray-100` | `bg-[var(--bg-secondary)]` |
341
+ | `bg-gray-200` | `bg-[var(--bg-tertiary)]` |
342
+ | `text-gray-900` | `text-[var(--text-primary)]` |
343
+ | `text-gray-700` | `text-[var(--text-secondary)]` |
344
+ | `text-gray-500` | `text-[var(--text-tertiary)]` |
345
+ | `text-gray-400` | `text-[var(--text-muted)]` |
346
+ | `border-gray-200` | `border-[var(--border-color)]` |
347
+ | `border-gray-100` | `border-[var(--border-subtle)]` |
348
+ | `bg-blue-500/10` (info badge) | `bg-[var(--info-bg)]` |
349
+ | `text-blue-600` (info text) | `text-[var(--info-text)]` |
350
+ | `bg-blue-600` (action button) | `bg-[var(--color-accent-600)]` |
351
+ | `text-blue-600` (link) | `text-[var(--color-accent-600)]` |
352
+ | `bg-red-500/10` | `bg-[var(--error-bg)]` |
353
+ | `text-red-500` / `text-red-600` | `text-[var(--error-text)]` |
354
+ | `border-red-500/30` | `border-[var(--error-border)]` |
355
+ | `bg-yellow-500/10` / `bg-amber-500/10` | `bg-[var(--warning-bg)]` |
356
+ | `text-yellow-600` / `text-amber-600` | `text-[var(--warning-text)]` |
357
+ | `bg-green-500/10` | `bg-[var(--success-bg)]` |
358
+ | `text-green-600` | `text-[var(--success-text)]` |
359
+ | `bg-purple-500/10` | `bg-[var(--accent-bg)]` |
360
+ | `text-purple-600` | `text-[var(--accent-text)]` |
361
+ | `dark:bg-gray-900` | (remove — `.dark` class on root drives `--bg-app`) |
362
+ | `dark:text-white` | (remove — CSS vars adapt automatically) |
363
+
364
+ ### Status badge recipe (canonical, theme-aware)
365
+
366
+ ```tsx
367
+ // success / warning / error / info / accent / neutral — pick one set
368
+ <span className="px-2 py-0.5 rounded text-xs font-medium border bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]">
369
+ Approved
370
+ </span>
371
+ ```
372
+
373
+ ### HTTP method badge recipe (REST conventions)
374
+
375
+ | Method | Token set |
376
+ |---|---|
377
+ | `GET` | `--info-*` |
378
+ | `POST` | `--success-*` |
379
+ | `PUT` | `--warning-*` |
380
+ | `PATCH` | `--accent-*` |
381
+ | `DELETE` | `--error-*` |
382
+
383
+ ---
384
+
385
+ ## Section 6 — Branding assets (DB-driven)
386
+
387
+ ### Architecture (since v3.45)
388
+
389
+ `BrandingAsset` entity stores uploads (logo, favicon) per scope:
390
+
391
+ ```csharp
392
+ class BrandingAsset : BaseEntity, IAuditableEntity, IOptionalTenantEntity
393
+ {
394
+ public BrandingAssetType AssetType { get; } // Logo=0, LogoDark=1, Favicon=2
395
+ public BrandingAssetScope Scope { get; } // Platform=0, Tenant=1
396
+ public Guid? TenantId { get; }
397
+ public string StorageFileName { get; } // resolved via IFileStorageService
398
+ public string ContentType { get; }
399
+ public long FileSizeBytes { get; }
400
+ public string OriginalFileName { get; }
401
+ public int? Width { get; }
402
+ public int? Height { get; }
403
+ }
404
+ ```
405
+
406
+ `UiTheme` may reference assets via `LogoAssetId`, `LogoDarkAssetId`, `FaviconAssetId` (theme-level overrides).
407
+
408
+ ### Built-in seeds (immutable)
409
+
410
+ - `UiThemeSeedData.DarkThemeId` = `f1e8a3d2-4b7c-4e5f-9a2c-6d1b8e4f3c7a`
411
+ - `UiThemeSeedData.LightThemeId` = `c2d9b4e5-3a8f-4c6d-b1e7-5f2c9a8b3d4e`
412
+
413
+ These IDs MUST be referenced by const, never re-generated.
414
+
415
+ ### API endpoints
416
+
417
+ | Endpoint | Purpose |
418
+ |---|---|
419
+ | `GET /api/ui/themes` | List effective themes for current user |
420
+ | `GET /api/ui/themes/{id}` | Get one theme |
421
+ | `POST /api/ui/themes` | Create custom theme (admin) |
422
+ | `GET /api/ui/branding/{type}` | Resolve asset for current tenant + assetType |
423
+ | `POST /api/ui/branding` | Upload asset (admin) |
424
+
425
+ The frontend `ThemeContext` calls these at startup and after a tenant switch.
426
+
427
+ ### Frontend consumption
428
+
429
+ ```tsx
430
+ import { useTheme } from '@atlashub/smartstack';
431
+
432
+ function MyComponent() {
433
+ const { mode, selectedTheme, toggleMode, setTheme } = useTheme();
434
+ // selectedTheme.BackgroundsJson is parsed and applied to :root by ThemeSync.
435
+ // Components only consume var(--xxx) and never read the JSON directly.
436
+ }
437
+ ```
438
+
439
+ ---
440
+
441
+ ## Section 7 — DO / DON'T
442
+
443
+ | ✅ DO | ❌ DON'T |
444
+ |---|---|
445
+ | Read theme via `useTheme()` | Read `localStorage` for theme directly |
446
+ | Use CSS vars (`var(--bg-card)`, `var(--text-primary)`, …) | Hardcode `bg-blue-500`, `text-gray-900`, `bg-white` |
447
+ | Toggle dark mode via `useTheme().toggleMode()` | Use `dark:` Tailwind prefix |
448
+ | Reference `DarkThemeId`/`LightThemeId` as constants | Re-generate the built-in theme GUIDs |
449
+ | Upload branding via `/api/ui/branding` | Replace logo file directly on disk |
450
+ | Use `BrandingAssetScope.Tenant` for per-tenant logos | Hardcode logo path in `App.tsx` |
451
+ | Put reusable component classes in `@layer components` | Duplicate the same className across 10 components |
452
+ | Use status tokens (`--success-*`, …) for badges | Pick a random Tailwind shade per badge |
453
+ | Rely on `IFileStorageService` for asset URLs | Hardcode `/uploads/logo.png` paths |
454
+
455
+ ---
456
+
457
+ ## Section 8 — Validation hooks
458
+
459
+ Generated UI MUST pass `apex/references/checks/frontend-checks.sh` (POST-CHECK C9 / C9b / C9c) which now BLOCK on:
460
+
461
+ - `bg|text|border-(red|blue|green|gray|white|black|slate|zinc|neutral|stone|amber|yellow|orange|purple|indigo|violet|cyan|pink|emerald|rose|sky|teal|lime|fuchsia)-\d+` in `.tsx`
462
+ - `dark:` prefix on any utility class
463
+ - Hex colors `#xxxxxx` inside `className=[…]`
464
+
465
+ Before declaring a generation complete, run:
466
+
467
+ ```bash
468
+ bash templates/skills/apex/references/checks/frontend-checks.sh
469
+ ```
470
+
471
+ Expected: `0 BLOCKING`. If C9 / C9b / C9c trigger, use the migration table in Section 5 to fix.
472
+
473
+ ---
474
+
475
+ ## Reference source files (read-only — do NOT copy verbatim)
476
+
477
+ - `D:\01 - projets\SmartStack.app\features\IA-Workflow\web\smartstack-web\src\index.css` (CSS vars)
478
+ - `D:\01 - projets\SmartStack.app\features\IA-Workflow\web\smartstack-web\src\base.css` (custom @layer classes)
479
+ - `D:\01 - projets\SmartStack.app\features\IA-Workflow\web\smartstack-web\src\config\themePresets.ts` (ACCENT_COLORS, ITEM_PALETTES, BORDER_RADIUS)
480
+ - `D:\01 - projets\SmartStack.app\features\IA-Workflow\web\smartstack-web\src\contexts\ThemeContext.tsx` (apply* functions)
481
+ - `D:\01 - projets\SmartStack.app\features\IA-Workflow\src\SmartStack.Domain\Platform\Administration\UiConfiguration\UiTheme.cs`
482
+ - `D:\01 - projets\SmartStack.app\features\IA-Workflow\src\SmartStack.Domain\Platform\Administration\UiConfiguration\BrandingAsset.cs`
483
+
484
+ See also [smartstack-provider.md](smartstack-provider.md) for `ThemeProvider` wrapping order, [contexts-cheatsheet.md](contexts-cheatsheet.md) for `useTheme()` API.
@@ -114,7 +114,7 @@ export function $MODULE_PASCALDetailPage() {
114
114
  } finally {
115
115
  setLoading(false);
116
116
  }
117
- }, [$entityId, t]);
117
+ }, [$entityId]);
118
118
 
119
119
  useEffect(() => {
120
120
  loadData();
@@ -239,7 +239,7 @@ export function $MODULE_PASCALEditPage() {
239
239
  } finally {
240
240
  setLoading(false);
241
241
  }
242
- }, [$entityId, t]);
242
+ }, [$entityId]);
243
243
 
244
244
  useEffect(() => {
245
245
  loadData();
@@ -804,10 +804,12 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
804
804
  }
805
805
  else
806
806
  {
807
+ // v3.46+ signature : Zone removed. New flags isOpen + isPersonal at the END (optional, default false).
807
808
  app = NavigationApplication.Create(
808
- ApplicationZone.Business, "{app_code}", "{app_label_en}",
809
+ "{app_code}", "{app_label_en}",
809
810
  "{app_desc_en}", "{app_icon}", IconType.Lucide,
810
- "/{app_code}", {display_order});
811
+ "/{app_code}", {display_order},
812
+ isOpen: false, isPersonal: false);
811
813
  context.NavigationApplications.Add(app);
812
814
  await ((DbContext)context).SaveChangesAsync(ct);
813
815
 
@@ -56,7 +56,9 @@ Navigation and permissions are **entirely driven by the database**. The React fr
56
56
  - Sole routing engine — App.tsx reduced to providers + DynamicRouter
57
57
  - Handles: dynamic app routes, feature gating, auto-redirects, outlet tab routes, doc routes
58
58
  - `OUTLET_SECTIONS` config for tab-based pages
59
- - `getStaticAppRoutes()` for per-app legacy redirects (migration period only)
59
+ - `IMPLICIT_SUFFIXES` (24 suffixes : `.detail`, `.edit`, `.create`, `.new`, `.duplicate`, `.settings`, `.configure`, `.permissions`, `.members`, `.history`, `.logs`, `.analytics`, `.preview`, `.versions`, `.comments`, `.attachments`, `.audit`, `.export`, `.notifications`, `.schedule`, `.workflow`, `.summary`, `.test`, `.runs`, `.import`) auto-generate child routes (e.g. `/users/:id` for `.detail`) without seeding them in the menu
60
+ - **`mergeRoutes()` and `getStaticAppRoutes()` REMOVED in v3.7+** — clients must register pages via `PageRegistry.register()` only. Legacy migration helpers no longer exist.
61
+ - API-driven `isOpen` flag on each application bypasses permission checks (replaces hardcoded OPEN_APPS list). DTO field on `ApplicationMenuDto`.
60
62
 
61
63
  ### 4. useRouteConfig
62
64
 
@@ -38,7 +38,7 @@ Path A — FAST (small module, < 5 min) Path B — FULL (multi-module,
38
38
  │ │
39
39
  ▼ ▼
40
40
  ┌──────────────┐ ┌──────────────────┐
41
- │ /sketch │ 0-2 questions │ /business-analyse│ ~40 questions
41
+ │ /business-analyse-quick│ 0-2 questions │ /business-analyse│ ~40 questions
42
42
  │ (2 min) │ Pure inference │ (steps 00-04) │ JSON output
43
43
  └──────┬───────┘ └────────┬─────────┘
44
44
  │ Natural language prompt │ entities/rules/usecases.json
@@ -84,7 +84,7 @@ Path A — FAST (small module, < 5 min) Path B — FULL (multi-module,
84
84
 
85
85
  | From | To | Data | Format |
86
86
  |------|----|------|--------|
87
- | `/sketch` | `/apex` | Inferred design (entities, FK, labels, code patterns) | Natural language prompt |
87
+ | `/business-analyse-quick` | `/apex` | Inferred design (entities, FK, labels, code patterns) | Natural language prompt |
88
88
  | `/business-analyse` | `/business-analyse-design` | Entities, use cases, permissions | JSON (`entities.json`, `usecases.json`, `permissions.json`) |
89
89
  | `/business-analyse-design` | `/business-analyse-html` | Screen specs, wireframes, navigation | JSON (`screens.json`, `navigation.json`) |
90
90
  | `/business-analyse-html` | Client | Interactive review document | HTML (`ba-interactive.html`) |
@@ -104,7 +104,7 @@ Path A — FAST (small module, < 5 min) Path B — FULL (multi-module,
104
104
  | Cadrage/scope only | `/business-analyse-html` | Just regenerate HTML |
105
105
  | No corrections (approved) | `/business-analyse-handoff` | Proceed to code generation |
106
106
 
107
- > **Rule:** Path A (`/sketch` → `/apex`) is for quick, single-module additions. Path B (full cycle) is for multi-module projects or when the client needs a formal review process.
107
+ > **Rule:** Path A (`/business-analyse-quick` → `/apex`) is for quick, single-module additions. Path B (full cycle) is for multi-module projects or when the client needs a formal review process.
108
108
  > **PRD generation:** Handoff data and PRD files are generated by the `/business-analyse-handoff` skill.
109
109
 
110
110
  ## JSON Architecture — Granular files + Index
@@ -13,6 +13,8 @@
13
13
  (date validation, required fields) are the MINIMUM baseline. Domain rules
14
14
  (half-day absences, team capacity, carry-over limits, credit note linking,
15
15
  sequential invoice numbering) are what make an analysis valuable.
16
+ **Target: >= 2 domain-specific rules per business module (`domainSpecific: true`).**
17
+ Post-check C19 enforces this as a WARNING.
16
18
 
17
19
  4. **ALWAYS propose contextual views.** A workflow module without filtered
18
20
  views (open-requests, rejected, history, my-{entity}) is incomplete.
@@ -25,6 +27,41 @@
25
27
  "standard billing also includes credit notes, payment tracking, and
26
28
  dunning. Would you like to add these?" The user came to you for expertise.
27
29
 
30
+ 7. **NEVER compress or batch module processing in step-03.** Each module MUST be
31
+ processed sequentially in the main context. Sub-agents do NOT have access to the
32
+ JSON schema and WILL produce inconsistent formats. If there are 15+ modules, the
33
+ correct approach is to maintain sequential processing, NOT to "accelerate" by
34
+ batching. The ba-012 audit proved that batching reduced schema conformity from
35
+ 95% to 35% — the rework cost exceeded any time saved.
36
+
37
+ 8. **ALL generated JSON content values MUST be in `{language}`** (from metadata or config).
38
+ This applies to ALL text values written to JSON files:
39
+ - Entity `description`, attribute `description`, relationship `description`
40
+ - Business rule `name`, `statement`, `examples[].input`, `examples[].expected`
41
+ - Use case `name`, `mainScenario[]` steps, `alternativeScenarios[].steps[]`, `errorScenarios[].steps[]`, `preconditions[]`, `postconditions[]`
42
+ - Permission `description`, role `description`
43
+ - Lifecycle state `displayName`
44
+ - Section and resource labels
45
+
46
+ **Mixed-language content across modules is a BLOCKING quality defect.**
47
+ If `language == "fr"` : write "Créer une absence", NOT "Create an absence".
48
+ If `language == "en"` : write "Create an absence", NOT "Créer une absence".
49
+ Technical identifiers (entity names, field names, enum values, IDs) remain in English/PascalCase.
50
+
51
+ 9. **BR `examples[]` are TEST DATA, not documentation.** Each example must be a
52
+ concrete test case with the `{scenario, given, when, then}` format:
53
+ - `given`: object with `Entity.field: concreteValue` pairs (initial state)
54
+ - `when`: string action (`"create"`, `"submit"`, `"calculate_remaining"`)
55
+ - `then`: object with expected outcome (`{result: "success"|"error", Entity.field: value}`)
56
+
57
+ These examples directly feed:
58
+ - Gherkin `Examples:` tables (step-03, F-ter)
59
+ - `brToCodeMapping` in handoff
60
+ - Automated unit/integration tests in `/business-analyse-develop`
61
+
62
+ A rule without test-ready examples = a test gap in development.
63
+ Prose examples like `"code déjà existant"` are INSUFFICIENT — use concrete values.
64
+
28
65
  ---
29
66
 
30
67
  ## JSON-First Architecture