@exxatdesignux/ui 0.5.10 → 0.5.12

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 (478) hide show
  1. package/CHANGELOG.md +37 -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 +13 -2
  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 +92 -12
  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/cursor-skills/exxat-senior-ux/SKILL.md +70 -17
  47. package/consumer-extras/patterns/command-menu-pattern.md +2 -2
  48. package/consumer-extras/patterns/consumer-upgrade-checklist.md +1 -1
  49. package/consumer-extras/patterns/jobs/README.md +1 -1
  50. package/consumer-extras/patterns/perf-memory-pattern.md +115 -150
  51. package/consumer-extras/scripts/dev-guard.mjs +156 -0
  52. package/consumer-extras/templates/README.md +23 -0
  53. package/consumer-extras/templates/handoff.md +190 -0
  54. package/dist/hooks/use-app-theme.d.ts +1 -1
  55. package/package.json +2 -2
  56. package/{template → template-vite}/.claude/skills/exxat-ds-skill/SKILL.md +184 -23
  57. package/template-vite/.cursor/rules/exxat-accessibility.mdc +40 -0
  58. package/template-vite/.cursor/rules/exxat-board-cards.mdc +28 -0
  59. package/template-vite/.cursor/rules/exxat-breadcrumbs-no-back.mdc +22 -0
  60. package/template-vite/.cursor/rules/exxat-card-vs-list-rows.mdc +22 -0
  61. package/template-vite/.cursor/rules/exxat-centralized-list-dataset.mdc +46 -0
  62. package/template-vite/.cursor/rules/exxat-collaboration-access.mdc +33 -0
  63. package/{template → template-vite}/.cursor/rules/exxat-command-menu.mdc +5 -5
  64. package/template-vite/.cursor/rules/exxat-data-tables.mdc +47 -0
  65. package/template-vite/.cursor/rules/exxat-dedicated-search-surfaces.mdc +32 -0
  66. package/template-vite/.cursor/rules/exxat-drawer-vs-dialog.mdc +23 -0
  67. package/template-vite/.cursor/rules/exxat-ds-agents.mdc +87 -0
  68. package/template-vite/.cursor/rules/exxat-fontawesome-icons.mdc +32 -0
  69. package/template-vite/.cursor/rules/exxat-hub-supported-views.mdc +56 -0
  70. package/{template → template-vite}/.cursor/rules/exxat-kbd-shortcuts.mdc +1 -0
  71. package/template-vite/.cursor/rules/exxat-kpi-flat-band.mdc +29 -0
  72. package/template-vite/.cursor/rules/exxat-kpi-max-four.mdc +22 -0
  73. package/template-vite/.cursor/rules/exxat-kpi-trends.mdc +32 -0
  74. package/template-vite/.cursor/rules/exxat-library-hub-header.mdc +29 -0
  75. package/template-vite/.cursor/rules/exxat-list-page-connected-views.mdc +28 -0
  76. package/template-vite/.cursor/rules/exxat-list-page-view-shells.mdc +32 -0
  77. package/{template → template-vite}/.cursor/rules/exxat-mono-ids.mdc +1 -0
  78. package/template-vite/.cursor/rules/exxat-nav-single-active.mdc +32 -0
  79. package/template-vite/.cursor/rules/exxat-no-image-pixel-copy.mdc +46 -0
  80. package/template-vite/.cursor/rules/exxat-no-slds-leakage.mdc +84 -0
  81. package/{template → template-vite}/.cursor/rules/exxat-no-toast.mdc +2 -2
  82. package/template-vite/.cursor/rules/exxat-no-vaul.mdc +26 -0
  83. package/template-vite/.cursor/rules/exxat-page-header-actions.mdc +33 -0
  84. package/{template → template-vite}/.cursor/rules/exxat-page-vs-drawer.mdc +5 -3
  85. package/template-vite/.cursor/rules/exxat-person-identity-display.mdc +48 -0
  86. package/template-vite/.cursor/rules/exxat-primary-nav-secondary-panel.mdc +53 -0
  87. package/template-vite/.cursor/rules/exxat-reuse-before-custom.mdc +37 -0
  88. package/template-vite/.cursor/rules/exxat-sidebar-shell.mdc +41 -0
  89. package/template-vite/.cursor/rules/exxat-table-properties-drawer.mdc +79 -0
  90. package/template-vite/.cursor/rules/exxat-table-row-preview.mdc +25 -0
  91. package/template-vite/.cursor/rules/exxat-tabs-chrome.mdc +33 -0
  92. package/template-vite/.cursor/rules/exxat-token-discipline.mdc +109 -0
  93. package/template-vite/.cursor/rules/exxat-ux-discovery-protocol.mdc +202 -0
  94. package/template-vite/.cursor/rules/exxat-ux-principles.mdc +187 -0
  95. package/template-vite/.cursor/skills/exxat-accessibility/SKILL.md +282 -0
  96. package/template-vite/.cursor/skills/exxat-board-cards/SKILL.md +68 -0
  97. package/template-vite/.cursor/skills/exxat-card-vs-list-rows/SKILL.md +20 -0
  98. package/template-vite/.cursor/skills/exxat-centralized-list-dataset/SKILL.md +99 -0
  99. package/template-vite/.cursor/skills/exxat-collaboration-access/SKILL.md +35 -0
  100. package/template-vite/.cursor/skills/exxat-dedicated-search-surfaces/SKILL.md +45 -0
  101. package/template-vite/.cursor/skills/exxat-drawer-vs-dialog/SKILL.md +20 -0
  102. package/template-vite/.cursor/skills/exxat-ds-skill/SKILL.md +893 -0
  103. package/template-vite/.cursor/skills/exxat-ds-skill/references/accessibility.md +142 -0
  104. package/template-vite/.cursor/skills/exxat-ds-skill/references/coach-marks.md +169 -0
  105. package/template-vite/.cursor/skills/exxat-ds-skill/references/data-table-pattern.md +392 -0
  106. package/template-vite/.cursor/skills/exxat-fontawesome-icons/SKILL.md +31 -0
  107. package/template-vite/.cursor/skills/exxat-kpi-flat-band/SKILL.md +38 -0
  108. package/template-vite/.cursor/skills/exxat-kpi-max-four/SKILL.md +19 -0
  109. package/template-vite/.cursor/skills/exxat-kpi-trends/SKILL.md +29 -0
  110. package/template-vite/.cursor/skills/exxat-list-page-view-shells/SKILL.md +36 -0
  111. package/template-vite/.cursor/skills/exxat-mono-ids/SKILL.md +56 -0
  112. package/template-vite/.cursor/skills/exxat-primary-nav-secondary-panel/SKILL.md +49 -0
  113. package/template-vite/.cursor/skills/exxat-senior-ux/SKILL.md +198 -0
  114. package/template-vite/.cursor/skills/exxat-token-economy/SKILL.md +287 -0
  115. package/template-vite/.cursor/skills/exxat-ux-audit/SKILL.md +303 -0
  116. package/{template → template-vite}/components/ask-leo-sidebar.tsx +10 -8
  117. package/{template → template-vite}/components/command-menu.tsx +1 -1
  118. package/{template → template-vite}/components/data-views/library-folder-tree-branch.tsx +1 -1
  119. package/{template → template-vite}/components/dedicated-search-recents.tsx +1 -1
  120. package/{template → template-vite}/components/dedicated-search-url-composer.tsx +1 -1
  121. package/{template → template-vite}/components/library-client.tsx +1 -1
  122. package/{template → template-vite}/components/library-hub-client.tsx +2 -2
  123. package/{template → template-vite}/components/library-secondary-nav.tsx +2 -2
  124. package/{template → template-vite}/components/library-table.tsx +35 -27
  125. package/{template → template-vite}/components/new-library-item-form.tsx +1 -1
  126. package/{template → template-vite}/components/page-breadcrumb-trail.tsx +1 -1
  127. package/{template → template-vite}/components/settings-client.tsx +1 -1
  128. package/{template → template-vite}/components/sidebar/app-sidebar.tsx +2 -2
  129. package/{template → template-vite}/components/sidebar/nav-main.tsx +1 -1
  130. package/{template → template-vite}/components/sidebar/nav-user.tsx +1 -1
  131. package/{template → template-vite}/components/sidebar/secondary-nav.tsx +1 -1
  132. package/{template → template-vite}/components/system-banner-slot.tsx +1 -1
  133. package/{template → template-vite}/components/templates/discovery-hub-template.tsx +2 -2
  134. package/{template → template-vite}/components/templates/new-focus-template.tsx +1 -1
  135. package/{template → template-vite}/components/tokens-secondary-nav.tsx +2 -2
  136. package/{template → template-vite}/components/tokens-themes-client.tsx +1 -1
  137. package/{template → template-vite}/hooks/use-secondary-panel-hub-nav.ts +1 -1
  138. package/template-vite/index.html +49 -0
  139. package/template-vite/lib/next-compat.tsx +98 -0
  140. package/{template → template-vite}/package.json +15 -27
  141. package/template-vite/scripts/port-next-imports.mjs +70 -0
  142. package/template-vite/src/App.tsx +103 -0
  143. package/template-vite/src/main.tsx +50 -0
  144. package/{template/app/(app)/error.tsx → template-vite/src/pages/_error.tsx} +12 -24
  145. package/{template/app/(app)/loading.tsx → template-vite/src/pages/_loading.tsx} +4 -2
  146. package/template-vite/src/pages/_not-found.tsx +17 -0
  147. package/template-vite/src/pages/dashboard.tsx +48 -0
  148. package/{template/app/(app)/help/page.tsx → template-vite/src/pages/help.tsx} +3 -2
  149. package/{template/app/(app)/library/layout.tsx → template-vite/src/pages/library/_layout.tsx} +18 -16
  150. package/{template/app/(app)/library/all/page.tsx → template-vite/src/pages/library/all.tsx} +1 -1
  151. package/{template/app/(app)/library/new/page.tsx → template-vite/src/pages/library/new.tsx} +12 -18
  152. package/template-vite/src/routes.tsx +72 -0
  153. package/{template/app → template-vite/src/styles}/globals.css +6 -2
  154. package/{template → template-vite}/tsconfig.json +5 -14
  155. package/template-vite/vite.config.ts +52 -0
  156. package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +0 -53
  157. package/template/.agents/skills/shadcn/SKILL.md +0 -242
  158. package/template/.agents/skills/shadcn/agents/openai.yml +0 -5
  159. package/template/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
  160. package/template/.agents/skills/shadcn/assets/shadcn.png +0 -0
  161. package/template/.agents/skills/shadcn/cli.md +0 -257
  162. package/template/.agents/skills/shadcn/customization.md +0 -202
  163. package/template/.agents/skills/shadcn/evals/evals.json +0 -47
  164. package/template/.agents/skills/shadcn/mcp.md +0 -94
  165. package/template/.agents/skills/shadcn/rules/base-vs-radix.md +0 -306
  166. package/template/.agents/skills/shadcn/rules/composition.md +0 -195
  167. package/template/.agents/skills/shadcn/rules/forms.md +0 -192
  168. package/template/.agents/skills/shadcn/rules/icons.md +0 -101
  169. package/template/.agents/skills/shadcn/rules/styling.md +0 -162
  170. package/template/.cursor/rules/exxat-accessibility.mdc +0 -33
  171. package/template/.cursor/rules/exxat-data-tables.mdc +0 -32
  172. package/template/.cursor/rules/exxat-ds-agents.mdc +0 -26
  173. package/template/.cursor/rules/exxat-list-page-connected-views.mdc +0 -16
  174. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +0 -40
  175. package/template/.nvmrc +0 -1
  176. package/template/.prettierignore +0 -7
  177. package/template/Logo/Exxat_Prism.svg +0 -39
  178. package/template/Logo/Exxat_one.svg +0 -36
  179. package/template/app/(app)/dashboard/loading.tsx +0 -18
  180. package/template/app/(app)/dashboard/page.tsx +0 -36
  181. package/template/app/(app)/layout.tsx +0 -77
  182. package/template/app/global-error.tsx +0 -63
  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/exxat-product-logo.tsx +0 -0
  273. /package/{template → template-vite}/components/folder-details-shell.tsx +0 -0
  274. /package/{template → template-vite}/components/form-layout-01.tsx +0 -0
  275. /package/{template → template-vite}/components/hub-tree-panel-view.tsx +0 -0
  276. /package/{template → template-vite}/components/invite-collaborators-drawer.tsx +0 -0
  277. /package/{template → template-vite}/components/key-metrics-ask-leo-bridge.tsx +0 -0
  278. /package/{template → template-vite}/components/key-metrics.tsx +0 -0
  279. /package/{template → template-vite}/components/leo-insight-indicator.tsx +0 -0
  280. /package/{template → template-vite}/components/leo-typing-dots.tsx +0 -0
  281. /package/{template → template-vite}/components/library-board-view.tsx +0 -0
  282. /package/{template → template-vite}/components/library-dashboard-charts.tsx +0 -0
  283. /package/{template → template-vite}/components/library-favorite-button.tsx +0 -0
  284. /package/{template → template-vite}/components/library-new-folder-sheet.tsx +0 -0
  285. /package/{template → template-vite}/components/library-os-folder-view.tsx +0 -0
  286. /package/{template → template-vite}/components/library-page-header.tsx +0 -0
  287. /package/{template → template-vite}/components/library-panel-activator.tsx +0 -0
  288. /package/{template → template-vite}/components/list-hub-status-badge.tsx +0 -0
  289. /package/{template → template-vite}/components/list-page-dashboard-charts.tsx +0 -0
  290. /package/{template → template-vite}/components/onboarding/getting-started.tsx +0 -0
  291. /package/{template → template-vite}/components/onboarding/index.ts +0 -0
  292. /package/{template → template-vite}/components/onboarding/onboarding-01.tsx +0 -0
  293. /package/{template → template-vite}/components/onboarding/onboarding-02.tsx +0 -0
  294. /package/{template → template-vite}/components/onboarding/onboarding-03.tsx +0 -0
  295. /package/{template → template-vite}/components/onboarding/onboarding-04.tsx +0 -0
  296. /package/{template → template-vite}/components/page-header.tsx +0 -0
  297. /package/{template → template-vite}/components/product-switcher.tsx +0 -0
  298. /package/{template → template-vite}/components/product-wordmark.tsx +0 -0
  299. /package/{template → template-vite}/components/settings-appearance-card.tsx +0 -0
  300. /package/{template → template-vite}/components/settings-form-row.tsx +0 -0
  301. /package/{template → template-vite}/components/sidebar/app-sidebar-dynamic.tsx +0 -0
  302. /package/{template → template-vite}/components/sidebar/index.ts +0 -0
  303. /package/{template → template-vite}/components/sidebar/nav-documents.tsx +0 -0
  304. /package/{template → template-vite}/components/sidebar/nav-secondary.tsx +0 -0
  305. /package/{template → template-vite}/components/sidebar/secondary-panel.tsx +0 -0
  306. /package/{template → template-vite}/components/sidebar/sidebar-auto-collapse.tsx +0 -0
  307. /package/{template → template-vite}/components/sidebar/sidebar-auto-open.tsx +0 -0
  308. /package/{template → template-vite}/components/sidebar/sidebar-shell.tsx +0 -0
  309. /package/{template → template-vite}/components/site-header.tsx +0 -0
  310. /package/{template → template-vite}/components/table-properties/column-row.tsx +0 -0
  311. /package/{template → template-vite}/components/table-properties/draggable-list.ts +0 -0
  312. /package/{template → template-vite}/components/table-properties/drawer-button.tsx +0 -0
  313. /package/{template → template-vite}/components/table-properties/drawer.tsx +0 -0
  314. /package/{template → template-vite}/components/table-properties/filter-card.tsx +0 -0
  315. /package/{template → template-vite}/components/table-properties/index.ts +0 -0
  316. /package/{template → template-vite}/components/table-properties/sort-card.tsx +0 -0
  317. /package/{template → template-vite}/components/table-properties/types.ts +0 -0
  318. /package/{template → template-vite}/components/task-list-panel.tsx +0 -0
  319. /package/{template → template-vite}/components/task-priority-badge.tsx +0 -0
  320. /package/{template → template-vite}/components/templates/dedicated-search-landing-template.tsx +0 -0
  321. /package/{template → template-vite}/components/templates/dedicated-search-results-template.tsx +0 -0
  322. /package/{template → template-vite}/components/templates/list-page.tsx +0 -0
  323. /package/{template → template-vite}/components/templates/nested-secondary-panel-shell.tsx +0 -0
  324. /package/{template → template-vite}/components/templates/primary-page-template.tsx +0 -0
  325. /package/{template → template-vite}/components/templates/secondary-panel-hub-template.tsx +0 -0
  326. /package/{template → template-vite}/components/theme-color-sync.tsx +0 -0
  327. /package/{template → template-vite}/components/theme-provider.tsx +0 -0
  328. /package/{template → template-vite}/components/tinted-icon-disc.tsx +0 -0
  329. /package/{template → template-vite}/components/tokens-hub-auxiliary-views.tsx +0 -0
  330. /package/{template → template-vite}/components/tokens-themes-section.tsx +0 -0
  331. /package/{template → template-vite}/components/ui/accordion.tsx +0 -0
  332. /package/{template → template-vite}/components/ui/ai-thinking-surface.tsx +0 -0
  333. /package/{template → template-vite}/components/ui/alert-dialog.tsx +0 -0
  334. /package/{template → template-vite}/components/ui/avatar.tsx +0 -0
  335. /package/{template → template-vite}/components/ui/badge.tsx +0 -0
  336. /package/{template → template-vite}/components/ui/banner.tsx +0 -0
  337. /package/{template → template-vite}/components/ui/breadcrumb.tsx +0 -0
  338. /package/{template → template-vite}/components/ui/button.tsx +0 -0
  339. /package/{template → template-vite}/components/ui/calendar.tsx +0 -0
  340. /package/{template → template-vite}/components/ui/card.tsx +0 -0
  341. /package/{template → template-vite}/components/ui/chart.tsx +0 -0
  342. /package/{template → template-vite}/components/ui/checkbox.tsx +0 -0
  343. /package/{template → template-vite}/components/ui/coach-mark.tsx +0 -0
  344. /package/{template → template-vite}/components/ui/collapsible.tsx +0 -0
  345. /package/{template → template-vite}/components/ui/command.tsx +0 -0
  346. /package/{template → template-vite}/components/ui/context-menu.tsx +0 -0
  347. /package/{template → template-vite}/components/ui/date-picker-field.tsx +0 -0
  348. /package/{template → template-vite}/components/ui/dialog.tsx +0 -0
  349. /package/{template → template-vite}/components/ui/dot-pattern.tsx +0 -0
  350. /package/{template → template-vite}/components/ui/drag-handle-grip.tsx +0 -0
  351. /package/{template → template-vite}/components/ui/dropdown-menu.tsx +0 -0
  352. /package/{template → template-vite}/components/ui/field.tsx +0 -0
  353. /package/{template → template-vite}/components/ui/form.tsx +0 -0
  354. /package/{template → template-vite}/components/ui/hover-card.tsx +0 -0
  355. /package/{template → template-vite}/components/ui/input-group.tsx +0 -0
  356. /package/{template → template-vite}/components/ui/input-mask.tsx +0 -0
  357. /package/{template → template-vite}/components/ui/input.tsx +0 -0
  358. /package/{template → template-vite}/components/ui/kbd.tsx +0 -0
  359. /package/{template → template-vite}/components/ui/label.tsx +0 -0
  360. /package/{template → template-vite}/components/ui/leo-icon.tsx +0 -0
  361. /package/{template → template-vite}/components/ui/payment-card-fields.tsx +0 -0
  362. /package/{template → template-vite}/components/ui/popover.tsx +0 -0
  363. /package/{template → template-vite}/components/ui/radio-group.tsx +0 -0
  364. /package/{template → template-vite}/components/ui/resizable.tsx +0 -0
  365. /package/{template → template-vite}/components/ui/scroll-area.tsx +0 -0
  366. /package/{template → template-vite}/components/ui/select.tsx +0 -0
  367. /package/{template → template-vite}/components/ui/selection-tile-grid.tsx +0 -0
  368. /package/{template → template-vite}/components/ui/separator.tsx +0 -0
  369. /package/{template → template-vite}/components/ui/sheet.tsx +0 -0
  370. /package/{template → template-vite}/components/ui/sidebar.tsx +0 -0
  371. /package/{template → template-vite}/components/ui/skeleton.tsx +0 -0
  372. /package/{template → template-vite}/components/ui/slider.tsx +0 -0
  373. /package/{template → template-vite}/components/ui/sonner.tsx +0 -0
  374. /package/{template → template-vite}/components/ui/status-badge.tsx +0 -0
  375. /package/{template → template-vite}/components/ui/table.tsx +0 -0
  376. /package/{template → template-vite}/components/ui/tabs.tsx +0 -0
  377. /package/{template → template-vite}/components/ui/textarea.tsx +0 -0
  378. /package/{template → template-vite}/components/ui/tip.tsx +0 -0
  379. /package/{template → template-vite}/components/ui/toggle-group.tsx +0 -0
  380. /package/{template → template-vite}/components/ui/toggle-switch.tsx +0 -0
  381. /package/{template → template-vite}/components/ui/toggle.tsx +0 -0
  382. /package/{template → template-vite}/components/ui/tooltip.tsx +0 -0
  383. /package/{template → template-vite}/components/ui/view-segmented-control.tsx +0 -0
  384. /package/{template → template-vite}/components.json +0 -0
  385. /package/{template → template-vite}/contexts/chart-variant-context.tsx +0 -0
  386. /package/{template → template-vite}/contexts/command-menu-context.tsx +0 -0
  387. /package/{template → template-vite}/contexts/dashboard-view-context.tsx +0 -0
  388. /package/{template → template-vite}/contexts/product-context.tsx +0 -0
  389. /package/{template → template-vite}/contexts/system-banner-context.tsx +0 -0
  390. /package/{template → template-vite}/eslint.config.mjs +0 -0
  391. /package/{template → template-vite}/fontawesome-subset.manifest.json +0 -0
  392. /package/{template → template-vite}/hooks/.gitkeep +0 -0
  393. /package/{template → template-vite}/hooks/use-app-theme.ts +0 -0
  394. /package/{template → template-vite}/hooks/use-coach-mark.ts +0 -0
  395. /package/{template → template-vite}/hooks/use-location-hash.ts +0 -0
  396. /package/{template → template-vite}/hooks/use-mobile.ts +0 -0
  397. /package/{template → template-vite}/hooks/use-mod-key-label.ts +0 -0
  398. /package/{template → template-vite}/hooks/use-sidebar-reflow-zoom.ts +0 -0
  399. /package/{template → template-vite}/lib/.gitkeep +0 -0
  400. /package/{template → template-vite}/lib/ask-leo-route-context.ts +0 -0
  401. /package/{template → template-vite}/lib/chart-keyboard-selection.test.ts +0 -0
  402. /package/{template → template-vite}/lib/chart-keyboard-selection.ts +0 -0
  403. /package/{template → template-vite}/lib/chart-line-dash.ts +0 -0
  404. /package/{template → template-vite}/lib/chunk-load-error.ts +0 -0
  405. /package/{template → template-vite}/lib/coach-mark-registry.ts +0 -0
  406. /package/{template → template-vite}/lib/collaborator-access.ts +0 -0
  407. /package/{template → template-vite}/lib/command-menu-config.ts +0 -0
  408. /package/{template → template-vite}/lib/command-menu-search-data.ts +0 -0
  409. /package/{template → template-vite}/lib/conditional-rule-match.ts +0 -0
  410. /package/{template → template-vite}/lib/dashboard-customize-coach-mark.ts +0 -0
  411. /package/{template → template-vite}/lib/dashboard-layout-merge.ts +0 -0
  412. /package/{template → template-vite}/lib/data-list-display-options.ts +0 -0
  413. /package/{template → template-vite}/lib/data-list-persistence.ts +0 -0
  414. /package/{template → template-vite}/lib/data-list-view-registry.ts +0 -0
  415. /package/{template → template-vite}/lib/data-list-view-surface.ts +0 -0
  416. /package/{template → template-vite}/lib/data-list-view.ts +0 -0
  417. /package/{template → template-vite}/lib/data-view-dashboard-storage.ts +0 -0
  418. /package/{template → template-vite}/lib/date-filter.ts +0 -0
  419. /package/{template → template-vite}/lib/dedicated-search-recents.ts +0 -0
  420. /package/{template → template-vite}/lib/dedicated-search-url.ts +0 -0
  421. /package/{template → template-vite}/lib/dev-log.test.ts +0 -0
  422. /package/{template → template-vite}/lib/dev-log.ts +0 -0
  423. /package/{template → template-vite}/lib/discovery-hub.ts +0 -0
  424. /package/{template → template-vite}/lib/editable-target.ts +0 -0
  425. /package/{template → template-vite}/lib/exxat-palette.json +0 -0
  426. /package/{template → template-vite}/lib/exxat-palette.ts +0 -0
  427. /package/{template → template-vite}/lib/floating-sheet-panel.ts +0 -0
  428. /package/{template → template-vite}/lib/full-hub-supported-views.ts +0 -0
  429. /package/{template → template-vite}/lib/hub-connected-view-renderers.ts +0 -0
  430. /package/{template → template-vite}/lib/initials-from-name.ts +0 -0
  431. /package/{template → template-vite}/lib/library-authoring.ts +0 -0
  432. /package/{template → template-vite}/lib/library-dedicated-search.ts +0 -0
  433. /package/{template → template-vite}/lib/library-hub-search.ts +0 -0
  434. /package/{template → template-vite}/lib/library-nav.ts +0 -0
  435. /package/{template → template-vite}/lib/library-recent-searches.ts +0 -0
  436. /package/{template → template-vite}/lib/library-supported-views.ts +0 -0
  437. /package/{template → template-vite}/lib/list-hub-supported-views.ts +0 -0
  438. /package/{template → template-vite}/lib/list-page-table-properties.ts +0 -0
  439. /package/{template → template-vite}/lib/list-status-badges.ts +0 -0
  440. /package/{template → template-vite}/lib/logo-dev.ts +0 -0
  441. /package/{template → template-vite}/lib/mailto.ts +0 -0
  442. /package/{template → template-vite}/lib/mock/dashboard.ts +0 -0
  443. /package/{template → template-vite}/lib/mock/library-folders.ts +0 -0
  444. /package/{template → template-vite}/lib/mock/library-header-collaborators.ts +0 -0
  445. /package/{template → template-vite}/lib/mock/library-inspector.ts +0 -0
  446. /package/{template → template-vite}/lib/mock/library-kpi.ts +0 -0
  447. /package/{template → template-vite}/lib/mock/library.ts +0 -0
  448. /package/{template → template-vite}/lib/mock/navigation.tsx +0 -0
  449. /package/{template → template-vite}/lib/motion-ui.ts +0 -0
  450. /package/{template → template-vite}/lib/product-brand.ts +0 -0
  451. /package/{template → template-vite}/lib/raf-throttle.ts +0 -0
  452. /package/{template → template-vite}/lib/row-height.ts +0 -0
  453. /package/{template → template-vite}/lib/sidebar-state-cookie.ts +0 -0
  454. /package/{template → template-vite}/lib/stock-portrait.ts +0 -0
  455. /package/{template → template-vite}/lib/table-state-lifecycle.ts +0 -0
  456. /package/{template → template-vite}/lib/utils.test.ts +0 -0
  457. /package/{template → template-vite}/lib/utils.ts +0 -0
  458. /package/{template → template-vite}/public/.gitkeep +0 -0
  459. /package/{template → template-vite}/public/Illustration/Rotation.svg +0 -0
  460. /package/{template → template-vite}/public/avatars/user.svg +0 -0
  461. /package/{template/public → template-vite/public/favicon}/favicon.ico +0 -0
  462. /package/{template/app → template-vite/public}/favicon.ico +0 -0
  463. /package/{template → template-vite}/public/folders/icons8-folder-windows-11.svg +0 -0
  464. /package/{template → template-vite}/public/logos/exxat-one.svg +0 -0
  465. /package/{template → template-vite}/public/logos/exxat-prism.svg +0 -0
  466. /package/{template → template-vite}/public/mock-schools/emory.svg +0 -0
  467. /package/{template → template-vite}/public/mock-schools/rush.svg +0 -0
  468. /package/{template → template-vite}/scripts/fontawesome-subset-audit.mjs +0 -0
  469. /package/{template → template-vite}/scripts/pm2-startup-macos.sh +0 -0
  470. /package/{template → template-vite}/skills-lock.json +0 -0
  471. /package/{template/app/(app)/columns/page.tsx → template-vite/src/pages/columns.tsx} +0 -0
  472. /package/{template/app/(app)/library/find/page.tsx → template-vite/src/pages/library/find.tsx} +0 -0
  473. /package/{template/app/(app)/library/page.tsx → template-vite/src/pages/library/index.tsx} +0 -0
  474. /package/{template/app/(app)/library/list/page.tsx → template-vite/src/pages/library/list.tsx} +0 -0
  475. /package/{template/app/(app)/settings/page.tsx → template-vite/src/pages/settings.tsx} +0 -0
  476. /package/{template/app/(app)/tokens-themes/page.tsx → template-vite/src/pages/tokens-themes.tsx} +0 -0
  477. /package/{template → template-vite}/stores/app-store.ts +0 -0
  478. /package/{template → template-vite}/types/react-payment-inputs.d.ts +0 -0
@@ -1,11 +1,16 @@
1
1
  ---
2
2
  name: exxat-senior-ux
3
3
  description: >-
4
- Make the agent behave like a senior UX designer — understand the problem
5
- before designing, study how modern SaaS solves the same job, propose a
6
- brief before writing code, follow principles, know when to break them,
7
- audit your own work. Load FIRST on any design / UI / page / hub / detail /
8
- wizard / settings task, BEFORE opening AGENTS.md or any blueprint.
4
+ Make the agent behave like a senior UX designer — STOP before writing
5
+ code, understand the problem, study how modern SaaS solves the same job,
6
+ propose a design brief, WAIT for user go-ahead, then build. Load FIRST
7
+ on ANY task that decides what a surface should be create, build, design,
8
+ rebuild, redesign, replace, redo, refresh, modernize, re-imagine, "make a
9
+ new version", "instead of what we have", "from scratch" — for any page,
10
+ route, hub, detail view, wizard, settings section, dashboard, dialog,
11
+ sheet, drawer, panel, layout, or significant component. Also load when
12
+ the user attaches a screenshot / mockup / Figma link and asks to build
13
+ it. Load BEFORE opening AGENTS.md, blueprints, or any other DS doc.
9
14
  user-invocable: true
10
15
  ---
11
16
 
@@ -17,15 +22,32 @@ products). You design for the **user's job**, not the user's words.
17
22
 
18
23
  ## When to load this skill
19
24
 
20
- - The user asks for a **new** page, route, hub, detail screen, wizard,
21
- settings section, dashboard, dialog/sheet flow, or significant component.
22
- - The user attaches a screenshot or mockup.
23
- - The user asks "how should I build X" / "design X" / "make it modern".
24
- - Any task where the prompt names a *surface* rather than a single line of
25
- code.
25
+ Load on **any task that decides what a surface should be** whether the
26
+ surface exists today or not. The user's verb is the strongest signal:
26
27
 
27
- Do **not** load on: typo fixes, dependency bumps, ESLint passes, single-class
28
- restyles of an existing surface that already follows DS rules.
28
+ | Phrase in the prompt | Load? |
29
+ |---|---|
30
+ | "create / build / make / add a new page / hub / detail / wizard / dashboard" | **Yes** |
31
+ | "rebuild / redesign / replace / redo / refresh / modernize / re-imagine X" | **Yes** |
32
+ | "make a new version of X" / "instead of what we have currently" / "from scratch" | **Yes** |
33
+ | "design X" / "how should I build X" / "make it modern" | **Yes** |
34
+ | User attaches a screenshot, mockup, Figma link, or legacy app capture | **Yes** |
35
+ | "Move that button up two pixels" / "change copy" / "fix the type error" | **No** |
36
+ | "Bump dep" / "ESLint pass" / "single-class restyle of a DS-compliant page" | **No** |
37
+ | "Add a column to the existing HubTable" / "another filter chip" | **No** *(unless IA changes)* |
38
+
39
+ When in doubt, ask yourself: **"Am I deciding what this surface should be,
40
+ or am I editing what's already decided?"** Decide → load. Edit → don't.
41
+
42
+ ## Hard gate (read this if you remember nothing else)
43
+
44
+ If you loaded this skill, your **next message must be the design brief**
45
+ (template in §3.1). It must NOT also contain `write_file` / `str_replace`
46
+ / `create_file` / edit tool calls. End the turn after the brief with
47
+ "Ready to build — confirm or edit." The user's reply is your green light.
48
+
49
+ Silence, a thumbs-up, or "ok" all count as confirmation. A new design
50
+ question or "actually let's change X" means revise the brief, don't build.
29
51
 
30
52
  ## Mindset (5 lines, memorize)
31
53
 
@@ -38,7 +60,11 @@ restyles of an existing surface that already follows DS rules.
38
60
  5. **The DS is the vocabulary, not the design.** Composition is the means;
39
61
  clarity for the user is the end.
40
62
 
41
- ## The five-step protocol (mandatory on new surfaces)
63
+ ## The five-step protocol (mandatory on any surface decision)
64
+
65
+ The five steps are **sequential checkpoints**, not a single turn. Each
66
+ checkpoint ends with you yielding to the user — except step 4 (Build) and
67
+ step 5 (Audit), which run together.
42
68
 
43
69
  ### 1. Discovery — ask, infer, or state assumptions
44
70
 
@@ -50,10 +76,37 @@ Use the **question bank by surface type** in
50
76
  `.cursor/rules/exxat-ux-discovery-protocol.mdc`.
51
77
 
52
78
  If the user said "no questions, build it", still output the brief + your
53
- assumptions, then build.
79
+ assumptions.
54
80
 
55
81
  ### 2. Research — recognize the pattern, don't reinvent
56
82
 
83
+ Run research **before posting the brief in step 3**, so the brief can name
84
+ specific references. (See research methods below.)
85
+
86
+ ### 3. Synthesis — post the brief and STOP
87
+
88
+ After research, post the brief (template below). **End your turn here** with
89
+ the explicit prompt:
90
+
91
+ > *Ready to build — confirm or edit.*
92
+
93
+ Do **not** call any code-mutating tool (`write_file`, `str_replace`,
94
+ `create_file`, `edit_notebook`, MCP write tools) in this turn. The user's
95
+ next message is your green light.
96
+
97
+ Acceptable confirmations:
98
+
99
+ - Plain `yes`, `proceed`, `ship it`, `LGTM`, `build it`, `go ahead`.
100
+ - Implicit acceptance — a follow-up question that assumes the brief
101
+ (e.g. "and add a section for X").
102
+ - Silence followed by a new design question — treat as accepted.
103
+
104
+ If the user replies with edits ("change the pattern to a sheet", "drop the
105
+ timeline section"), revise the brief and post again. Only build after a
106
+ confirmed brief.
107
+
108
+ ### Research methods (used inside step 2)
109
+
57
110
  1. Check this repo first — does a canonical reference solve the same **job**?
58
111
  See `apps/web/docs/jobs/`.
59
112
  2. If unfamiliar, call **Mobbin** `search_screens` for the **job type**
@@ -67,7 +120,7 @@ assumptions, then build.
67
120
  5. Extract **patterns** (IA, hierarchy, action placement), never pixels
68
121
  (`exxat-no-image-pixel-copy.mdc`).
69
122
 
70
- ### 3. Synthesis output a one-screen brief
123
+ ### 3.1 Brief template (copy verbatim into chat)
71
124
 
72
125
  ```
73
126
  Problem: <one sentence — the user's pain, not the feature>
@@ -82,7 +135,7 @@ Out of scope: <what this surface intentionally does not do>
82
135
  Open questions: <max 2; ideally 0>
83
136
  ```
84
137
 
85
- Then build against the brief. Every decision references it.
138
+ End the turn with: *Ready to build confirm or edit.*
86
139
 
87
140
  ### 4. Build — compose, don't invent
88
141
 
@@ -1,6 +1,6 @@
1
1
  # Global command palette (⌘K)
2
2
 
3
- **Code:** `components/command-menu.tsx`, config **`buildCommandMenuConfig()`** in **`lib/command-menu-config.ts`**, wired in **`app/(app)/layout.tsx`** via **`CommandMenuProvider`**. Searchable row data is built in **`lib/command-menu-search-data.ts`** (not inside the shell component).
3
+ **Code:** `components/command-menu.tsx`, config **`buildCommandMenuConfig()`** in **`lib/command-menu-config.ts`**, wired in **`src/App.tsx`** via **`CommandMenuProvider`**. Searchable row data is built in **`lib/command-menu-search-data.ts`** (not inside the shell component).
4
4
 
5
5
  ## Role
6
6
 
@@ -34,7 +34,7 @@ The command menu is the app’s **global search and AI entry**—one place to ju
34
34
  | Palette UI | `components/command-menu.tsx` |
35
35
  | Static groups + `buildCommandMenuConfig` | `lib/command-menu-config.ts` (`CommandMenuGroup.searchOnly`) |
36
36
  | Row → menu items (placements, etc.) | `lib/command-menu-search-data.ts` |
37
- | Provider + `dataGroups` | `app/(app)/layout.tsx` |
37
+ | Provider + `dataGroups` | `src/App.tsx` |
38
38
 
39
39
  ## Sidebar
40
40
 
@@ -21,7 +21,7 @@ Overwrites only **`.cursor/skills/exxat-*`** and **`docs/exxat-ds/*.md`** (inclu
21
21
 
22
22
  The npm package includes a full Next.js reference under:
23
23
 
24
- **`node_modules/@exxatdesignux/ui/template/`**
24
+ **`node_modules/@exxatdesignux/ui/template-vite/`**
25
25
 
26
26
  Use it when you need to know **what files exist**, **how shims re-export** `@exxatdesignux/ui`, or **what AGENTS / layout** patterns look like for the current release. Porting is manual: diff template vs your repo and apply intentional changes (imports, new components, CSS entrypoints).
27
27
 
@@ -25,7 +25,7 @@ contract.**
25
25
  | **Review a record's full state** | [`record-detail.md`](./record-detail.md) | Students / Placements / Library detail |
26
26
  | **Triage a list of records** (find at-risk / actionable) | *future* | `PlacementsClient`, `ComplianceClient` |
27
27
  | **Compose / create a new record** | *future* | `new-library-item-form.tsx` |
28
- | **Configure preferences or workspace settings** | *future* | `app/(app)/settings/page.tsx` |
28
+ | **Configure preferences or workspace settings** | *future* | `src/views/settings.tsx` |
29
29
  | **Scan many metrics for anomalies** | *future* | Dashboard route, `DashboardTabs` |
30
30
  | **Search / find anything** | *future* | `CommandMenu`, `DedicatedSearch*` |
31
31
  | **Onboarding / first-run setup** | *future* | `getting-started.tsx`, `CoachMark` |
@@ -1,206 +1,171 @@
1
- # Dev memory tuning for Next.js + Node 24
1
+ # Dev memory tuning for Vite + Node 24
2
2
 
3
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.
4
+ > **Companion to:** [`HANDBOOK.md`](./HANDBOOK.md). Read this when `pnpm dev`
5
+ > RSS climbs past ~1.5 GB or when two designers are running dev servers on
6
+ > one machine.
7
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.
8
+ A fresh `pnpm dev` against this app stabilizes around **~250–500 MB RSS**
9
+ with the settings below. Without them or running multiple Vite
10
+ instances against the same monorepo total system memory drifts to
11
+ 1.5 GB+ per process and designers' laptops start to swap.
11
12
 
12
- ## 1. The six knobs
13
+ > **History:** before PR-6 (May 2026) `apps/web` ran on Next.js + Turbopack
14
+ > with a 1.4–4 GB baseline per dev server. Migrating to Vite + react-router
15
+ > dropped the steady-state RSS by **8×** and cold start from 8–12 s to
16
+ > 150–300 ms. The full migration story is in commits `49e9adf` (PR-1) →
17
+ > `d16ec77` (PR-6).
18
+
19
+ ## 1. The four knobs that matter
13
20
 
14
21
  | # | Knob | Why it matters | Where it lives |
15
22
  |---|------|----------------|----------------|
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
23
+ | 1 | `dev-guard` predev hook | Blocks a second `pnpm dev` from booting against the same checkout. The #1 source of memory inflation in practice two parallel Vite servers double total system RSS for zero throughput. | `package.json` `predev*` scripts `exxat-ui dev-guard` (in `packages/ui/consumer-extras/scripts/dev-guard.mjs`) |
24
+ | 2 | `optimizeDeps.include` for hot deps | Pre-bundles `react`, `react-dom`, `react-router-dom` so the first request doesn't trigger a 600+ ms esbuild dep-scan. Drops first-paint TTFB by ~30%. | `vite.config.ts` |
25
+ | 3 | `optimizeDeps.exclude: ["@exxatdesignux/ui"]` | The shared UI package is a pnpm workspace package. Eager pre-bundling fights pnpm's strict node_modules layout (esbuild can't resolve `radix-ui`, `cmdk`, etc. when crawling the package's own `dist/`). Excluding it lets Vite resolve through the consumer's module resolver — which sees peer deps correctly. | `vite.config.ts` |
26
+ | 4 | `resolve.dedupe: ["react", "react-dom", "react-router-dom"]` | Prevents two React instances from being bundled when `apps/web` and `packages/ui` resolve different versions in pnpm. The classic "Invalid hook call" runtime error and a hidden 30+ MB heap duplicate. | `vite.config.ts` |
24
27
 
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
+ `NODE_OPTIONS` is **not** required under Vite V8's default heap is fine
29
+ for a 250–500 MB process. The Next-era `--max-old-space-size=6144` was
30
+ fighting Turbopack's mmap'd FS cache; that whole class of problem is gone.
28
31
 
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.
32
+ ## 2. Don't run two Vite servers against the same checkout
36
33
 
37
- ## 3. Turbopack file-system cache (Next 16.1)
34
+ A single `vite` process (Vite + the React plugin + Tailwind plugin)
35
+ stabilizes at ~280 MB RSS once the route tree is warm. Two parallel
36
+ servers stabilize at ~560 MB, three at ~840 MB — they don't share dep
37
+ caches across processes.
38
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.
39
+ The `predev` hook (`exxat-ui dev-guard`) detects an already-running
40
+ `vite` instance under the same checkout and exits with a friendly
41
+ message instead of starting a second one. Unconditionally honour it —
42
+ do not bypass with `--no-predev` unless you've explicitly killed the
43
+ other server.
40
44
 
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:
45
+ To check what's running:
42
46
 
43
47
  ```bash
44
- du -sh .next
45
- # 3.2G .next
48
+ ps aux | grep -E "vite/bin/vite" | grep -v grep
46
49
  ```
47
50
 
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
+ If you legitimately need two designer servers (e.g. comparing two
52
+ branches side-by-side), use the dedicated alternate ports:
51
53
 
52
54
  ```bash
53
- pnpm clean:cache # removes .next/dev/cache and .next/dev/trace
54
- pnpm dev:fresh # bust + restart in one command
55
+ pnpm dev # http://localhost:3000
56
+ pnpm dev:3001 # http://localhost:3001
57
+ pnpm dev:3005 # http://localhost:3005
55
58
  ```
56
59
 
57
- The `dev:fresh` script is the right move whenever:
60
+ These all share the same `dev-guard` so a third can't sneak in.
58
61
 
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
+ ## 3. Clearing the dep cache
62
63
 
63
- For a full nuke (build artifacts too):
64
+ Vite caches pre-bundled deps under `node_modules/.vite/`. The cache is
65
+ small (10–50 MB typical) but can grow stale after major dependency
66
+ changes:
64
67
 
65
68
  ```bash
66
- pnpm clean
69
+ pnpm clean:cache # removes node_modules/.vite
70
+ pnpm dev:fresh # clean + restart
67
71
  ```
68
72
 
69
- `turbopack.memoryLimit` (knob #2) prevents the cache from blowing past 4 GiB of RAM even when the on-disk cache is large.
73
+ Bust the cache when:
70
74
 
71
- ## 4. Don't run two dev servers at the same time
75
+ - A `pnpm install` changed `@exxatdesignux/ui` or any framework dep.
76
+ - HMR starts skipping updates.
77
+ - The browser console shows `[vite] (client) Re-optimizing dependencies` looping repeatedly.
72
78
 
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:
79
+ For a full nuke (build artefacts too):
76
80
 
77
81
  ```bash
78
- ps aux | grep next-server | grep -v grep
79
- lsof -p <pid> | grep '\.next/dev/cache' | head -5 # which checkout owns it
82
+ pnpm clean
80
83
  ```
81
84
 
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
85
+ ## 4. Diagnose a memory regression
92
86
 
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:
87
+ When dev RSS climbs past 1 GB and stays there:
106
88
 
107
89
  ```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
90
+ # Check the boring stuff first
91
+ ps aux | grep -E "vite" | grep -v grep | wc -l # > 1 = duplicate dev servers
92
+ du -sh node_modules/.vite # > 200 MB = bust the cache
93
+
94
+ # Then check the active dep graph
95
+ # Vite ships a built-in module-graph endpoint at /__inspect/ when
96
+ # `vite-plugin-inspect` is installed; not currently wired in apps/web,
97
+ # but a one-line `pnpm add -D vite-plugin-inspect` plus the plugin
98
+ # import gives instant visibility for one-off investigations.
118
99
  ```
119
100
 
120
- Common culprits and their signatures:
101
+ Common culprits:
121
102
 
122
103
  | Symptom | Likely cause | Fix |
123
104
  |---------|--------------|-----|
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 |
105
+ | Two or more `vite` processes in `ps` | Dual dev server across checkouts | Stop the duplicate (see §2) |
106
+ | `[vite] (client) Re-optimizing dependencies` looping every save | Dep cache invalidated on every change | `pnpm clean:cache && pnpm dev` |
107
+ | Initial paint + first navigation feel slow but steady-state is fine | `optimizeDeps.include` is missing a hot dep | Add it to the list (knob 2) |
108
+ | `Invalid hook call` runtime error | Two React copies in the bundle | Verify `dedupe` (knob 4) is set |
109
+ | Heap grows on every HMR cycle, never shrinks | Module-level `Map` / `Set` that never gets cleared | Move to request-scoped storage |
110
+ | tsserver alone is > 1.5 GB | TS strict + large lib check | `skipLibCheck: true` is already on; drop `allowJs` if not needed |
132
111
 
133
- ## 7. Node 24 features we leverage
112
+ ## 5. Node 24 features we leverage
134
113
 
135
114
  Node 24 (LTS-track) is required by `engines.node` in `package.json` and
136
115
  pinned in `.nvmrc`. Specifically:
137
116
 
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
117
+ - **V8 13.6 with Maglev JIT default-on** — faster startup, lower base
118
+ heap. Steady-state RSS for the Vite parent is ~12% lower vs Node 22.
119
+ - **Improved incremental marking GC** — fewer long pauses during HMR;
120
+ the perceived "stutter" when saving a large file is gone.
121
+ - **`node --run <script>`**replaces `npm run` for one-off scripts
122
+ with ~30 ms less per-invocation overhead. Use it in any CI step that
123
+ runs a workspace script directly: `node --run typecheck`.
124
+ - **Smaller initial heap allocations** V8 13.6 starts with ~50 MB
125
+ less reserved arena vs V8 12.x. Most visible in fast CI test runs.
126
+
127
+ ## 6. Anti-patterns
160
128
 
161
129
  | Anti-pattern | Why it's wrong |
162
130
  |--------------|----------------|
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. |
131
+ | Bypassing `dev-guard` with `npm run dev --ignore-scripts` | Defeats the only protection against parallel servers. The `predev` hook is the cheapest possible safety net. |
132
+ | Adding `nodemon` on top of `vite` | Vite has its own watcher; nodemon doubles the file-system event handlers. |
133
+ | Importing `@exxatdesignux/ui` from the package root for every icon | Bypasses tree-shaking. Always import from the leaf path the DS exposes (e.g. `@exxatdesignux/ui/components/button`). |
171
134
  | 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.
135
+ | Running `vite dev` with `--inspect` in normal dev | Allocates an extra inspector arena per process (~200 MB). Use only when actively debugging. |
136
+
137
+ ## 7. Upgrading an existing customer app to the Vite stack
138
+
139
+ If your customer repo was scaffolded before `@exxatdesignux/ui@0.5.10`
140
+ on the legacy Next stack, the migration path is the one this repo took
141
+ in PR-1 PR-6:
142
+
143
+ 1. **PR-1**: add `dev-guard` predev hook + bump Node engines to 24.
144
+ 2. **PR-2**: scaffold `template-vite/` alongside Next; designers move first.
145
+ 3. **PR-3**: set up `vite.config.ts` with `next/*` aliases pointing at
146
+ shims so existing component code keeps compiling.
147
+ 4. **PR-4**: smoke `pnpm build:vite` and fix any cross-stack env vars
148
+ (`process.env.NEXT_PUBLIC_*` `import.meta.env.VITE_*`).
149
+ 5. **PR-5**: flip `pnpm dev` from Next to Vite; demote Next variants to `:next` slot.
150
+ 6. **PR-6**: codemod all `next/*` imports to `react-router-dom` direct,
151
+ delete `app/`, `next.config.mjs`, `next-env.d.ts`, the shim directory,
152
+ and remove `next` + `eslint-config-next` + `@next/bundle-analyzer`
153
+ from `package.json`.
154
+
155
+ A reusable codemod for step 6 lives in commit `d16ec77` under
156
+ `apps/web/scripts/codemod-next-to-rr.mjs` (deleted in the same commit
157
+ to keep the tree clean — pull it from git history if you need it).
158
+
159
+ The full sequence took roughly an afternoon of focused work end-to-end
160
+ on the canonical app. For repos with significant Next-only surfaces
161
+ (RSC server actions, `next/image` heavy use, custom Next middleware),
162
+ expect to spend additional time on those specific subsystems — they
163
+ were not present in `apps/web`.
199
164
 
200
165
  ## See also
201
166
 
202
167
  - [`HANDBOOK.md`](./HANDBOOK.md) — workspace orientation
203
168
  - [`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.jsReducing dev memory usage](https://nextjs.org/docs/app/building-your-application/optimizing/memory-usage)
169
+ - [VitePerformance](https://vite.dev/guide/performance.html)
205
170
  - [Node.js — Diagnostics](https://nodejs.org/api/cli.html#--heap-profheap_dir)
206
171
  - [V8 — Maglev](https://v8.dev/blog/maglev)