@exxatdesignux/ui 0.5.11 → 0.5.13

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 (477) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/bin/cli.mjs +70 -1
  3. package/bin/init.mjs +18 -4
  4. package/bin/sync-extras.mjs +28 -4
  5. package/consumer-extras/README.md +41 -5
  6. package/consumer-extras/cursor-rules/exxat-accessibility.mdc +2 -1
  7. package/consumer-extras/cursor-rules/exxat-board-cards.mdc +5 -3
  8. package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +1 -0
  9. package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +1 -0
  10. package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +4 -2
  11. package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +1 -0
  12. package/consumer-extras/cursor-rules/exxat-command-menu.mdc +3 -2
  13. package/consumer-extras/cursor-rules/exxat-data-tables.mdc +5 -3
  14. package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +7 -0
  15. package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +2 -1
  16. package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +1 -0
  17. package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +1 -0
  18. package/consumer-extras/cursor-rules/exxat-hub-supported-views.mdc +6 -4
  19. package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +6 -5
  20. package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +1 -0
  21. package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +1 -0
  22. package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +1 -0
  23. package/consumer-extras/cursor-rules/exxat-library-hub-header.mdc +2 -1
  24. package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +6 -2
  25. package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +2 -1
  26. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +2 -1
  27. package/consumer-extras/cursor-rules/exxat-nav-single-active.mdc +4 -3
  28. package/consumer-extras/cursor-rules/exxat-no-image-pixel-copy.mdc +25 -14
  29. package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +8 -2
  30. package/consumer-extras/cursor-rules/exxat-no-toast.mdc +1 -0
  31. package/consumer-extras/cursor-rules/exxat-no-vaul.mdc +2 -1
  32. package/consumer-extras/cursor-rules/exxat-page-header-actions.mdc +6 -4
  33. package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +2 -1
  34. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +1 -0
  35. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +2 -1
  36. package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +1 -0
  37. package/consumer-extras/cursor-rules/exxat-sidebar-shell.mdc +13 -7
  38. package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +5 -3
  39. package/consumer-extras/cursor-rules/exxat-table-row-preview.mdc +1 -0
  40. package/consumer-extras/cursor-rules/exxat-tabs-chrome.mdc +6 -4
  41. package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +6 -0
  42. package/consumer-extras/cursor-rules/exxat-ux-discovery-protocol.mdc +28 -0
  43. package/consumer-extras/cursor-rules/exxat-ux-principles.mdc +1 -0
  44. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +1 -1
  45. package/consumer-extras/cursor-skills/exxat-kpi-trends/SKILL.md +5 -3
  46. package/consumer-extras/patterns/command-menu-pattern.md +2 -2
  47. package/consumer-extras/patterns/consumer-upgrade-checklist.md +1 -1
  48. package/consumer-extras/patterns/jobs/README.md +1 -1
  49. package/consumer-extras/patterns/perf-memory-pattern.md +115 -150
  50. package/consumer-extras/scripts/dev-guard.mjs +156 -0
  51. package/consumer-extras/templates/README.md +23 -0
  52. package/consumer-extras/templates/handoff.md +190 -0
  53. package/package.json +2 -3
  54. package/{template → template-vite}/.claude/skills/exxat-ds-skill/SKILL.md +184 -23
  55. package/template-vite/.cursor/rules/exxat-accessibility.mdc +40 -0
  56. package/template-vite/.cursor/rules/exxat-board-cards.mdc +28 -0
  57. package/template-vite/.cursor/rules/exxat-breadcrumbs-no-back.mdc +22 -0
  58. package/template-vite/.cursor/rules/exxat-card-vs-list-rows.mdc +22 -0
  59. package/template-vite/.cursor/rules/exxat-centralized-list-dataset.mdc +46 -0
  60. package/template-vite/.cursor/rules/exxat-collaboration-access.mdc +33 -0
  61. package/{template → template-vite}/.cursor/rules/exxat-command-menu.mdc +5 -5
  62. package/template-vite/.cursor/rules/exxat-data-tables.mdc +47 -0
  63. package/template-vite/.cursor/rules/exxat-dedicated-search-surfaces.mdc +32 -0
  64. package/template-vite/.cursor/rules/exxat-drawer-vs-dialog.mdc +23 -0
  65. package/template-vite/.cursor/rules/exxat-ds-agents.mdc +87 -0
  66. package/template-vite/.cursor/rules/exxat-fontawesome-icons.mdc +32 -0
  67. package/template-vite/.cursor/rules/exxat-hub-supported-views.mdc +56 -0
  68. package/{template → template-vite}/.cursor/rules/exxat-kbd-shortcuts.mdc +1 -0
  69. package/template-vite/.cursor/rules/exxat-kpi-flat-band.mdc +29 -0
  70. package/template-vite/.cursor/rules/exxat-kpi-max-four.mdc +22 -0
  71. package/template-vite/.cursor/rules/exxat-kpi-trends.mdc +32 -0
  72. package/template-vite/.cursor/rules/exxat-library-hub-header.mdc +29 -0
  73. package/template-vite/.cursor/rules/exxat-list-page-connected-views.mdc +28 -0
  74. package/template-vite/.cursor/rules/exxat-list-page-view-shells.mdc +32 -0
  75. package/{template → template-vite}/.cursor/rules/exxat-mono-ids.mdc +1 -0
  76. package/template-vite/.cursor/rules/exxat-nav-single-active.mdc +32 -0
  77. package/template-vite/.cursor/rules/exxat-no-image-pixel-copy.mdc +46 -0
  78. package/template-vite/.cursor/rules/exxat-no-slds-leakage.mdc +84 -0
  79. package/{template → template-vite}/.cursor/rules/exxat-no-toast.mdc +2 -2
  80. package/template-vite/.cursor/rules/exxat-no-vaul.mdc +26 -0
  81. package/template-vite/.cursor/rules/exxat-page-header-actions.mdc +33 -0
  82. package/{template → template-vite}/.cursor/rules/exxat-page-vs-drawer.mdc +5 -3
  83. package/template-vite/.cursor/rules/exxat-person-identity-display.mdc +48 -0
  84. package/template-vite/.cursor/rules/exxat-primary-nav-secondary-panel.mdc +53 -0
  85. package/template-vite/.cursor/rules/exxat-reuse-before-custom.mdc +37 -0
  86. package/template-vite/.cursor/rules/exxat-sidebar-shell.mdc +41 -0
  87. package/template-vite/.cursor/rules/exxat-table-properties-drawer.mdc +79 -0
  88. package/template-vite/.cursor/rules/exxat-table-row-preview.mdc +25 -0
  89. package/template-vite/.cursor/rules/exxat-tabs-chrome.mdc +33 -0
  90. package/template-vite/.cursor/rules/exxat-token-discipline.mdc +109 -0
  91. package/template-vite/.cursor/rules/exxat-ux-discovery-protocol.mdc +202 -0
  92. package/template-vite/.cursor/rules/exxat-ux-principles.mdc +187 -0
  93. package/template-vite/.cursor/skills/exxat-accessibility/SKILL.md +282 -0
  94. package/template-vite/.cursor/skills/exxat-board-cards/SKILL.md +68 -0
  95. package/template-vite/.cursor/skills/exxat-card-vs-list-rows/SKILL.md +20 -0
  96. package/template-vite/.cursor/skills/exxat-centralized-list-dataset/SKILL.md +99 -0
  97. package/template-vite/.cursor/skills/exxat-collaboration-access/SKILL.md +35 -0
  98. package/template-vite/.cursor/skills/exxat-dedicated-search-surfaces/SKILL.md +45 -0
  99. package/template-vite/.cursor/skills/exxat-drawer-vs-dialog/SKILL.md +20 -0
  100. package/template-vite/.cursor/skills/exxat-ds-skill/SKILL.md +893 -0
  101. package/template-vite/.cursor/skills/exxat-ds-skill/references/accessibility.md +142 -0
  102. package/template-vite/.cursor/skills/exxat-ds-skill/references/coach-marks.md +169 -0
  103. package/template-vite/.cursor/skills/exxat-ds-skill/references/data-table-pattern.md +392 -0
  104. package/template-vite/.cursor/skills/exxat-fontawesome-icons/SKILL.md +31 -0
  105. package/template-vite/.cursor/skills/exxat-kpi-flat-band/SKILL.md +38 -0
  106. package/template-vite/.cursor/skills/exxat-kpi-max-four/SKILL.md +19 -0
  107. package/template-vite/.cursor/skills/exxat-kpi-trends/SKILL.md +29 -0
  108. package/template-vite/.cursor/skills/exxat-list-page-view-shells/SKILL.md +36 -0
  109. package/template-vite/.cursor/skills/exxat-mono-ids/SKILL.md +56 -0
  110. package/template-vite/.cursor/skills/exxat-primary-nav-secondary-panel/SKILL.md +49 -0
  111. package/template-vite/.cursor/skills/exxat-senior-ux/SKILL.md +198 -0
  112. package/template-vite/.cursor/skills/exxat-token-economy/SKILL.md +287 -0
  113. package/template-vite/.cursor/skills/exxat-ux-audit/SKILL.md +303 -0
  114. package/{template → template-vite}/components/ask-leo-sidebar.tsx +10 -8
  115. package/{template → template-vite}/components/command-menu.tsx +1 -1
  116. package/{template → template-vite}/components/data-views/library-folder-tree-branch.tsx +1 -1
  117. package/{template → template-vite}/components/dedicated-search-recents.tsx +1 -1
  118. package/{template → template-vite}/components/dedicated-search-url-composer.tsx +1 -1
  119. package/{template → template-vite}/components/exxat-product-logo.tsx +3 -3
  120. package/{template → template-vite}/components/library-client.tsx +1 -1
  121. package/{template → template-vite}/components/library-hub-client.tsx +2 -2
  122. package/{template → template-vite}/components/library-secondary-nav.tsx +2 -2
  123. package/{template → template-vite}/components/library-table.tsx +35 -27
  124. package/{template → template-vite}/components/new-library-item-form.tsx +1 -1
  125. package/{template → template-vite}/components/page-breadcrumb-trail.tsx +1 -1
  126. package/{template → template-vite}/components/settings-client.tsx +1 -1
  127. package/{template → template-vite}/components/sidebar/app-sidebar.tsx +2 -2
  128. package/{template → template-vite}/components/sidebar/nav-main.tsx +1 -1
  129. package/{template → template-vite}/components/sidebar/nav-user.tsx +1 -1
  130. package/{template → template-vite}/components/sidebar/secondary-nav.tsx +1 -1
  131. package/{template → template-vite}/components/system-banner-slot.tsx +1 -1
  132. package/{template → template-vite}/components/templates/discovery-hub-template.tsx +2 -2
  133. package/{template → template-vite}/components/templates/new-focus-template.tsx +1 -1
  134. package/{template → template-vite}/components/tokens-secondary-nav.tsx +2 -2
  135. package/{template → template-vite}/components/tokens-themes-client.tsx +1 -1
  136. package/{template → template-vite}/hooks/use-secondary-panel-hub-nav.ts +1 -1
  137. package/template-vite/index.html +49 -0
  138. package/template-vite/lib/next-compat.tsx +98 -0
  139. package/{template → template-vite}/package.json +15 -27
  140. package/template-vite/scripts/port-next-imports.mjs +70 -0
  141. package/template-vite/src/App.tsx +103 -0
  142. package/template-vite/src/main.tsx +50 -0
  143. package/{template/app/(app)/error.tsx → template-vite/src/pages/_error.tsx} +12 -24
  144. package/{template/app/(app)/loading.tsx → template-vite/src/pages/_loading.tsx} +4 -2
  145. package/template-vite/src/pages/_not-found.tsx +17 -0
  146. package/template-vite/src/pages/dashboard.tsx +48 -0
  147. package/{template/app/(app)/help/page.tsx → template-vite/src/pages/help.tsx} +3 -2
  148. package/{template/app/(app)/library/layout.tsx → template-vite/src/pages/library/_layout.tsx} +18 -16
  149. package/{template/app/(app)/library/all/page.tsx → template-vite/src/pages/library/all.tsx} +1 -1
  150. package/{template/app/(app)/library/new/page.tsx → template-vite/src/pages/library/new.tsx} +12 -18
  151. package/template-vite/src/routes.tsx +72 -0
  152. package/template-vite/src/styles/globals.css +25 -0
  153. package/{template → template-vite}/tsconfig.json +5 -14
  154. package/template-vite/vite.config.ts +52 -0
  155. package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +0 -53
  156. package/template/.agents/skills/shadcn/SKILL.md +0 -242
  157. package/template/.agents/skills/shadcn/agents/openai.yml +0 -5
  158. package/template/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
  159. package/template/.agents/skills/shadcn/assets/shadcn.png +0 -0
  160. package/template/.agents/skills/shadcn/cli.md +0 -257
  161. package/template/.agents/skills/shadcn/customization.md +0 -202
  162. package/template/.agents/skills/shadcn/evals/evals.json +0 -47
  163. package/template/.agents/skills/shadcn/mcp.md +0 -94
  164. package/template/.agents/skills/shadcn/rules/base-vs-radix.md +0 -306
  165. package/template/.agents/skills/shadcn/rules/composition.md +0 -195
  166. package/template/.agents/skills/shadcn/rules/forms.md +0 -192
  167. package/template/.agents/skills/shadcn/rules/icons.md +0 -101
  168. package/template/.agents/skills/shadcn/rules/styling.md +0 -162
  169. package/template/.cursor/rules/exxat-accessibility.mdc +0 -33
  170. package/template/.cursor/rules/exxat-data-tables.mdc +0 -32
  171. package/template/.cursor/rules/exxat-ds-agents.mdc +0 -26
  172. package/template/.cursor/rules/exxat-list-page-connected-views.mdc +0 -16
  173. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +0 -40
  174. package/template/.nvmrc +0 -1
  175. package/template/.prettierignore +0 -7
  176. package/template/Logo/Exxat_Prism.svg +0 -39
  177. package/template/Logo/Exxat_one.svg +0 -36
  178. package/template/app/(app)/dashboard/loading.tsx +0 -18
  179. package/template/app/(app)/dashboard/page.tsx +0 -36
  180. package/template/app/(app)/layout.tsx +0 -77
  181. package/template/app/global-error.tsx +0 -63
  182. package/template/app/globals.css +0 -20
  183. package/template/app/layout.tsx +0 -133
  184. package/template/app/page.tsx +0 -9
  185. package/template/docs/HANDBOOK.md +0 -187
  186. package/template/docs/blueprints/README.md +0 -86
  187. package/template/docs/blueprints/_template.md +0 -91
  188. package/template/docs/blueprints/board-card.md +0 -123
  189. package/template/docs/blueprints/data-table.md +0 -139
  190. package/template/docs/blueprints/key-metrics.md +0 -128
  191. package/template/docs/blueprints/list-page-template.md +0 -123
  192. package/template/docs/blueprints/page-header.md +0 -130
  193. package/template/docs/card-vs-rows-pattern.md +0 -36
  194. package/template/docs/collaboration-access-pattern.md +0 -116
  195. package/template/docs/command-menu-pattern.md +0 -45
  196. package/template/docs/component-selection-guide.md +0 -224
  197. package/template/docs/components-audit-2026-05.md +0 -158
  198. package/template/docs/consumer-upgrade-checklist.md +0 -52
  199. package/template/docs/data-views-pattern.md +0 -185
  200. package/template/docs/drawer-vs-dialog-pattern.md +0 -50
  201. package/template/docs/glossary.md +0 -59
  202. package/template/docs/hub-supported-views-pattern.md +0 -53
  203. package/template/docs/jobs/README.md +0 -59
  204. package/template/docs/jobs/record-detail.md +0 -177
  205. package/template/docs/kpi-flat-band-pattern.md +0 -57
  206. package/template/docs/kpi-strip-max-four-pattern.md +0 -30
  207. package/template/docs/kpi-trend-pattern.md +0 -58
  208. package/template/docs/large-dataset-strategy.md +0 -155
  209. package/template/docs/library-hub-header-pattern.md +0 -25
  210. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +0 -95
  211. package/template/docs/migrations/0002-exxat-token-namespace.md +0 -154
  212. package/template/docs/migrations/0003-globals-css-canonical.md +0 -110
  213. package/template/docs/migrations/README.md +0 -100
  214. package/template/docs/migrations/_template.md +0 -64
  215. package/template/docs/modern-saas-patterns.md +0 -165
  216. package/template/docs/perf-memory-pattern.md +0 -206
  217. package/template/docs/reference-implementations.md +0 -153
  218. package/template/docs/shell-surface-elevation-pattern.md +0 -52
  219. package/template/docs/token-taxonomy.md +0 -416
  220. package/template/docs/voice-and-tone.md +0 -262
  221. package/template/ecosystem.config.cjs +0 -32
  222. package/template/next.config.mjs +0 -216
  223. package/template/postcss.config.mjs +0 -8
  224. package/template/public/favicon/favicon.ico +0 -0
  225. package/template/tests/setup.ts +0 -26
  226. package/template/vitest.config.ts +0 -18
  227. /package/{template → template-vite}/.cursor/rules/exxat-dashboard-view-charts.mdc +0 -0
  228. /package/{template → template-vite}/.prettierrc +0 -0
  229. /package/{template → template-vite}/AGENTS.md +0 -0
  230. /package/{template → template-vite}/README.md +0 -0
  231. /package/{template → template-vite}/components/.gitkeep +0 -0
  232. /package/{template → template-vite}/components/ask-leo-composer.tsx +0 -0
  233. /package/{template → template-vite}/components/brand-color-picker.tsx +0 -0
  234. /package/{template → template-vite}/components/chart-area-interactive.tsx +0 -0
  235. /package/{template → template-vite}/components/charts-overview.tsx +0 -0
  236. /package/{template → template-vite}/components/collaboration-access-flow.tsx +0 -0
  237. /package/{template → template-vite}/components/columns-client.tsx +0 -0
  238. /package/{template → template-vite}/components/columns-showcase.tsx +0 -0
  239. /package/{template → template-vite}/components/dashboard-promo-banner.tsx +0 -0
  240. /package/{template → template-vite}/components/dashboard-quota-progress-card.tsx +0 -0
  241. /package/{template → template-vite}/components/dashboard-report-charts.tsx +0 -0
  242. /package/{template → template-vite}/components/dashboard-section-heading.tsx +0 -0
  243. /package/{template → template-vite}/components/dashboard-tabs.tsx +0 -0
  244. /package/{template → template-vite}/components/data-table/filter-date-calendar.tsx +0 -0
  245. /package/{template → template-vite}/components/data-table/filter-text-value-input.tsx +0 -0
  246. /package/{template → template-vite}/components/data-table/index.tsx +0 -0
  247. /package/{template → template-vite}/components/data-table/pagination.tsx +0 -0
  248. /package/{template → template-vite}/components/data-table/types.ts +0 -0
  249. /package/{template → template-vite}/components/data-table/use-table-state.test.ts +0 -0
  250. /package/{template → template-vite}/components/data-table/use-table-state.ts +0 -0
  251. /package/{template → template-vite}/components/data-views/board-card-primitives.tsx +0 -0
  252. /package/{template → template-vite}/components/data-views/data-row-list.tsx +0 -0
  253. /package/{template → template-vite}/components/data-views/finder-panel-view.tsx +0 -0
  254. /package/{template → template-vite}/components/data-views/folder-grid-view.tsx +0 -0
  255. /package/{template → template-vite}/components/data-views/hub-table.tsx +0 -0
  256. /package/{template → template-vite}/components/data-views/index.ts +0 -0
  257. /package/{template → template-vite}/components/data-views/list-page-board-card.tsx +0 -0
  258. /package/{template → template-vite}/components/data-views/list-page-board-template.tsx +0 -0
  259. /package/{template → template-vite}/components/data-views/list-page-connected-view-body.tsx +0 -0
  260. /package/{template → template-vite}/components/data-views/list-page-split-details-placeholder.tsx +0 -0
  261. /package/{template → template-vite}/components/data-views/list-page-split-hub-chrome.tsx +0 -0
  262. /package/{template → template-vite}/components/data-views/list-page-split-hub-tokens.ts +0 -0
  263. /package/{template → template-vite}/components/data-views/list-page-tree-column-header.tsx +0 -0
  264. /package/{template → template-vite}/components/data-views/list-page-tree-panel-shell.tsx +0 -0
  265. /package/{template → template-vite}/components/data-views/list-page-view-frame.tsx +0 -0
  266. /package/{template → template-vite}/components/data-views/os-folder-glyph.tsx +0 -0
  267. /package/{template → template-vite}/components/data-views/outline-tree-menu.tsx +0 -0
  268. /package/{template → template-vite}/components/data-views/table-cells.tsx +0 -0
  269. /package/{template → template-vite}/components/dev-chunk-load-recovery.tsx +0 -0
  270. /package/{template → template-vite}/components/export-drawer.test.tsx +0 -0
  271. /package/{template → template-vite}/components/export-drawer.tsx +0 -0
  272. /package/{template → template-vite}/components/folder-details-shell.tsx +0 -0
  273. /package/{template → template-vite}/components/form-layout-01.tsx +0 -0
  274. /package/{template → template-vite}/components/hub-tree-panel-view.tsx +0 -0
  275. /package/{template → template-vite}/components/invite-collaborators-drawer.tsx +0 -0
  276. /package/{template → template-vite}/components/key-metrics-ask-leo-bridge.tsx +0 -0
  277. /package/{template → template-vite}/components/key-metrics.tsx +0 -0
  278. /package/{template → template-vite}/components/leo-insight-indicator.tsx +0 -0
  279. /package/{template → template-vite}/components/leo-typing-dots.tsx +0 -0
  280. /package/{template → template-vite}/components/library-board-view.tsx +0 -0
  281. /package/{template → template-vite}/components/library-dashboard-charts.tsx +0 -0
  282. /package/{template → template-vite}/components/library-favorite-button.tsx +0 -0
  283. /package/{template → template-vite}/components/library-new-folder-sheet.tsx +0 -0
  284. /package/{template → template-vite}/components/library-os-folder-view.tsx +0 -0
  285. /package/{template → template-vite}/components/library-page-header.tsx +0 -0
  286. /package/{template → template-vite}/components/library-panel-activator.tsx +0 -0
  287. /package/{template → template-vite}/components/list-hub-status-badge.tsx +0 -0
  288. /package/{template → template-vite}/components/list-page-dashboard-charts.tsx +0 -0
  289. /package/{template → template-vite}/components/onboarding/getting-started.tsx +0 -0
  290. /package/{template → template-vite}/components/onboarding/index.ts +0 -0
  291. /package/{template → template-vite}/components/onboarding/onboarding-01.tsx +0 -0
  292. /package/{template → template-vite}/components/onboarding/onboarding-02.tsx +0 -0
  293. /package/{template → template-vite}/components/onboarding/onboarding-03.tsx +0 -0
  294. /package/{template → template-vite}/components/onboarding/onboarding-04.tsx +0 -0
  295. /package/{template → template-vite}/components/page-header.tsx +0 -0
  296. /package/{template → template-vite}/components/product-switcher.tsx +0 -0
  297. /package/{template → template-vite}/components/product-wordmark.tsx +0 -0
  298. /package/{template → template-vite}/components/settings-appearance-card.tsx +0 -0
  299. /package/{template → template-vite}/components/settings-form-row.tsx +0 -0
  300. /package/{template → template-vite}/components/sidebar/app-sidebar-dynamic.tsx +0 -0
  301. /package/{template → template-vite}/components/sidebar/index.ts +0 -0
  302. /package/{template → template-vite}/components/sidebar/nav-documents.tsx +0 -0
  303. /package/{template → template-vite}/components/sidebar/nav-secondary.tsx +0 -0
  304. /package/{template → template-vite}/components/sidebar/secondary-panel.tsx +0 -0
  305. /package/{template → template-vite}/components/sidebar/sidebar-auto-collapse.tsx +0 -0
  306. /package/{template → template-vite}/components/sidebar/sidebar-auto-open.tsx +0 -0
  307. /package/{template → template-vite}/components/sidebar/sidebar-shell.tsx +0 -0
  308. /package/{template → template-vite}/components/site-header.tsx +0 -0
  309. /package/{template → template-vite}/components/table-properties/column-row.tsx +0 -0
  310. /package/{template → template-vite}/components/table-properties/draggable-list.ts +0 -0
  311. /package/{template → template-vite}/components/table-properties/drawer-button.tsx +0 -0
  312. /package/{template → template-vite}/components/table-properties/drawer.tsx +0 -0
  313. /package/{template → template-vite}/components/table-properties/filter-card.tsx +0 -0
  314. /package/{template → template-vite}/components/table-properties/index.ts +0 -0
  315. /package/{template → template-vite}/components/table-properties/sort-card.tsx +0 -0
  316. /package/{template → template-vite}/components/table-properties/types.ts +0 -0
  317. /package/{template → template-vite}/components/task-list-panel.tsx +0 -0
  318. /package/{template → template-vite}/components/task-priority-badge.tsx +0 -0
  319. /package/{template → template-vite}/components/templates/dedicated-search-landing-template.tsx +0 -0
  320. /package/{template → template-vite}/components/templates/dedicated-search-results-template.tsx +0 -0
  321. /package/{template → template-vite}/components/templates/list-page.tsx +0 -0
  322. /package/{template → template-vite}/components/templates/nested-secondary-panel-shell.tsx +0 -0
  323. /package/{template → template-vite}/components/templates/primary-page-template.tsx +0 -0
  324. /package/{template → template-vite}/components/templates/secondary-panel-hub-template.tsx +0 -0
  325. /package/{template → template-vite}/components/theme-color-sync.tsx +0 -0
  326. /package/{template → template-vite}/components/theme-provider.tsx +0 -0
  327. /package/{template → template-vite}/components/tinted-icon-disc.tsx +0 -0
  328. /package/{template → template-vite}/components/tokens-hub-auxiliary-views.tsx +0 -0
  329. /package/{template → template-vite}/components/tokens-themes-section.tsx +0 -0
  330. /package/{template → template-vite}/components/ui/accordion.tsx +0 -0
  331. /package/{template → template-vite}/components/ui/ai-thinking-surface.tsx +0 -0
  332. /package/{template → template-vite}/components/ui/alert-dialog.tsx +0 -0
  333. /package/{template → template-vite}/components/ui/avatar.tsx +0 -0
  334. /package/{template → template-vite}/components/ui/badge.tsx +0 -0
  335. /package/{template → template-vite}/components/ui/banner.tsx +0 -0
  336. /package/{template → template-vite}/components/ui/breadcrumb.tsx +0 -0
  337. /package/{template → template-vite}/components/ui/button.tsx +0 -0
  338. /package/{template → template-vite}/components/ui/calendar.tsx +0 -0
  339. /package/{template → template-vite}/components/ui/card.tsx +0 -0
  340. /package/{template → template-vite}/components/ui/chart.tsx +0 -0
  341. /package/{template → template-vite}/components/ui/checkbox.tsx +0 -0
  342. /package/{template → template-vite}/components/ui/coach-mark.tsx +0 -0
  343. /package/{template → template-vite}/components/ui/collapsible.tsx +0 -0
  344. /package/{template → template-vite}/components/ui/command.tsx +0 -0
  345. /package/{template → template-vite}/components/ui/context-menu.tsx +0 -0
  346. /package/{template → template-vite}/components/ui/date-picker-field.tsx +0 -0
  347. /package/{template → template-vite}/components/ui/dialog.tsx +0 -0
  348. /package/{template → template-vite}/components/ui/dot-pattern.tsx +0 -0
  349. /package/{template → template-vite}/components/ui/drag-handle-grip.tsx +0 -0
  350. /package/{template → template-vite}/components/ui/dropdown-menu.tsx +0 -0
  351. /package/{template → template-vite}/components/ui/field.tsx +0 -0
  352. /package/{template → template-vite}/components/ui/form.tsx +0 -0
  353. /package/{template → template-vite}/components/ui/hover-card.tsx +0 -0
  354. /package/{template → template-vite}/components/ui/input-group.tsx +0 -0
  355. /package/{template → template-vite}/components/ui/input-mask.tsx +0 -0
  356. /package/{template → template-vite}/components/ui/input.tsx +0 -0
  357. /package/{template → template-vite}/components/ui/kbd.tsx +0 -0
  358. /package/{template → template-vite}/components/ui/label.tsx +0 -0
  359. /package/{template → template-vite}/components/ui/leo-icon.tsx +0 -0
  360. /package/{template → template-vite}/components/ui/payment-card-fields.tsx +0 -0
  361. /package/{template → template-vite}/components/ui/popover.tsx +0 -0
  362. /package/{template → template-vite}/components/ui/radio-group.tsx +0 -0
  363. /package/{template → template-vite}/components/ui/resizable.tsx +0 -0
  364. /package/{template → template-vite}/components/ui/scroll-area.tsx +0 -0
  365. /package/{template → template-vite}/components/ui/select.tsx +0 -0
  366. /package/{template → template-vite}/components/ui/selection-tile-grid.tsx +0 -0
  367. /package/{template → template-vite}/components/ui/separator.tsx +0 -0
  368. /package/{template → template-vite}/components/ui/sheet.tsx +0 -0
  369. /package/{template → template-vite}/components/ui/sidebar.tsx +0 -0
  370. /package/{template → template-vite}/components/ui/skeleton.tsx +0 -0
  371. /package/{template → template-vite}/components/ui/slider.tsx +0 -0
  372. /package/{template → template-vite}/components/ui/sonner.tsx +0 -0
  373. /package/{template → template-vite}/components/ui/status-badge.tsx +0 -0
  374. /package/{template → template-vite}/components/ui/table.tsx +0 -0
  375. /package/{template → template-vite}/components/ui/tabs.tsx +0 -0
  376. /package/{template → template-vite}/components/ui/textarea.tsx +0 -0
  377. /package/{template → template-vite}/components/ui/tip.tsx +0 -0
  378. /package/{template → template-vite}/components/ui/toggle-group.tsx +0 -0
  379. /package/{template → template-vite}/components/ui/toggle-switch.tsx +0 -0
  380. /package/{template → template-vite}/components/ui/toggle.tsx +0 -0
  381. /package/{template → template-vite}/components/ui/tooltip.tsx +0 -0
  382. /package/{template → template-vite}/components/ui/view-segmented-control.tsx +0 -0
  383. /package/{template → template-vite}/components.json +0 -0
  384. /package/{template → template-vite}/contexts/chart-variant-context.tsx +0 -0
  385. /package/{template → template-vite}/contexts/command-menu-context.tsx +0 -0
  386. /package/{template → template-vite}/contexts/dashboard-view-context.tsx +0 -0
  387. /package/{template → template-vite}/contexts/product-context.tsx +0 -0
  388. /package/{template → template-vite}/contexts/system-banner-context.tsx +0 -0
  389. /package/{template → template-vite}/eslint.config.mjs +0 -0
  390. /package/{template → template-vite}/fontawesome-subset.manifest.json +0 -0
  391. /package/{template → template-vite}/hooks/.gitkeep +0 -0
  392. /package/{template → template-vite}/hooks/use-app-theme.ts +0 -0
  393. /package/{template → template-vite}/hooks/use-coach-mark.ts +0 -0
  394. /package/{template → template-vite}/hooks/use-location-hash.ts +0 -0
  395. /package/{template → template-vite}/hooks/use-mobile.ts +0 -0
  396. /package/{template → template-vite}/hooks/use-mod-key-label.ts +0 -0
  397. /package/{template → template-vite}/hooks/use-sidebar-reflow-zoom.ts +0 -0
  398. /package/{template → template-vite}/lib/.gitkeep +0 -0
  399. /package/{template → template-vite}/lib/ask-leo-route-context.ts +0 -0
  400. /package/{template → template-vite}/lib/chart-keyboard-selection.test.ts +0 -0
  401. /package/{template → template-vite}/lib/chart-keyboard-selection.ts +0 -0
  402. /package/{template → template-vite}/lib/chart-line-dash.ts +0 -0
  403. /package/{template → template-vite}/lib/chunk-load-error.ts +0 -0
  404. /package/{template → template-vite}/lib/coach-mark-registry.ts +0 -0
  405. /package/{template → template-vite}/lib/collaborator-access.ts +0 -0
  406. /package/{template → template-vite}/lib/command-menu-config.ts +0 -0
  407. /package/{template → template-vite}/lib/command-menu-search-data.ts +0 -0
  408. /package/{template → template-vite}/lib/conditional-rule-match.ts +0 -0
  409. /package/{template → template-vite}/lib/dashboard-customize-coach-mark.ts +0 -0
  410. /package/{template → template-vite}/lib/dashboard-layout-merge.ts +0 -0
  411. /package/{template → template-vite}/lib/data-list-display-options.ts +0 -0
  412. /package/{template → template-vite}/lib/data-list-persistence.ts +0 -0
  413. /package/{template → template-vite}/lib/data-list-view-registry.ts +0 -0
  414. /package/{template → template-vite}/lib/data-list-view-surface.ts +0 -0
  415. /package/{template → template-vite}/lib/data-list-view.ts +0 -0
  416. /package/{template → template-vite}/lib/data-view-dashboard-storage.ts +0 -0
  417. /package/{template → template-vite}/lib/date-filter.ts +0 -0
  418. /package/{template → template-vite}/lib/dedicated-search-recents.ts +0 -0
  419. /package/{template → template-vite}/lib/dedicated-search-url.ts +0 -0
  420. /package/{template → template-vite}/lib/dev-log.test.ts +0 -0
  421. /package/{template → template-vite}/lib/dev-log.ts +0 -0
  422. /package/{template → template-vite}/lib/discovery-hub.ts +0 -0
  423. /package/{template → template-vite}/lib/editable-target.ts +0 -0
  424. /package/{template → template-vite}/lib/exxat-palette.json +0 -0
  425. /package/{template → template-vite}/lib/exxat-palette.ts +0 -0
  426. /package/{template → template-vite}/lib/floating-sheet-panel.ts +0 -0
  427. /package/{template → template-vite}/lib/full-hub-supported-views.ts +0 -0
  428. /package/{template → template-vite}/lib/hub-connected-view-renderers.ts +0 -0
  429. /package/{template → template-vite}/lib/initials-from-name.ts +0 -0
  430. /package/{template → template-vite}/lib/library-authoring.ts +0 -0
  431. /package/{template → template-vite}/lib/library-dedicated-search.ts +0 -0
  432. /package/{template → template-vite}/lib/library-hub-search.ts +0 -0
  433. /package/{template → template-vite}/lib/library-nav.ts +0 -0
  434. /package/{template → template-vite}/lib/library-recent-searches.ts +0 -0
  435. /package/{template → template-vite}/lib/library-supported-views.ts +0 -0
  436. /package/{template → template-vite}/lib/list-hub-supported-views.ts +0 -0
  437. /package/{template → template-vite}/lib/list-page-table-properties.ts +0 -0
  438. /package/{template → template-vite}/lib/list-status-badges.ts +0 -0
  439. /package/{template → template-vite}/lib/logo-dev.ts +0 -0
  440. /package/{template → template-vite}/lib/mailto.ts +0 -0
  441. /package/{template → template-vite}/lib/mock/dashboard.ts +0 -0
  442. /package/{template → template-vite}/lib/mock/library-folders.ts +0 -0
  443. /package/{template → template-vite}/lib/mock/library-header-collaborators.ts +0 -0
  444. /package/{template → template-vite}/lib/mock/library-inspector.ts +0 -0
  445. /package/{template → template-vite}/lib/mock/library-kpi.ts +0 -0
  446. /package/{template → template-vite}/lib/mock/library.ts +0 -0
  447. /package/{template → template-vite}/lib/mock/navigation.tsx +0 -0
  448. /package/{template → template-vite}/lib/motion-ui.ts +0 -0
  449. /package/{template → template-vite}/lib/product-brand.ts +0 -0
  450. /package/{template → template-vite}/lib/raf-throttle.ts +0 -0
  451. /package/{template → template-vite}/lib/row-height.ts +0 -0
  452. /package/{template → template-vite}/lib/sidebar-state-cookie.ts +0 -0
  453. /package/{template → template-vite}/lib/stock-portrait.ts +0 -0
  454. /package/{template → template-vite}/lib/table-state-lifecycle.ts +0 -0
  455. /package/{template → template-vite}/lib/utils.test.ts +0 -0
  456. /package/{template → template-vite}/lib/utils.ts +0 -0
  457. /package/{template → template-vite}/public/.gitkeep +0 -0
  458. /package/{template → template-vite}/public/Illustration/Rotation.svg +0 -0
  459. /package/{template → template-vite}/public/avatars/user.svg +0 -0
  460. /package/{template/public → template-vite/public/favicon}/favicon.ico +0 -0
  461. /package/{template/app → template-vite/public}/favicon.ico +0 -0
  462. /package/{template → template-vite}/public/folders/icons8-folder-windows-11.svg +0 -0
  463. /package/{template → template-vite}/public/logos/exxat-one.svg +0 -0
  464. /package/{template → template-vite}/public/logos/exxat-prism.svg +0 -0
  465. /package/{template → template-vite}/public/mock-schools/emory.svg +0 -0
  466. /package/{template → template-vite}/public/mock-schools/rush.svg +0 -0
  467. /package/{template → template-vite}/scripts/fontawesome-subset-audit.mjs +0 -0
  468. /package/{template → template-vite}/scripts/pm2-startup-macos.sh +0 -0
  469. /package/{template → template-vite}/skills-lock.json +0 -0
  470. /package/{template/app/(app)/columns/page.tsx → template-vite/src/pages/columns.tsx} +0 -0
  471. /package/{template/app/(app)/library/find/page.tsx → template-vite/src/pages/library/find.tsx} +0 -0
  472. /package/{template/app/(app)/library/page.tsx → template-vite/src/pages/library/index.tsx} +0 -0
  473. /package/{template/app/(app)/library/list/page.tsx → template-vite/src/pages/library/list.tsx} +0 -0
  474. /package/{template/app/(app)/settings/page.tsx → template-vite/src/pages/settings.tsx} +0 -0
  475. /package/{template/app/(app)/tokens-themes/page.tsx → template-vite/src/pages/tokens-themes.tsx} +0 -0
  476. /package/{template → template-vite}/stores/app-store.ts +0 -0
  477. /package/{template → template-vite}/types/react-payment-inputs.d.ts +0 -0
@@ -1,206 +0,0 @@
1
- # Dev memory tuning for Next.js + Node 24
2
-
3
- > **Audience:** humans + AI agents.
4
- > **Companion to:** [`HANDBOOK.md`](./HANDBOOK.md). Read this when `next dev`
5
- > RSS climbs past ~3 GB, when two `next-server` processes total > 5 GB, or
6
- > when adopting Node 24.
7
-
8
- A fresh `next dev` against this app stabilizes around **~1.4 GB RSS** with
9
- the settings below. Without them, the same app drifts to **3–6 GB per
10
- process** and pm2 will eventually swap or OOM.
11
-
12
- ## 1. The six knobs
13
-
14
- | # | Knob | Why it matters | Where it lives |
15
- |---|------|----------------|----------------|
16
- | 1 | `NODE_OPTIONS="--max-old-space-size=6144 --max-semi-space-size=64"` | Caps V8 old-space at 6 GB (default on macOS is ~94% of system RAM = unbounded for practical purposes). With a ceiling, V8 GC pressure kicks in earlier and steady-state heap is lower. `--max-semi-space-size=64` widens the young generation so short-lived render allocations don't promote to old-space. | `package.json` `dev*` scripts + `ecosystem.config.cjs` `env` |
17
- | 2 | `turbopack.memoryLimit: 4 GiB` | Hard cap on the Turbopack worker process. Without this, Turbopack's module graph + mmap'd FS cache files grow unbounded — we observed 3.2 GB on disk and 5+ GB RSS per process with no cap. 4 GiB is generous for apps with < ~1000 routes. | `next.config.mjs` `turbopack` |
18
- | 3 | `experimental.preloadEntriesOnStart: false` | Next compiles routes on first visit instead of pre-warming every entry on dev start. Dev TTFB drops from ~15s → ~2s; steady-state heap is ~30% lower. | `next.config.mjs` |
19
- | 4 | `experimental.optimizePackageImports: [...]` | Re-export barrels (`lucide-react`, `@tabler/icons-react`, `motion`, `@dnd-kit/*`, `recharts`) get tree-shaken to leaf imports. Cuts the dev server's parsed-module count by ~40%. | `next.config.mjs` |
20
- | 5 | `experimental.webpackMemoryOptimizations: true` | Drops large in-memory webpack caches at the cost of slightly slower rebuilds. **Only the `pnpm dev:webpack` fallback uses webpack** — Turbopack ignores this flag. Keep it on for the rare cases where the webpack path is needed. | `next.config.mjs` |
21
- | 6 | `target: ES2022` (tsconfig) | The TS compiler emits less polyfill scaffolding for `async/await`, optional chaining, nullish coalescing, etc. tsserver in-memory AST shrinks proportionally. Safe with React 19 + Next 16 + Node 24. | `tsconfig.json` |
22
-
23
- ## 2. NODE_OPTIONS propagation
24
-
25
- `NODE_OPTIONS` is read by **every Node process** the moment it boots. The npm
26
- parent doesn't read it (npm is a shell wrapper), but its child `next-server`
27
- processes inherit and honour it.
28
-
29
- - **Local dev:** set inline in `package.json` `scripts`. Cross-shell safe
30
- because Next dev is only run from POSIX shells.
31
- - **PM2 daemon:** set in `ecosystem.config.cjs` `env` (which becomes the child
32
- environment).
33
- - **CI:** set in the workflow `env:` block on the same step that runs `next`.
34
- - **VS Code / Cursor terminals:** these inherit the parent shell env, so the
35
- `package.json` script is enough.
36
-
37
- ## 3. Turbopack file-system cache (Next ≥ 16.1)
38
-
39
- Since Next 16.1, **`experimental.turbopackFileSystemCacheForDev` defaults to `true`** — Turbopack writes compilation artifacts to `.next/dev/cache/turbopack/<hash>/*.meta` and mmaps them across dev sessions. This is what makes the second `next dev` start in ~1 s instead of ~15 s.
40
-
41
- **The trade-off** is that the cache grows linearly with the number of unique routes / modules you've touched. After a few weeks of feature work it's normal to see:
42
-
43
- ```bash
44
- du -sh .next
45
- # 3.2G .next
46
- ```
47
-
48
- Each `.meta` file is mmap'd by the running `next-server`, so the cache size is roughly the floor of the dev process's RSS until the OS evicts pages.
49
-
50
- **Do not disable** the FS cache (`turbopackFileSystemCacheForDev: false`) — cold-start dev becomes painful (~15–30 s every restart on this app). Instead, **bust the cache** when it grows past 1–2 GB:
51
-
52
- ```bash
53
- pnpm clean:cache # removes .next/dev/cache and .next/dev/trace
54
- pnpm dev:fresh # bust + restart in one command
55
- ```
56
-
57
- The `dev:fresh` script is the right move whenever:
58
-
59
- - A pnpm install changed `@exxatdesignux/ui` or any framework dep.
60
- - `.next` is > 2 GB and dev memory is climbing.
61
- - HMR starts skipping updates or compilation gets stuck on a stale module.
62
-
63
- For a full nuke (build artifacts too):
64
-
65
- ```bash
66
- pnpm clean
67
- ```
68
-
69
- `turbopack.memoryLimit` (knob #2) prevents the cache from blowing past 4 GiB of RAM even when the on-disk cache is large.
70
-
71
- ## 4. Don't run two dev servers at the same time
72
-
73
- **This is the #1 cause of memory exhaustion in practice.** A single `next-server` (parent + render worker) stabilizes at ~2 GB total RSS with the knobs above. Two parallel servers stabilize at ~4 GB, three at ~6 GB, and so on — they don't share any caches.
74
-
75
- If you see two `next-server` lineages in `ps`, check:
76
-
77
- ```bash
78
- ps aux | grep next-server | grep -v grep
79
- lsof -p <pid> | grep '\.next/dev/cache' | head -5 # which checkout owns it
80
- ```
81
-
82
- Common dual-server scenarios:
83
-
84
- | Scenario | Symptom | Fix |
85
- |----------|---------|-----|
86
- | Two checkouts of the same monorepo (e.g. `DS_Workspace/` and `Exxat-DS-Workspace/`) both running `pnpm dev:web` | Two `next-server` parents, both in `apps/web/.next/...` paths but on different absolute roots | Quit one. Pin to a single checkout per machine. |
87
- | A customer app (e.g. `test-9`) + the monorepo `apps/web` running at the same time | Different cache hashes (`ee6e79b1/`) under different roots | Stop whichever you're not actively touching: `pm2 stop exxat-ds` or `Ctrl+C` |
88
- | A stale pm2 daemon from a prior `nvm use 22` session left running after upgrading to Node 24 | One Node-22 + one Node-24 dev server | `pm2 delete exxat-ds` then `pnpm dev:daemon` to re-launch under Node 24 |
89
- | `next build` running in another tab while `next dev` is up | Three or four `next-server` for the duration of the build | Wait for the build, or kill the dev server until the build is done |
90
-
91
- ## 5. Two `next-server` processes per app is normal
92
-
93
- Next 16 splits dev into:
94
-
95
- - **`next-server` (main)** — HTTP entry, watcher, router.
96
- - **`next-server` (render worker)** — RSC + SSR pipeline.
97
-
98
- Both inherit `NODE_OPTIONS`, so the 6 GB cap applies to **each**. With the
99
- config in this app the totals stabilize around **~1.4 GB + ~0.6 GB ≈ 2 GB**.
100
- If you ever see a third or fourth `next-server`, that's the build worker
101
- spawning during a route compile — they exit when the build completes.
102
-
103
- ## 6. Diagnose a memory regression
104
-
105
- When dev RSS climbs past 4 GB and stays there:
106
-
107
- ```bash
108
- # First, check the boring stuff
109
- du -sh .next # > 2 GB → run pnpm clean:cache
110
- ps aux | grep next-server | grep -v grep | wc -l # > 2 lines → you have two dev servers
111
- lsof -p <pid> | wc -l # > 5000 FDs → cache is mmap-flooding
112
-
113
- # Then profile a 60s window — heap snapshots to .next/diagnostics/
114
- pnpm dev:profile
115
-
116
- # Open the latest .heapprofile in Chrome DevTools → Memory → "Load"
117
- ls -lt .next/diagnostics | head -3
118
- ```
119
-
120
- Common culprits and their signatures:
121
-
122
- | Symptom | Likely cause | Fix |
123
- |---------|--------------|-----|
124
- | `.next` is > 2 GB on disk; many `.meta` files | Turbopack FS cache bloat over weeks | `pnpm clean:cache` then `pnpm dev` (see §3) |
125
- | Two or more `next-server` parents in `ps` | Dual dev server across checkouts / apps | Stop the one you aren't using (see §4) |
126
- | Many copies of `lucide-react.js` / `recharts.js` retained in heap | Missing entry in `optimizePackageImports` | Add the package to the list (knob 4) |
127
- | Compiled chunks for routes you never visited | `preloadEntriesOnStart` is `true` | Set to `false` (knob 3) |
128
- | Heap grows on every HMR cycle, never shrinks | RSC HMR cache + import.meta.hot leak | `experimental.serverComponentsHmrCache: false` (try only if knob 3 is already on) |
129
- | Single retainer chain holds 100 MB+ | A module-level `Map` / `Set` in app code never gets cleared | Move to request-scoped storage |
130
- | tsserver alone is > 1.5 GB | TS strict + large lib check | `skipLibCheck: true` (already on), drop `allowJs` if not needed |
131
- | Turbopack worker RSS keeps growing past 4 GiB | `turbopack.memoryLimit` not set | Apply knob 2 |
132
-
133
- ## 7. Node 24 features we leverage
134
-
135
- Node 24 (LTS-track) is required by `engines.node` in `package.json` and
136
- pinned in `.nvmrc`. Specifically:
137
-
138
- - **V8 13.6 with Maglev JIT default-on** — faster startup, lower base heap.
139
- Steady-state RSS for the `next dev` parent is ~12% lower vs Node 22.
140
- - **Improved incremental marking GC** — fewer long pauses during HMR; the
141
- perceived "stutter" when saving a large file is gone.
142
- - **Permission model (`--permission`)** — not enabled in dev (Next reads
143
- too many paths to make `--permission` ergonomic), but available for
144
- hardening production scripts.
145
- - **`node --run <script>`** — replaces `npm run` for one-off scripts with
146
- ~30 ms less per-invocation overhead. Use it in any CI step that runs a
147
- workspace script directly: `node --run typecheck`. Not yet wired into
148
- this repo's pm2 / package scripts because pm2 itself spawns `npm`.
149
- - **`--heap-prof` / `--cpu-prof` always-on** — the `dev:profile` script in
150
- `package.json` uses these to drop snapshots into `.next/diagnostics/`
151
- without any third-party profiler dependency.
152
- - **`--experimental-strip-types`** — Node 24 can run `.ts` files directly,
153
- but Next still uses tsc + swc, so this only helps for stand-alone
154
- scripts under `apps/web/scripts/` (e.g. `fa:subset-audit`) if they're
155
- converted from `.mjs` to `.ts`.
156
- - **Smaller initial heap allocations** — V8 13.6 starts with ~50 MB less
157
- reserved arena vs V8 12.x. Most visible in fast CI test runs.
158
-
159
- ## 8. Anti-patterns
160
-
161
- | Anti-pattern | Why it's wrong |
162
- |--------------|----------------|
163
- | Setting `NODE_OPTIONS` only in `.env.local` | `.env.local` is read by Next, not by Node. The dev server's own runtime never sees it. |
164
- | Setting `--max-old-space-size` to the system RAM amount | Defeats the cap. The point is to force GC pressure, not raise the ceiling. |
165
- | Running multiple `next dev` instances on the same machine without unique ports | Each instance ignores the others' caches and the total RSS is N × steady-state. Use the dedicated `dev:3001` / `dev:3005` scripts. |
166
- | `NODE_OPTIONS=--inspect` in normal dev | Allocates an extra inspector arena per process (~200 MB). Use only when actively debugging. |
167
- | Adding `nodemon` on top of `next dev` | Next has its own watcher; nodemon doubles the file-system event handlers. |
168
- | Importing `@exxatdesignux/ui` from the package root for every icon | Defeats `optimizePackageImports`. Always import from the leaf path the DS exposes. |
169
- | Running pm2 without `max_memory_restart` | A wedged worker stays wedged. The 7 GB ceiling lets pm2 recycle before the OS swaps. |
170
- | Disabling `turbopackFileSystemCacheForDev` because "cache is the problem" | Cold starts go from ~1s to ~15–30s every restart. Bust with `pnpm clean:cache` instead. |
171
- | Two checkouts of the same monorepo both running dev | Caches don't share — 2× total RSS. Pin to one checkout per machine. |
172
-
173
- ## 9. Upgrading an existing customer app
174
-
175
- If your app was scaffolded before `@exxatdesignux/ui@0.5.10`, copy the diffs
176
- below from `node_modules/@exxatdesignux/ui/template/`:
177
-
178
- 1. `.nvmrc` — set to `24`.
179
- 2. `package.json` — `engines.node: ">=24.0.0"` + the `NODE_OPTIONS` /
180
- `NEXT_TELEMETRY_DISABLED` prefix on every `dev*` script + the new
181
- `dev:profile`, `dev:fresh`, `clean`, `clean:cache` scripts.
182
- 3. `next.config.mjs` — add the `turbopack: { memoryLimit }` block, the
183
- expanded `experimental.optimizePackageImports` array,
184
- `experimental.preloadEntriesOnStart: false`,
185
- `experimental.webpackMemoryOptimizations: true`, and the
186
- `onDemandEntries` block.
187
- 4. `tsconfig.json` — `target: ES2022` + `assumeChangesOnlyAffectDirectDependencies: true`.
188
- 5. `ecosystem.config.cjs` (if used) — add the `env` block with
189
- `NODE_OPTIONS` + `NEXT_TELEMETRY_DISABLED` and `max_memory_restart: "7G"`.
190
- 6. Run `nvm install 24 && nvm use` (or your Node manager equivalent).
191
- 7. **First run after upgrading:** `pnpm clean && pnpm dev` to drop the
192
- pre-0.5.10 Turbopack cache (it was written without the memory cap and
193
- may carry stale mmap layouts).
194
-
195
- Restart the dev server. You should see steady-state RSS settle in the
196
- 1.5–2 GB range within ~30 s of the first navigation. If you still see
197
- > 3 GB per process: re-read §4 — you almost certainly have a second
198
- dev server running somewhere.
199
-
200
- ## See also
201
-
202
- - [`HANDBOOK.md`](./HANDBOOK.md) — workspace orientation
203
- - [`consumer-upgrade-checklist.md`](https://github.com/ExxatDesign/Exxat-DS-Workspace/blob/main/packages/ui/consumer-extras/patterns/consumer-upgrade-checklist.md) — what to do after `pnpm add @exxatdesignux/ui@latest`
204
- - [Next.js — Reducing dev memory usage](https://nextjs.org/docs/app/building-your-application/optimizing/memory-usage)
205
- - [Node.js — Diagnostics](https://nodejs.org/api/cli.html#--heap-profheap_dir)
206
- - [V8 — Maglev](https://v8.dev/blog/maglev)
@@ -1,153 +0,0 @@
1
- # Exxat DS — Reference implementations
2
-
3
- > When a rule says "see the canonical hub" or "see the catalog page", **this is the index**. Open the file. Copy. Don't reinvent.
4
-
5
- Reference pages are the **canonical working implementations** of a pattern. They're the source of truth that rules + blueprints summarize. If a rule conflicts with a reference page, the bug is in the rule — open a PR.
6
-
7
- ---
8
-
9
- ## How to use this page
10
-
11
- 1. Find the row that matches the pattern you're building.
12
- 2. Open the **Reference page** column — that file is the template.
13
- 3. Read the linked **Blueprint** for the framework-agnostic spec.
14
- 4. Read the linked **Rule** for the binding MUST / MUST NOT.
15
- 5. Read the linked **Pattern** for the long-form "why".
16
-
17
- If you find yourself diverging from the reference page, ask **why** before shipping.
18
-
19
- ---
20
-
21
- ## Primary hubs
22
-
23
- | Pattern | Reference page | Blueprint | Rule(s) | Pattern doc |
24
- |---|---|---|---|---|
25
- | Full hub: table + board + dashboard + list + paginated + conditional rules + dashboard customize | `apps/web/components/library-table.tsx` + `library-hub-client.tsx` | [`list-page-template`](./blueprints/list-page-template.md), [`data-table`](./blueprints/data-table.md), [`board-card`](./blueprints/board-card.md), [`key-metrics`](./blueprints/key-metrics.md) | [`exxat-data-tables`](../../../.cursor/rules/exxat-data-tables.mdc), [`exxat-list-page-connected-views`](../../../.cursor/rules/exxat-list-page-connected-views.mdc), [`exxat-centralized-list-dataset`](../../../.cursor/rules/exxat-centralized-list-dataset.mdc) | [`data-views-pattern`](./data-views-pattern.md) |
26
- | Hub with secondary panel scope (folder rail) | `apps/web/components/library-hub-client.tsx` + `library-secondary-nav.tsx` | [`list-page-template`](./blueprints/list-page-template.md) | [`exxat-primary-nav-secondary-panel`](../../../.cursor/rules/exxat-primary-nav-secondary-panel.mdc), [`exxat-library-hub-header`](../../../.cursor/rules/exxat-library-hub-header.mdc) | [`library-hub-header-pattern`](./library-hub-header-pattern.md) |
27
- | Hub with secondary panel scope (URL-driven category rail) — **smallest** secondary-panel reference + built-in pagination chrome | `apps/web/components/tokens-themes-client.tsx` + `tokens-secondary-nav.tsx` | [`list-page-template`](./blueprints/list-page-template.md) | [`exxat-primary-nav-secondary-panel`](../../../.cursor/rules/exxat-primary-nav-secondary-panel.mdc) | [`shell-surface-elevation-pattern`](./shell-surface-elevation-pattern.md) |
28
- | Cell-pattern catalog — **18 SaaS cell patterns** via custom `columnDefs`; **seven views** via **`LibraryTable`** (same Add view as Library). | `apps/web/components/columns-showcase.tsx` + `columns-client.tsx` | [`list-page-template`](./blueprints/list-page-template.md), [`data-table`](./blueprints/data-table.md), [`hub-supported-views-pattern`](./hub-supported-views-pattern.md) | [`exxat-data-tables`](../../../.cursor/rules/exxat-data-tables.mdc), [`exxat-hub-supported-views`](../../../.cursor/rules/exxat-hub-supported-views.mdc) | — |
29
-
30
- > **First-time hub builder:** copy **`library-table.tsx`** + **`library-client.tsx`** for seven-view wiring; use **`columns-showcase.tsx`** for custom columns on **`LibraryItem`**; use **`tokens-themes-client.tsx`** + **`tokens-hub-auxiliary-views.tsx`** for token rows. Read **`hub-supported-views-pattern.md`** before changing Add view.
31
-
32
- ---
33
-
34
- ## Cell primitives (importable)
35
-
36
- Every cell renderer below is exported from `@/components/data-views` (re-exported from `apps/web/components/data-views/table-cells.tsx`). The live catalog page is `/columns`. **Do not re-implement these inside a `ColumnDef['cell']`** — import the name.
37
-
38
- | Cell | Renders | Import |
39
- |------|---------|--------|
40
- | `ProgressCell` | Track + filled bar with auto-tone in thirds; `value`, `max`, `tone`, `label` | `@/components/data-views` |
41
- | `CurrencyCell` | Right-aligned `tabular-nums`; `value`, `currency` (USD), `locale`, `maximumFractionDigits` | same |
42
- | `NumericCell` | Right-aligned plain count; `value`, `fractionDigits` | same |
43
- | `RatingCell` | N of `max` FA stars + value; color + glyph paired (WCAG 1.4.1) | same |
44
- | `SignalBarsCell` | Wi-Fi-style ordinal bars; `level`, `max`, `tone`, `label` (required) | same |
45
- | `BooleanToggleCell` | Inline `ToggleSwitch` with `checked` + `onChange(next)`; stops row click propagation | same |
46
- | `AttachmentCountCell` | Paperclip + count chip; muted dash on `0` | same |
47
- | `ExternalLinkCell` | Truncated host + new-tab icon; `url`, `label?`; `Tip` shows full URL | same |
48
- | `RelativeTimeCell` | "3 hours ago" with `Tip(absolute)`; `iso`, `now?` (deterministic snapshots) | same |
49
- | `PeopleAvatarRailCell` | Face rail with `+N` overflow; `people: PersonStub[]`, **non-overlapping** | same |
50
- | `PillCell` | Outlined badge + leading FA icon; `label`, `icon?` | same |
51
- | `TagListCell` | Soft badges with `+N` overflow; `tags`, `visibleMax?`, `formatLabel?` | same |
52
- | `RowActionsCell<TRow>` | `⋯` overflow dropdown; `row`, `actions: RowActionDef<TRow>[]` (label, icon, onSelect, variant, shortcut, disabled) | same |
53
- | `EMPTY_DASH` | Aria-hidden `—` placeholder for null/undefined cells | same |
54
-
55
- **Anti-references** (do NOT copy):
56
- - ❌ Inlining `Intl.NumberFormat`, `[1,2,3,4,5].map(s => …)` star loops, raw `<a target="_blank">`, `new URL(…).hostname`, or `Intl.RelativeTimeFormat` inside a `cell:`. Import the named cell.
57
- - ❌ Re-implementing `RowActionsCell` per hub with a custom `DropdownMenu`. The generic `RowActionsCell<TRow>` covers `Open / Edit / Duplicate / Archive`-style menus.
58
-
59
- ---
60
-
61
- ## Hub chrome
62
-
63
- | Pattern | Reference page | Blueprint | Rule(s) |
64
- |---|---|---|---|
65
- | Page header — primary hub | `apps/web/components/library-page-header.tsx` | [`page-header`](./blueprints/page-header.md) | [`exxat-collaboration-access`](../../../.cursor/rules/exxat-collaboration-access.mdc), [`exxat-mono-ids`](../../../.cursor/rules/exxat-mono-ids.mdc) |
66
- | Page header — entity / record (no view tabs) | `apps/web/components/page-header.tsx` (variants) | [`page-header`](./blueprints/page-header.md) | — |
67
- | KPI flat band on a hub (clickable tiles + insight card) | `apps/web/components/columns-client.tsx`, `apps/web/components/tokens-themes-client.tsx` | [`key-metrics`](./blueprints/key-metrics.md) | [`exxat-kpi-flat-band`](../../../.cursor/rules/exxat-kpi-flat-band.mdc), [`exxat-kpi-max-four`](../../../.cursor/rules/exxat-kpi-max-four.mdc), [`exxat-kpi-trends`](../../../.cursor/rules/exxat-kpi-trends.mdc) |
68
- | Properties drawer wiring (auto via `HubTable`) | `apps/web/components/library-table.tsx`, `apps/web/components/columns-showcase.tsx` | — | [`exxat-table-properties-drawer`](../../../.cursor/rules/exxat-table-properties-drawer.mdc) |
69
- | Pagination chrome (auto via `HubTable` when `pagination` is toggled) | `apps/web/components/columns-showcase.tsx`, `apps/web/components/tokens-themes-client.tsx` | [`data-table`](./blueprints/data-table.md) | [`exxat-data-tables`](../../../.cursor/rules/exxat-data-tables.mdc) |
70
- | Export drawer + ⋯ menu | `apps/web/components/library-page-header.tsx` + `export-drawer.tsx` | — | [`exxat-drawer-vs-dialog`](../../../.cursor/rules/exxat-drawer-vs-dialog.mdc) |
71
-
72
- ---
73
-
74
- ## Board, list, dashboard views
75
-
76
- | Pattern | Reference page | Blueprint | Rule(s) |
77
- |---|---|---|---|
78
- | Board card (kanban) | `apps/web/components/library-board-view.tsx` | [`board-card`](./blueprints/board-card.md) | [`exxat-board-cards`](../../../.cursor/rules/exxat-board-cards.mdc), [`exxat-card-vs-list-rows`](../../../.cursor/rules/exxat-card-vs-list-rows.mdc) |
79
- | List row (single-column) | `apps/web/components/library-table.tsx` (`renderListRow`) | [`board-card`](./blueprints/board-card.md) (row layout) | [`exxat-card-vs-list-rows`](../../../.cursor/rules/exxat-card-vs-list-rows.mdc) |
80
- | Dashboard view with charts + KPI band | `apps/web/components/library-dashboard-charts.tsx` | [`key-metrics`](./blueprints/key-metrics.md) | [`exxat-dashboard-view-charts`](../.cursor/rules/exxat-dashboard-view-charts.mdc) |
81
-
82
- ---
83
-
84
- ## Search
85
-
86
- | Pattern | Reference page | Rule(s) | Pattern doc |
87
- |---|---|---|---|
88
- | Global command palette (⌘K) | `apps/web/components/command-menu.tsx` + `lib/command-menu-config.ts` | [`exxat-command-menu`](../../../.cursor/rules/exxat-command-menu.mdc) | [`command-menu-pattern`](./command-menu-pattern.md) |
89
- | Dedicated search (landing + results) | `apps/web/components/dedicated-search-*.tsx` | [`exxat-dedicated-search-surfaces`](../../../.cursor/rules/exxat-dedicated-search-surfaces.mdc) | — |
90
- | In-table search (toolbar) | wired by `HubTable` automatically | [`exxat-data-tables`](../../../.cursor/rules/exxat-data-tables.mdc) | [`data-views-pattern`](./data-views-pattern.md) |
91
-
92
- ---
93
-
94
- ## Collaboration
95
-
96
- | Pattern | Reference page | Rule(s) | Pattern doc |
97
- |---|---|---|---|
98
- | Face rail + invite drawer | `apps/web/components/collaboration-access-flow.tsx`, `invite-collaborators-drawer.tsx` | [`exxat-collaboration-access`](../../../.cursor/rules/exxat-collaboration-access.mdc) | [`collaboration-access-pattern`](./collaboration-access-pattern.md) |
99
-
100
- ---
101
-
102
- ## Overlays and confirmations
103
-
104
- | Pattern | Reference page | Rule(s) | Pattern doc |
105
- |---|---|---|---|
106
- | Side drawer (long auxiliary flow) | `apps/web/components/export-drawer.tsx`, `invite-collaborators-drawer.tsx`, `apps/web/components/table-properties/drawer.tsx` | [`exxat-drawer-vs-dialog`](../../../.cursor/rules/exxat-drawer-vs-dialog.mdc), [`exxat-page-vs-drawer`](../../../.cursor/rules/exxat-page-vs-drawer.mdc) | [`drawer-vs-dialog-pattern`](./drawer-vs-dialog-pattern.md) |
107
- | Dialog (blocking short confirm / destructive) | `apps/web/components/ui/alert-dialog.tsx` consumers (search `<AlertDialog`) | [`exxat-drawer-vs-dialog`](../../../.cursor/rules/exxat-drawer-vs-dialog.mdc) | [`drawer-vs-dialog-pattern`](./drawer-vs-dialog-pattern.md) |
108
- | Coach mark / onboarding | `apps/web/lib/coach-mark-registry.ts` consumers (Library dashboard customize) | — | — |
109
-
110
- ---
111
-
112
- ## Settings, tokens, themes
113
-
114
- | Pattern | Reference page | Rule(s) |
115
- |---|---|---|
116
- | Settings page (preferences + sections) | `apps/web/app/(app)/settings/page.tsx` | — |
117
- | Tokens & themes hub (secondary panel + categories + visualizers) | `apps/web/components/tokens-themes-client.tsx`, `tokens-themes-section.tsx`, `tokens-secondary-nav.tsx` | [`exxat-token-discipline`](../../../.cursor/rules/exxat-token-discipline.mdc), [`exxat-primary-nav-secondary-panel`](../../../.cursor/rules/exxat-primary-nav-secondary-panel.mdc) |
118
-
119
- ---
120
-
121
- ## Anti-references (what NOT to copy)
122
-
123
- These exist but are **not** canonical. They predate a rule, are scoped to a one-off, or use a legacy primitive. **Don't copy from them.**
124
-
125
- | Anti-reference | Why not | What to use instead |
126
- |---|---|---|
127
- | Raw `<DataTable>` mounted directly in `ListPageTemplate.renderContent` (historical) | Loses filter chips, Properties drawer, and the new built-in pagination chrome | `HubTable` (see `columns-showcase.tsx`, `tokens-themes-client.tsx`, `library-table.tsx`) |
128
- | Hub-side `PaginationBar` + `CountSyncer` wiring around `DataTable` (the old Placements pattern) | `HubTable` now mounts pagination chrome automatically when the hub passes `pagination` + `onPaginationChange` | Pass `pagination` / `onPaginationChange` / optional `paginationInitialPageSize` / `paginationPageSizeOptions` to `HubTable` |
129
- | Custom search input above a `DataTable` | `HubTable`'s toolbar already does this; duplicating leads to drift | Configure `ColumnDef.filter` + use `HubTable` |
130
- | `toast()` / Sonner / snackbar | Forbidden — see [`exxat-no-toast.mdc`](../../../.cursor/rules/exxat-no-toast.mdc) | `LocalBanner` / `SystemBanner` or inline status |
131
- | Negative-margin overlapping avatars | Forbidden — see [`exxat-person-identity-display.mdc`](../../../.cursor/rules/exxat-person-identity-display.mdc) | `AvatarGroup` (gapped by default) |
132
- | Legacy customer sidebar screenshots (rainbow section text, pink wash, custom pills) | Visual spec for old product — **not** Exxat DS chrome | **`AppSidebar`** + **`SidebarMenuButton`** + **`lib/mock/navigation.tsx`** — [`exxat-sidebar-shell.mdc`](../../../.cursor/rules/exxat-sidebar-shell.mdc) |
133
- | Uploaded screenshots / mockups treated as pixel spec | Images show **intent** (labels, fields, flows) — DS blueprints + reference hubs define **implementation** | [`exxat-no-image-pixel-copy.mdc`](../../../.cursor/rules/exxat-no-image-pixel-copy.mdc) + **`component-selection-guide.md`** |
134
-
135
- ---
136
-
137
- ## Adding a new reference page
138
-
139
- If you build a pattern that **other hubs will copy**, list it here. A reference page is canonical when:
140
-
141
- 1. It satisfies the matching blueprint or rule end-to-end.
142
- 2. It passes the §13 PR-review checklist in [`AGENTS.md`](../AGENTS.md).
143
- 3. The file has a top-level doc comment that names what it's the reference for (e.g. *"Tokens & themes hub — table + secondary-panel category rail; thin wrapper around `<HubTable>` with the new built-in pagination chrome."*).
144
- 4. The matching rule's "Reference implementations" list points back to it.
145
-
146
- ---
147
-
148
- ## See also
149
-
150
- - [`HANDBOOK.md`](./HANDBOOK.md) — start-here doc map
151
- - [`blueprints/README.md`](./blueprints/README.md) — what a blueprint is
152
- - [`component-selection-guide.md`](./component-selection-guide.md) — decision tree across blueprints
153
- - [`apps/web/AGENTS.md` §13](../AGENTS.md) — full PR-review checklist
@@ -1,52 +0,0 @@
1
- # Shell surface elevation (sidebar · secondary panel · page)
2
-
3
- > **Tokens:** `app/globals.css` — `--sidebar`, `--secondary-panel-bg`, `--background`, `--brand-tint*`.
4
- > **Shell:** `components/templates/nested-secondary-panel-shell.tsx` — `bg-[var(--secondary-panel-bg)]`.
5
- > **Cursor:** `.cursor/rules/exxat-primary-nav-secondary-panel.mdc` · `.cursor/skills/exxat-primary-nav-secondary-panel/SKILL.md`
6
-
7
- ## Stack (back → front)
8
-
9
- | Level | Surface | Token / class | Notes |
10
- |-------|---------|---------------|--------|
11
- | **0** | Primary icon rail + app chrome | `--sidebar` (= `--brand-tint` on light product themes) | Darkest brand wash in the shell |
12
- | **1** | Nested secondary panel (Library, etc.) | `--secondary-panel-bg` | **Lighter** than level 0; **same product hue** |
13
- | **2** | Main page / inset content | `--background` | Lightest (white canvas light; dark charcoal dark) |
14
-
15
- **MUST** derive secondary panel fill from **`--brand-tint` / `--brand-tint-light`**, not a fixed rose or neutral grey. When the user selects **Exxat One**, both levels use **indigo hue ~286**; **Prism** uses **rose ~342**; **`theme-custom`** follows `--custom-product-brand-color` via `ProductProvider`.
16
-
17
- ## OKLCH formulas (light)
18
-
19
- ```css
20
- --sidebar: var(--brand-tint);
21
- --secondary-panel-bg: color-mix(in oklch, var(--background) 40%, var(--brand-tint-light) 60%);
22
- ```
23
-
24
- ## OKLCH formulas (dark)
25
-
26
- ```css
27
- --secondary-panel-bg: color-mix(in oklch, var(--card) 32%, var(--brand-tint) 68%);
28
- ```
29
-
30
- Per-product **dark** theme blocks (`.theme-one.dark`, `.theme-prism.dark`, …) set **`--brand-tint-light`** where needed so mixes stay on-hue.
31
-
32
- ## Implementation
33
-
34
- - **`NestedSecondaryPanelShell`** — `bg-[var(--secondary-panel-bg)]`, `ring-sidebar-border` (not generic `ring-border` alone).
35
- - **Do not** set secondary panel to `bg-sidebar` (same as level 0 — loses elevation).
36
- - **Do not** use `color-mix(… var(--sidebar) …)` without brand tokens if it drifts from active product theme.
37
-
38
- ## Product theme classes
39
-
40
- - **`theme-one`** / **`theme-prism`** / **`theme-assessment`** — built-in OKLCH brand scales in `globals.css`.
41
- - **`theme-custom`** — when user picks an accent in Settings; driven by `--custom-product-brand-color`.
42
- - **`ProductProvider`** — applies `theme-one` vs `theme-prism` vs `theme-custom`; accent override only when it **differs** from the product default (see `accentOverrideActive` in `contexts/product-context.tsx`).
43
-
44
- ## Logo vs chrome
45
-
46
- - **Chrome** (sidebar, secondary panel, KPI glow) follows **`--brand-tint` / `--brand-color`** per product.
47
- - **Logo art** (mark + suffix) stays **Exxat pink** via `wordmarkColor` / `markGradient` in `lib/product-brand.ts` — recolouring a product in Settings changes **theme accent**, not corporate logo pink.
48
-
49
- ## See also
50
-
51
- - **`docs/kpi-flat-band-pattern.md`** — flat KPI strip uses brand glow only, no surface
52
- - **`apps/web/AGENTS.md` §4.6** — secondary panel wiring