forgebook 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (690) hide show
  1. package/README.md +914 -72
  2. package/dist/bin/forgebook/agentClient.d.ts +2 -1
  3. package/dist/bin/forgebook/agentClient.js +13 -6
  4. package/dist/bin/forgebook/agentGuide.d.ts +59 -0
  5. package/dist/bin/forgebook/agentGuide.js +203 -0
  6. package/dist/bin/forgebook/agentLoopCommands.mjs +22 -42
  7. package/dist/bin/forgebook/agentSetup/agentFiles.d.ts +55 -0
  8. package/dist/bin/forgebook/agentSetup/agentFiles.js +319 -0
  9. package/dist/bin/forgebook/agentSetup/assistantHooks.d.ts +71 -0
  10. package/dist/bin/forgebook/agentSetup/assistantHooks.js +125 -0
  11. package/dist/bin/forgebook/agentSetup/ciWorkflow.d.ts +23 -0
  12. package/dist/bin/forgebook/agentSetup/ciWorkflow.js +55 -0
  13. package/dist/bin/forgebook/agentSetup/drawCandidates.d.ts +25 -0
  14. package/dist/bin/forgebook/agentSetup/drawCandidates.js +116 -0
  15. package/dist/bin/forgebook/agentSetup/drawDiagnosis.d.ts +28 -0
  16. package/dist/bin/forgebook/agentSetup/drawDiagnosis.js +134 -0
  17. package/dist/bin/forgebook/agentSetup/drawRun.d.ts +91 -0
  18. package/dist/bin/forgebook/agentSetup/drawRun.js +353 -0
  19. package/dist/bin/forgebook/agentSetup/hookNames.d.ts +7 -0
  20. package/dist/bin/forgebook/agentSetup/hookNames.js +7 -0
  21. package/dist/bin/forgebook/agentSetup/initAgentSteps.d.ts +48 -0
  22. package/dist/bin/forgebook/agentSetup/initAgentSteps.js +104 -0
  23. package/dist/bin/forgebook/agentSetup/liftedProviders.d.ts +17 -0
  24. package/dist/bin/forgebook/agentSetup/liftedProviders.js +186 -0
  25. package/dist/bin/forgebook/agentSetup/projectRunner.d.ts +46 -0
  26. package/dist/bin/forgebook/agentSetup/projectRunner.js +85 -0
  27. package/dist/bin/forgebook/agentSetup/stopHook.d.ts +65 -0
  28. package/dist/bin/forgebook/agentSetup/stopHook.js +202 -0
  29. package/dist/bin/forgebook/agentSetup/uniformPicture.d.ts +7 -0
  30. package/dist/bin/forgebook/agentSetup/uniformPicture.js +98 -0
  31. package/dist/bin/forgebook/agentSetupCommands.d.mts +14 -0
  32. package/dist/bin/forgebook/agentSetupCommands.mjs +98 -0
  33. package/dist/bin/forgebook/agentText.d.ts +23 -3
  34. package/dist/bin/forgebook/agentText.js +175 -28
  35. package/dist/bin/forgebook/agents.md +20 -191
  36. package/dist/bin/forgebook/agentsText.js +2 -1
  37. package/dist/bin/forgebook/appBuild/appBuild.d.ts +59 -0
  38. package/dist/bin/forgebook/appBuild/appBuild.js +213 -0
  39. package/dist/bin/forgebook/appBuild/appViteConfig.d.ts +96 -0
  40. package/dist/bin/forgebook/appBuild/appViteConfig.js +320 -0
  41. package/dist/bin/forgebook/appBuild/tsconfigPaths.d.ts +14 -0
  42. package/dist/bin/forgebook/appBuild/tsconfigPaths.js +80 -0
  43. package/dist/bin/forgebook/auditCommand.d.mts +8 -0
  44. package/dist/bin/forgebook/auditCommand.mjs +75 -0
  45. package/dist/bin/forgebook/auditRun.d.ts +95 -0
  46. package/dist/bin/forgebook/auditRun.js +270 -0
  47. package/dist/bin/forgebook/browserRun.d.ts +21 -0
  48. package/dist/bin/forgebook/browserRun.js +57 -0
  49. package/dist/bin/forgebook/buildFailure.d.ts +7 -0
  50. package/dist/bin/forgebook/buildFailure.js +47 -0
  51. package/dist/bin/forgebook/buildWatch.d.ts +52 -0
  52. package/dist/bin/forgebook/buildWatch.js +137 -0
  53. package/dist/bin/forgebook/builtCatalogue.js +9 -5
  54. package/dist/bin/forgebook/catalogueCommands.d.ts +9 -0
  55. package/dist/bin/forgebook/catalogueCommands.js +23 -0
  56. package/dist/bin/forgebook/catalogueVite.d.ts +5 -1
  57. package/dist/bin/forgebook/catalogueVite.js +14 -6
  58. package/dist/bin/forgebook/commandCacheClaim.d.ts +18 -0
  59. package/dist/bin/forgebook/commandCacheClaim.js +170 -0
  60. package/dist/bin/forgebook/commandServer.d.ts +8 -0
  61. package/dist/bin/forgebook/commandServer.js +61 -13
  62. package/dist/bin/forgebook/forgebookCommands.mjs +105 -28
  63. package/dist/bin/forgebook/graphCommand.d.mts +8 -0
  64. package/dist/bin/forgebook/graphCommand.mjs +84 -0
  65. package/dist/bin/forgebook/guide/commands.md +57 -0
  66. package/dist/bin/forgebook/guide/devices.md +17 -0
  67. package/dist/bin/forgebook/guide/docs-pages.md +13 -0
  68. package/dist/bin/forgebook/guide/frameworks/angular.md +22 -0
  69. package/dist/bin/forgebook/guide/frameworks/html.md +22 -0
  70. package/dist/bin/forgebook/guide/frameworks/nextjs.md +23 -0
  71. package/dist/bin/forgebook/guide/frameworks/nuxt.md +22 -0
  72. package/dist/bin/forgebook/guide/frameworks/preact.md +16 -0
  73. package/dist/bin/forgebook/guide/frameworks/react-native-web.md +21 -0
  74. package/dist/bin/forgebook/guide/frameworks/react.md +16 -0
  75. package/dist/bin/forgebook/guide/frameworks/solid.md +18 -0
  76. package/dist/bin/forgebook/guide/frameworks/svelte.md +18 -0
  77. package/dist/bin/forgebook/guide/frameworks/sveltekit.md +23 -0
  78. package/dist/bin/forgebook/guide/frameworks/vue.md +18 -0
  79. package/dist/bin/forgebook/guide/frameworks/web-components.md +21 -0
  80. package/dist/bin/forgebook/guide/links.md +29 -0
  81. package/dist/bin/forgebook/guide/setup.md +23 -0
  82. package/dist/bin/forgebook/guide/stories.md +90 -0
  83. package/dist/bin/forgebook/guide/switches.md +43 -0
  84. package/dist/bin/forgebook/guideCommand.d.mts +13 -0
  85. package/dist/bin/forgebook/guideCommand.mjs +37 -0
  86. package/dist/bin/forgebook/importers/storybook.d.ts +21 -0
  87. package/dist/bin/forgebook/importers/storybook.js +11 -5
  88. package/dist/bin/forgebook/importers/storybookFrameworks.js +1 -1
  89. package/dist/bin/forgebook/initCommands.d.mts +11 -0
  90. package/dist/bin/forgebook/initCommands.mjs +51 -78
  91. package/dist/bin/forgebook/initConfig.d.ts +5 -3
  92. package/dist/bin/forgebook/initConfig.js +6 -3
  93. package/dist/bin/forgebook/initInstall.d.ts +15 -0
  94. package/dist/bin/forgebook/initInstall.js +77 -0
  95. package/dist/bin/forgebook/initPrint.d.ts +9 -0
  96. package/dist/bin/forgebook/initPrint.js +60 -0
  97. package/dist/bin/forgebook/initRefusals.d.ts +45 -0
  98. package/dist/bin/forgebook/initRefusals.js +91 -0
  99. package/dist/bin/forgebook/initRun.d.ts +28 -0
  100. package/dist/bin/forgebook/initRun.js +311 -0
  101. package/dist/bin/forgebook/mcpCommand.mjs +38 -4
  102. package/dist/bin/forgebook/mcpGraph.d.ts +13 -0
  103. package/dist/bin/forgebook/mcpGraph.js +24 -0
  104. package/dist/bin/forgebook/mcpTokens.d.ts +14 -0
  105. package/dist/bin/forgebook/mcpTokens.js +58 -0
  106. package/dist/bin/forgebook/mcpToolParts.d.ts +7 -0
  107. package/dist/bin/forgebook/mcpToolParts.js +10 -0
  108. package/dist/bin/forgebook/mcpTools.d.ts +13 -6
  109. package/dist/bin/forgebook/mcpTools.js +57 -90
  110. package/dist/bin/forgebook/mcpVerify.d.ts +16 -0
  111. package/dist/bin/forgebook/mcpVerify.js +36 -0
  112. package/dist/bin/forgebook/migrate/codemods.d.ts +11 -0
  113. package/dist/bin/forgebook/migrate/codemods.js +61 -0
  114. package/dist/bin/forgebook/migrate/migrate.types.d.ts +117 -0
  115. package/dist/bin/forgebook/migrate/migrate.types.js +5 -0
  116. package/dist/bin/forgebook/migrate/migrateCommand.d.mts +8 -0
  117. package/dist/bin/forgebook/migrate/migrateCommand.mjs +76 -0
  118. package/dist/bin/forgebook/migrate/migrateRun.d.ts +61 -0
  119. package/dist/bin/forgebook/migrate/migrateRun.js +210 -0
  120. package/dist/bin/forgebook/migrate/migrateText.d.ts +12 -0
  121. package/dist/bin/forgebook/migrate/migrateText.js +30 -0
  122. package/dist/bin/forgebook/migrate/migrateWrite.d.ts +27 -0
  123. package/dist/bin/forgebook/migrate/migrateWrite.js +66 -0
  124. package/dist/bin/forgebook/migrate/objectEdits.d.ts +70 -0
  125. package/dist/bin/forgebook/migrate/objectEdits.js +241 -0
  126. package/dist/bin/forgebook/migrate/playOnInBuilds.d.ts +3 -0
  127. package/dist/bin/forgebook/migrate/playOnInBuilds.js +86 -0
  128. package/dist/bin/forgebook/migrate/propGroupStrings.d.ts +5 -0
  129. package/dist/bin/forgebook/migrate/propGroupStrings.js +81 -0
  130. package/dist/bin/forgebook/newProject/newProject.d.ts +39 -0
  131. package/dist/bin/forgebook/newProject/newProject.js +180 -0
  132. package/dist/bin/forgebook/newProject/newProject.types.d.ts +97 -0
  133. package/dist/bin/forgebook/newProject/newProject.types.js +6 -0
  134. package/dist/bin/forgebook/newProject/packageManagers.d.ts +51 -0
  135. package/dist/bin/forgebook/newProject/packageManagers.js +121 -0
  136. package/dist/bin/forgebook/newProject/projectEntries.d.ts +62 -0
  137. package/dist/bin/forgebook/newProject/projectEntries.js +191 -0
  138. package/dist/bin/forgebook/newProject/projectFrameworks.d.ts +57 -0
  139. package/dist/bin/forgebook/newProject/projectFrameworks.js +148 -0
  140. package/dist/bin/forgebook/newProject/projectLook.d.ts +23 -0
  141. package/dist/bin/forgebook/newProject/projectLook.js +293 -0
  142. package/dist/bin/forgebook/newProject/projectPackages.d.ts +66 -0
  143. package/dist/bin/forgebook/newProject/projectPackages.js +178 -0
  144. package/dist/bin/forgebook/newRepair.d.ts +45 -0
  145. package/dist/bin/forgebook/newRepair.js +157 -0
  146. package/dist/bin/forgebook/newRepairRun.d.ts +69 -0
  147. package/dist/bin/forgebook/newRepairRun.js +148 -0
  148. package/dist/bin/forgebook/newStories.d.ts +23 -1
  149. package/dist/bin/forgebook/newStories.js +101 -11
  150. package/dist/bin/forgebook/newStoriesFile.d.ts +20 -1
  151. package/dist/bin/forgebook/newStoriesFile.js +43 -4
  152. package/dist/bin/forgebook/prebundleRun.d.ts +3 -1
  153. package/dist/bin/forgebook/prebundleRun.js +28 -8
  154. package/dist/bin/forgebook/proofCommand.d.mts +15 -0
  155. package/dist/bin/forgebook/proofCommand.mjs +212 -0
  156. package/dist/bin/forgebook/proofRun.d.ts +63 -0
  157. package/dist/bin/forgebook/proofRun.js +412 -0
  158. package/dist/bin/forgebook/proofText.d.ts +36 -0
  159. package/dist/bin/forgebook/proofText.js +131 -0
  160. package/dist/bin/forgebook/proofWorkflow.d.ts +29 -0
  161. package/dist/bin/forgebook/proofWorkflow.js +205 -0
  162. package/dist/bin/forgebook/setArgsTool.d.ts +8 -0
  163. package/dist/bin/forgebook/setArgsTool.js +70 -0
  164. package/dist/bin/forgebook/storyCheckCommands.mjs +42 -3
  165. package/dist/bin/forgebook/storyCheckRun.d.ts +50 -0
  166. package/dist/bin/forgebook/storyCheckRun.js +83 -9
  167. package/dist/bin/forgebook/storyFileIds.d.ts +15 -0
  168. package/dist/bin/forgebook/storyFileIds.js +14 -0
  169. package/dist/bin/forgebook/stressCases.d.ts +31 -0
  170. package/dist/bin/forgebook/stressCases.js +79 -0
  171. package/dist/bin/forgebook/stressRun.d.ts +12 -0
  172. package/dist/bin/forgebook/stressRun.js +61 -0
  173. package/dist/bin/forgebook/stressText.d.ts +27 -0
  174. package/dist/bin/forgebook/stressText.js +46 -0
  175. package/dist/bin/forgebook/verifyBase.d.ts +45 -0
  176. package/dist/bin/forgebook/verifyBase.js +196 -0
  177. package/dist/bin/forgebook/verifyCommand.d.mts +13 -0
  178. package/dist/bin/forgebook/verifyCommand.mjs +125 -0
  179. package/dist/bin/forgebook/verifyRun.d.ts +63 -0
  180. package/dist/bin/forgebook/verifyRun.js +108 -0
  181. package/dist/bin/forgebook/verifyVerdict.d.ts +40 -0
  182. package/dist/bin/forgebook/verifyVerdict.js +297 -0
  183. package/dist/bin/forgebook/workflowActions.d.ts +23 -0
  184. package/dist/bin/forgebook/workflowActions.js +23 -0
  185. package/dist/bin/forgebook-docs/catalogueMarkdown.js +12 -1
  186. package/dist/src/addressArgs.d.ts +29 -5
  187. package/dist/src/addressArgs.js +58 -16
  188. package/dist/src/addressArgsParam.d.ts +54 -0
  189. package/dist/src/addressArgsParam.js +51 -0
  190. package/dist/src/addressTexts.d.ts +14 -0
  191. package/dist/src/addressTexts.js +28 -21
  192. package/dist/src/agentIndexFile.d.ts +11 -0
  193. package/dist/src/agentIndexFile.js +11 -0
  194. package/dist/src/argConditions.d.ts +52 -0
  195. package/dist/src/argConditions.js +80 -0
  196. package/dist/src/argControl.d.ts +100 -0
  197. package/dist/src/argControl.js +0 -0
  198. package/dist/src/argExpression.d.ts +21 -0
  199. package/dist/src/argExpression.js +30 -0
  200. package/dist/src/argTypes.d.ts +40 -51
  201. package/dist/src/argTypes.js +66 -184
  202. package/dist/src/argsProps.d.ts +3 -3
  203. package/dist/src/argsProps.js +11 -5
  204. package/dist/src/bundlerErrors.d.ts +29 -0
  205. package/dist/src/bundlerErrors.js +49 -0
  206. package/dist/src/catalogue.d.ts +31 -0
  207. package/dist/src/catalogue.js +13 -2
  208. package/dist/src/catalogueRefs.d.ts +75 -0
  209. package/dist/src/catalogueRefs.js +122 -0
  210. package/dist/src/componentDocs.d.ts +71 -0
  211. package/dist/src/componentDocs.js +15 -2
  212. package/dist/src/frame/callValues.d.ts +19 -0
  213. package/dist/src/frame/callValues.js +58 -0
  214. package/dist/src/frame/canvasScheme.d.ts +33 -0
  215. package/dist/src/frame/canvasScheme.js +67 -0
  216. package/dist/src/frame/frame.css +36 -3
  217. package/dist/src/frame/frameStatus.d.ts +16 -1
  218. package/dist/src/frame/frameStatus.js +16 -1
  219. package/dist/src/frame/frameView.js +4 -3
  220. package/dist/src/frame/mountFrame.d.ts +7 -1
  221. package/dist/src/frame/mountFrame.js +153 -46
  222. package/dist/src/frame/panelValues.d.ts +35 -0
  223. package/dist/src/frame/panelValues.js +127 -0
  224. package/dist/src/frame/playActions.d.ts +39 -0
  225. package/dist/src/frame/playActions.js +98 -0
  226. package/dist/src/frame/playStepper.d.ts +28 -0
  227. package/dist/src/frame/playStepper.js +38 -0
  228. package/dist/src/frame/playStory.d.ts +9 -1
  229. package/dist/src/frame/playStory.js +49 -3
  230. package/dist/src/frame/renderer.d.ts +34 -1
  231. package/dist/src/frame/renderer.js +24 -0
  232. package/dist/src/frame/shellChannel.d.ts +1 -1
  233. package/dist/src/frame/shellChannel.js +1 -1
  234. package/dist/src/frame/shellCheck.d.ts +17 -0
  235. package/dist/src/frame/shellCheck.js +25 -0
  236. package/dist/src/frame/shellMessageCheck.d.ts +7 -0
  237. package/dist/src/frame/shellMessageCheck.js +53 -0
  238. package/dist/src/frame/storyContent.d.ts +50 -0
  239. package/dist/src/frame/storyContent.js +73 -0
  240. package/dist/src/frame/storyModule.d.ts +9 -0
  241. package/dist/src/frame/storyModule.js +20 -2
  242. package/dist/src/frame/storyRun.d.ts +15 -7
  243. package/dist/src/frame/storyRun.js +64 -15
  244. package/dist/src/frame/valueSheets.d.ts +35 -0
  245. package/dist/src/frame/valueSheets.js +99 -0
  246. package/dist/src/hotModules.d.ts +20 -0
  247. package/dist/src/hotModules.js +23 -0
  248. package/dist/src/jsxCode.d.ts +1 -14
  249. package/dist/src/jsxCode.js +46 -10
  250. package/dist/src/liveErrors.d.ts +30 -4
  251. package/dist/src/liveErrors.js +18 -3
  252. package/dist/src/messages.d.ts +77 -27
  253. package/dist/src/messages.js +58 -100
  254. package/dist/src/namedValues.d.ts +2 -26
  255. package/dist/src/namedValues.js +0 -47
  256. package/dist/src/pageConfig.d.ts +2 -0
  257. package/dist/src/playTrace.d.ts +19 -2
  258. package/dist/src/playTrace.js +10 -5
  259. package/dist/src/plugin.d.ts +10 -3
  260. package/dist/src/previewRelay.js +9 -1
  261. package/dist/src/printable.d.ts +12 -0
  262. package/dist/src/printable.js +22 -0
  263. package/dist/src/propsSignature.d.ts +37 -0
  264. package/dist/src/propsSignature.js +40 -0
  265. package/dist/src/search.d.ts +41 -5
  266. package/dist/src/search.js +93 -23
  267. package/dist/src/searchMatch.d.ts +4 -1
  268. package/dist/src/searchMatch.js +26 -5
  269. package/dist/src/searchTypos.d.ts +88 -0
  270. package/dist/src/searchTypos.js +178 -0
  271. package/dist/src/shapeValues.d.ts +86 -0
  272. package/dist/src/shapeValues.js +295 -0
  273. package/dist/src/shell/ApiReference.js +6 -3
  274. package/dist/src/shell/ApiTableBox.d.ts +15 -0
  275. package/dist/src/shell/ApiTableBox.js +11 -0
  276. package/dist/src/shell/AppearanceMenu.d.ts +4 -1
  277. package/dist/src/shell/AppearanceMenu.js +9 -6
  278. package/dist/src/shell/CodeTab.d.ts +3 -2
  279. package/dist/src/shell/CodeTab.js +3 -2
  280. package/dist/src/shell/CodeText.d.ts +1 -1
  281. package/dist/src/shell/CodeText.js +2 -3
  282. package/dist/src/shell/CompareGrid.js +1 -1
  283. package/dist/src/shell/ComponentPage.d.ts +1 -1
  284. package/dist/src/shell/ComponentPage.js +5 -1
  285. package/dist/src/shell/CustomControl.d.ts +34 -0
  286. package/dist/src/shell/CustomControl.js +132 -0
  287. package/dist/src/shell/DocContainers.js +1 -1
  288. package/dist/src/shell/DocPage.js +2 -2
  289. package/dist/src/shell/DroppedArgsList.d.ts +2 -2
  290. package/dist/src/shell/DroppedArgsList.js +1 -1
  291. package/dist/src/shell/EmbedPage.js +30 -12
  292. package/dist/src/shell/Example.d.ts +5 -1
  293. package/dist/src/shell/Example.js +16 -8
  294. package/dist/src/shell/FrameView.d.ts +6 -3
  295. package/dist/src/shell/FrameView.js +2 -2
  296. package/dist/src/shell/HomePage.d.ts +3 -1
  297. package/dist/src/shell/HomePage.js +16 -6
  298. package/dist/src/shell/InfoTip.js +2 -2
  299. package/dist/src/shell/InteractionsTab.d.ts +11 -4
  300. package/dist/src/shell/InteractionsTab.js +18 -2
  301. package/dist/src/shell/LazyPage.js +1 -1
  302. package/dist/src/shell/PackageHtml.js +3 -1
  303. package/dist/src/shell/PinnedControl.js +14 -62
  304. package/dist/src/shell/PinnedControlMenu.d.ts +44 -0
  305. package/dist/src/shell/PinnedControlMenu.js +72 -0
  306. package/dist/src/shell/PropFields.d.ts +3 -1
  307. package/dist/src/shell/PropFields.js +9 -6
  308. package/dist/src/shell/PropRows.d.ts +23 -2
  309. package/dist/src/shell/PropRows.js +58 -19
  310. package/dist/src/shell/PropsTab.d.ts +12 -5
  311. package/dist/src/shell/PropsTab.js +9 -21
  312. package/dist/src/shell/RefStoryPage.d.ts +33 -0
  313. package/dist/src/shell/RefStoryPage.js +123 -0
  314. package/dist/src/shell/SearchPanel.js +51 -24
  315. package/dist/src/shell/Shell.d.ts +18 -0
  316. package/dist/src/shell/Shell.js +137 -22
  317. package/dist/src/shell/ShortcutHelp.d.ts +22 -0
  318. package/dist/src/shell/ShortcutHelp.js +66 -0
  319. package/dist/src/shell/Sidebar.d.ts +17 -4
  320. package/dist/src/shell/Sidebar.js +92 -41
  321. package/dist/src/shell/SidebarDocs.js +2 -2
  322. package/dist/src/shell/SidebarEntries.js +5 -3
  323. package/dist/src/shell/SidebarHandle.d.ts +3 -5
  324. package/dist/src/shell/SidebarHandle.js +4 -4
  325. package/dist/src/shell/SidebarRefs.d.ts +39 -0
  326. package/dist/src/shell/SidebarRefs.js +99 -0
  327. package/dist/src/shell/SidebarSearch.js +37 -9
  328. package/dist/src/shell/SignatureReference.js +3 -1
  329. package/dist/src/shell/Stage.d.ts +10 -2
  330. package/dist/src/shell/Stage.js +29 -49
  331. package/dist/src/shell/StatusBadges.d.ts +54 -0
  332. package/dist/src/shell/StatusBadges.js +77 -0
  333. package/dist/src/shell/StoryCodeBlock.d.ts +8 -19
  334. package/dist/src/shell/StoryCodeBlock.js +7 -6
  335. package/dist/src/shell/SwitchGallery.d.ts +36 -0
  336. package/dist/src/shell/SwitchGallery.js +17 -0
  337. package/dist/src/shell/SwitchGalleryPanel.d.ts +37 -0
  338. package/dist/src/shell/SwitchGalleryPanel.js +99 -0
  339. package/dist/src/shell/TagFilter.d.ts +24 -0
  340. package/dist/src/shell/TagFilter.js +45 -0
  341. package/dist/src/shell/TagViews.d.ts +39 -0
  342. package/dist/src/shell/TagViews.js +20 -0
  343. package/dist/src/shell/Toolbar.d.ts +4 -1
  344. package/dist/src/shell/Toolbar.js +17 -7
  345. package/dist/src/shell/ToolbarControl.d.ts +3 -0
  346. package/dist/src/shell/ToolbarControl.js +23 -6
  347. package/dist/src/shell/ViewMenuPanel.js +6 -1
  348. package/dist/src/shell/argChecks.d.ts +22 -0
  349. package/dist/src/shell/argChecks.js +20 -0
  350. package/dist/src/shell/asideStory.js +7 -2
  351. package/dist/src/shell/audienceSections.css +9 -9
  352. package/dist/src/shell/catalogueContext.d.ts +1 -1
  353. package/dist/src/shell/catalogueContext.js +6 -1
  354. package/dist/src/shell/codeSpans.d.ts +27 -0
  355. package/dist/src/shell/codeSpans.js +76 -0
  356. package/dist/src/shell/compareVariants.d.ts +4 -2
  357. package/dist/src/shell/compareVariants.js +16 -8
  358. package/dist/src/shell/composition.d.ts +23 -0
  359. package/dist/src/shell/composition.js +26 -0
  360. package/dist/src/shell/controlCycle.d.ts +1 -1
  361. package/dist/src/shell/controlCycle.js +3 -2
  362. package/dist/src/shell/customControls.d.ts +55 -0
  363. package/dist/src/shell/customControls.js +70 -0
  364. package/dist/src/shell/docPage.css +22 -22
  365. package/dist/src/shell/dockTabs.d.ts +19 -3
  366. package/dist/src/shell/dockTabs.js +28 -20
  367. package/dist/src/shell/embed.css +7 -7
  368. package/dist/src/shell/framesOrigin.d.ts +7 -0
  369. package/dist/src/shell/framesOrigin.js +1 -1
  370. package/dist/src/shell/galleryPlace.d.ts +20 -0
  371. package/dist/src/shell/galleryPlace.js +26 -0
  372. package/dist/src/shell/icons.d.ts +1 -0
  373. package/dist/src/shell/icons.js +1 -0
  374. package/dist/src/shell/keyboard.d.ts +14 -12
  375. package/dist/src/shell/keyboard.js +21 -6
  376. package/dist/src/shell/laterStrings.d.ts +29 -0
  377. package/dist/src/shell/laterStrings.js +42 -3
  378. package/dist/src/shell/mountShell.js +3 -0
  379. package/dist/src/shell/pageStrings.d.ts +4 -0
  380. package/dist/src/shell/pageStrings.js +4 -0
  381. package/dist/src/shell/pageTagView.d.ts +18 -0
  382. package/dist/src/shell/pageTagView.js +10 -0
  383. package/dist/src/shell/playMemory.d.ts +14 -0
  384. package/dist/src/shell/playMemory.js +8 -0
  385. package/dist/src/shell/propNotes.d.ts +23 -0
  386. package/dist/src/shell/propNotes.js +37 -0
  387. package/dist/src/shell/refIndexLoad.d.ts +17 -0
  388. package/dist/src/shell/refIndexLoad.js +38 -0
  389. package/dist/src/shell/refParts.d.ts +34 -0
  390. package/dist/src/shell/refParts.js +9 -0
  391. package/dist/src/shell/refStory.css +21 -0
  392. package/dist/src/shell/refStrings.d.ts +13 -0
  393. package/dist/src/shell/refStrings.js +21 -0
  394. package/dist/src/shell/search.css +11 -11
  395. package/dist/src/shell/shell.css +348 -168
  396. package/dist/src/shell/shellScheme.js +2 -2
  397. package/dist/src/shell/shortcutHelp.css +64 -0
  398. package/dist/src/shell/stageArgs.d.ts +53 -0
  399. package/dist/src/shell/stageArgs.js +64 -0
  400. package/dist/src/shell/statusBadges.css +51 -0
  401. package/dist/src/shell/strings.d.ts +7 -16
  402. package/dist/src/shell/strings.js +12 -17
  403. package/dist/src/shell/switchGallery.css +104 -0
  404. package/dist/src/shell/tagFilter.css +46 -0
  405. package/dist/src/shell/tagView.d.ts +20 -0
  406. package/dist/src/shell/tagView.js +10 -0
  407. package/dist/src/shell/useAddressArgs.d.ts +9 -0
  408. package/dist/src/shell/useAddressArgs.js +56 -11
  409. package/dist/src/shell/useControlKeys.js +2 -2
  410. package/dist/src/shell/useEditedProblems.d.ts +6 -0
  411. package/dist/src/shell/useEditedProblems.js +40 -0
  412. package/dist/src/shell/useFrameMessages.js +3 -0
  413. package/dist/src/shell/useListedTree.d.ts +13 -0
  414. package/dist/src/shell/useListedTree.js +32 -0
  415. package/dist/src/shell/usePageFrames.js +2 -2
  416. package/dist/src/shell/usePopover.d.ts +5 -0
  417. package/dist/src/shell/usePopover.js +7 -1
  418. package/dist/src/shell/useRefIndex.d.ts +22 -0
  419. package/dist/src/shell/useRefIndex.js +36 -0
  420. package/dist/src/shell/useScrollStops.d.ts +20 -0
  421. package/dist/src/shell/useScrollStops.js +41 -0
  422. package/dist/src/shell/useShortcutHelp.d.ts +18 -0
  423. package/dist/src/shell/useShortcutHelp.js +32 -0
  424. package/dist/src/shell/useSidebarOverlay.d.ts +2 -1
  425. package/dist/src/shell/useSidebarOverlay.js +12 -4
  426. package/dist/src/shell/useStoryCode.d.ts +2 -1
  427. package/dist/src/shell/useStoryCode.js +12 -7
  428. package/dist/src/shell/useToolbarLayout.d.ts +5 -1
  429. package/dist/src/shell/useToolbarLayout.js +2 -2
  430. package/dist/src/shell/useWorstCase.d.ts +8 -2
  431. package/dist/src/shell/useWorstCase.js +2 -2
  432. package/dist/src/shell/valueEditors/FileEditor.d.ts +28 -0
  433. package/dist/src/shell/valueEditors/FileEditor.js +66 -0
  434. package/dist/src/shell/valueEditors/JsonEditor.d.ts +14 -0
  435. package/dist/src/shell/valueEditors/JsonEditor.js +53 -0
  436. package/dist/src/shell/valueEditors/ListEditor.d.ts +24 -0
  437. package/dist/src/shell/valueEditors/ListEditor.js +82 -0
  438. package/dist/src/shell/valueEditors/ObjectEditor.d.ts +32 -0
  439. package/dist/src/shell/valueEditors/ObjectEditor.js +70 -0
  440. package/dist/src/shell/valueEditors/PropEditor.d.ts +37 -0
  441. package/dist/src/shell/valueEditors/PropEditor.js +53 -0
  442. package/dist/src/shell/valueEditors/RecordEditor.d.ts +20 -0
  443. package/dist/src/shell/valueEditors/RecordEditor.js +84 -0
  444. package/dist/src/shell/valueEditors/SearchSelect.d.ts +42 -0
  445. package/dist/src/shell/valueEditors/SearchSelect.js +80 -0
  446. package/dist/src/shell/valueEditors/TokenEditor.d.ts +49 -0
  447. package/dist/src/shell/valueEditors/TokenEditor.js +74 -0
  448. package/dist/src/shell/valueEditors/UnionEditor.d.ts +20 -0
  449. package/dist/src/shell/valueEditors/UnionEditor.js +64 -0
  450. package/dist/src/shell/valueEditors/ValueField.d.ts +15 -0
  451. package/dist/src/shell/valueEditors/ValueField.js +147 -0
  452. package/dist/src/shell/valueEditors/editorStrings.d.ts +56 -0
  453. package/dist/src/shell/valueEditors/editorStrings.js +66 -0
  454. package/dist/src/shell/valueEditors/fieldTypes.d.ts +31 -0
  455. package/dist/src/shell/valueEditors/fieldTypes.js +0 -0
  456. package/dist/src/shell/valueEditors/valueEditors.css +153 -0
  457. package/dist/src/shell/worstArgs.d.ts +8 -5
  458. package/dist/src/shell/worstArgs.js +14 -7
  459. package/dist/src/shellTheme.d.ts +1 -1
  460. package/dist/src/shellTheme.js +15 -1
  461. package/dist/src/shellTheme.types.d.ts +4 -0
  462. package/dist/src/shellWord.d.ts +12 -0
  463. package/dist/src/shellWord.js +15 -0
  464. package/dist/src/sourceFiles.js +2 -1
  465. package/dist/src/storyArgTypes.d.ts +57 -0
  466. package/dist/src/storyArgTypes.js +195 -0
  467. package/dist/src/storyBackground.js +14 -3
  468. package/dist/src/storyCheck.d.ts +85 -3
  469. package/dist/src/storyCheck.js +23 -1
  470. package/dist/src/storyCodeText.d.ts +46 -0
  471. package/dist/src/storyCodeText.js +27 -0
  472. package/dist/src/storyControls.d.ts +100 -0
  473. package/dist/src/storyControls.js +100 -0
  474. package/dist/src/storyStatuses.d.ts +55 -0
  475. package/dist/src/storyStatuses.js +104 -0
  476. package/dist/src/storyTagNames.d.ts +25 -0
  477. package/dist/src/storyTagNames.js +25 -0
  478. package/dist/src/storyTags.d.ts +29 -0
  479. package/dist/src/storyTags.js +85 -0
  480. package/dist/src/storyTree.d.ts +13 -0
  481. package/dist/src/storyTree.js +24 -4
  482. package/dist/src/storybookArgs.d.ts +24 -0
  483. package/dist/src/storybookArgs.js +185 -0
  484. package/dist/src/switches.d.ts +66 -3
  485. package/dist/src/switches.js +42 -1
  486. package/dist/src/valueSchema.d.ts +28 -0
  487. package/dist/src/valueSchema.js +196 -0
  488. package/dist/src/valueShape.d.ts +94 -0
  489. package/dist/src/valueShape.js +25 -0
  490. package/dist/src/viewState.d.ts +8 -3
  491. package/dist/src/viewState.js +27 -10
  492. package/dist/src/vite/adapter.d.ts +40 -2
  493. package/dist/src/vite/adapter.js +1 -0
  494. package/dist/src/vite/agent.types.d.ts +347 -7
  495. package/dist/src/vite/agentApi.d.ts +23 -0
  496. package/dist/src/vite/agentApi.js +90 -17
  497. package/dist/src/vite/agentIndex.d.ts +0 -2
  498. package/dist/src/vite/agentIndex.js +5 -6
  499. package/dist/src/vite/agentRoutes.d.ts +20 -1
  500. package/dist/src/vite/agentRoutes.js +106 -65
  501. package/dist/src/vite/agentStatuses.d.ts +42 -0
  502. package/dist/src/vite/agentStatuses.js +67 -0
  503. package/dist/src/vite/agentStoryCode.d.ts +48 -0
  504. package/dist/src/vite/agentStoryCode.js +38 -0
  505. package/dist/src/vite/agentVisibility.d.ts +47 -0
  506. package/dist/src/vite/agentVisibility.js +174 -0
  507. package/dist/src/vite/appAudit.d.ts +134 -0
  508. package/dist/src/vite/appAudit.js +333 -0
  509. package/dist/src/vite/appBuildOption.d.ts +53 -0
  510. package/dist/src/vite/appBuildOption.js +55 -0
  511. package/dist/src/vite/appTokenFiles.d.ts +92 -0
  512. package/dist/src/vite/appTokenFiles.js +433 -0
  513. package/dist/src/vite/appTokens.d.ts +23 -0
  514. package/dist/src/vite/appTokens.js +275 -0
  515. package/dist/src/vite/builtTexts.d.ts +10 -0
  516. package/dist/src/vite/builtTexts.js +59 -22
  517. package/dist/src/vite/catalogueConfig.d.ts +3 -1
  518. package/dist/src/vite/catalogueConfig.js +15 -3
  519. package/dist/src/vite/changeCoverage.d.ts +74 -0
  520. package/dist/src/vite/changeCoverage.js +120 -0
  521. package/dist/src/vite/changedRoute.d.ts +30 -0
  522. package/dist/src/vite/changedRoute.js +197 -0
  523. package/dist/src/vite/checkCode.d.ts +105 -3
  524. package/dist/src/vite/checkCode.js +323 -36
  525. package/dist/src/vite/checkoutWatch.d.ts +97 -0
  526. package/dist/src/vite/checkoutWatch.js +287 -0
  527. package/dist/src/vite/closeWatch.d.ts +8 -0
  528. package/dist/src/vite/closeWatch.js +1 -1
  529. package/dist/src/vite/componentCache.d.ts +8 -0
  530. package/dist/src/vite/componentCache.js +66 -0
  531. package/dist/src/vite/componentGraph.d.ts +71 -0
  532. package/dist/src/vite/componentGraph.js +133 -0
  533. package/dist/src/vite/componentRules.d.ts +33 -0
  534. package/dist/src/vite/componentRules.js +105 -0
  535. package/dist/src/vite/componentScan.d.ts +69 -0
  536. package/dist/src/vite/componentScan.js +418 -0
  537. package/dist/src/vite/compositionCheck.d.ts +15 -0
  538. package/dist/src/vite/compositionCheck.js +243 -0
  539. package/dist/src/vite/config.d.ts +32 -1
  540. package/dist/src/vite/configFile.d.ts +14 -2
  541. package/dist/src/vite/configFile.js +124 -40
  542. package/dist/src/vite/configKeys.d.ts +15 -0
  543. package/dist/src/vite/configKeys.js +171 -0
  544. package/dist/src/vite/configLoadError.d.ts +23 -0
  545. package/dist/src/vite/configLoadError.js +71 -0
  546. package/dist/src/vite/cssDeclarations.d.ts +71 -0
  547. package/dist/src/vite/cssDeclarations.js +290 -0
  548. package/dist/src/vite/cssImports.d.ts +14 -0
  549. package/dist/src/vite/cssImports.js +48 -0
  550. package/dist/src/vite/cssReferences.d.ts +54 -0
  551. package/dist/src/vite/cssReferences.js +157 -0
  552. package/dist/src/vite/cssTokenValues.d.ts +50 -0
  553. package/dist/src/vite/cssTokenValues.js +233 -0
  554. package/dist/src/vite/designTokens.d.ts +24 -0
  555. package/dist/src/vite/designTokens.js +5 -1
  556. package/dist/src/vite/docsExtractor.d.ts +9 -3
  557. package/dist/src/vite/docsExtractor.js +11 -3
  558. package/dist/src/vite/docsProgram.d.ts +17 -4
  559. package/dist/src/vite/docsProgram.js +52 -11
  560. package/dist/src/vite/docsWorker.js +7 -2
  561. package/dist/src/vite/emptyStoryGlobs.d.ts +41 -0
  562. package/dist/src/vite/emptyStoryGlobs.js +52 -0
  563. package/dist/src/vite/fileImports.d.ts +17 -0
  564. package/dist/src/vite/fileImports.js +57 -0
  565. package/dist/src/vite/findComponent.d.ts +10 -2
  566. package/dist/src/vite/findComponent.js +27 -22
  567. package/dist/src/vite/findRoute.js +3 -2
  568. package/dist/src/vite/forcedStates.d.ts +9 -2
  569. package/dist/src/vite/forcedStates.js +12 -3
  570. package/dist/src/vite/forgebookPlugin.d.ts +2 -0
  571. package/dist/src/vite/forgebookPlugin.js +52 -72
  572. package/dist/src/vite/frameErrors.d.ts +19 -0
  573. package/dist/src/vite/frameErrors.js +70 -0
  574. package/dist/src/vite/framesServer.d.ts +12 -0
  575. package/dist/src/vite/framesServer.js +21 -4
  576. package/dist/src/vite/functionComponentDocs.js +81 -12
  577. package/dist/src/vite/generatedModules.js +4 -2
  578. package/dist/src/vite/gitChange.d.ts +38 -5
  579. package/dist/src/vite/gitChange.js +71 -11
  580. package/dist/src/vite/hiddenStoryFiles.d.ts +23 -0
  581. package/dist/src/vite/hiddenStoryFiles.js +107 -0
  582. package/dist/src/vite/hotSnippets.d.ts +38 -14
  583. package/dist/src/vite/hotSnippets.js +137 -39
  584. package/dist/src/vite/importedNames.d.ts +37 -0
  585. package/dist/src/vite/importedNames.js +138 -0
  586. package/dist/src/vite/indexFields.d.ts +6 -0
  587. package/dist/src/vite/indexFields.js +21 -0
  588. package/dist/src/vite/indexStoryFile.d.ts +8 -1
  589. package/dist/src/vite/indexStoryFile.js +22 -157
  590. package/dist/src/vite/jsxCallSites.d.ts +33 -0
  591. package/dist/src/vite/jsxCallSites.js +200 -0
  592. package/dist/src/vite/jsxInScripts.d.ts +67 -0
  593. package/dist/src/vite/jsxInScripts.js +138 -0
  594. package/dist/src/vite/jsxTree.d.ts +20 -0
  595. package/dist/src/vite/jsxTree.js +163 -0
  596. package/dist/src/vite/lineAndColumn.d.ts +13 -0
  597. package/dist/src/vite/lineAndColumn.js +18 -0
  598. package/dist/src/vite/lookAlikes.d.ts +65 -0
  599. package/dist/src/vite/lookAlikes.js +228 -0
  600. package/dist/src/vite/nearestToken.d.ts +17 -0
  601. package/dist/src/vite/nearestToken.js +9 -2
  602. package/dist/src/vite/packageEntries.d.ts +42 -0
  603. package/dist/src/vite/packageEntries.js +127 -0
  604. package/dist/src/vite/pages.d.ts +9 -1
  605. package/dist/src/vite/pages.js +108 -4
  606. package/dist/src/vite/pluginConfig.js +4 -0
  607. package/dist/src/vite/pluginIds.d.ts +2 -0
  608. package/dist/src/vite/pluginIds.js +5 -1
  609. package/dist/src/vite/pluginModules.d.ts +81 -11
  610. package/dist/src/vite/pluginModules.js +109 -21
  611. package/dist/src/vite/prebundled.d.ts +57 -15
  612. package/dist/src/vite/prebundled.js +80 -0
  613. package/dist/src/vite/previewTags.d.ts +25 -0
  614. package/dist/src/vite/previewTags.js +56 -0
  615. package/dist/src/vite/projectFiles.d.ts +54 -0
  616. package/dist/src/vite/projectFiles.js +116 -0
  617. package/dist/src/vite/projectPostcss.d.ts +70 -0
  618. package/dist/src/vite/projectPostcss.js +250 -0
  619. package/dist/src/vite/propDocs.d.ts +12 -0
  620. package/dist/src/vite/propDocs.js +130 -58
  621. package/dist/src/vite/propKind.d.ts +40 -0
  622. package/dist/src/vite/propKind.js +71 -0
  623. package/dist/src/vite/propTypeNotes.d.ts +22 -0
  624. package/dist/src/vite/propTypeNotes.js +51 -0
  625. package/dist/src/vite/publishedExports.d.ts +27 -0
  626. package/dist/src/vite/publishedExports.js +298 -0
  627. package/dist/src/vite/realFolder.d.ts +6 -0
  628. package/dist/src/vite/realFolder.js +25 -0
  629. package/dist/src/vite/refsConfig.d.ts +39 -0
  630. package/dist/src/vite/refsConfig.js +54 -0
  631. package/dist/src/vite/reuseCheck.d.ts +45 -0
  632. package/dist/src/vite/reuseCheck.js +260 -0
  633. package/dist/src/vite/runningVersions.d.ts +33 -0
  634. package/dist/src/vite/runningVersions.js +25 -0
  635. package/dist/src/vite/scriptProblems.d.ts +60 -0
  636. package/dist/src/vite/scriptProblems.js +155 -0
  637. package/dist/src/vite/searchModule.js +3 -2
  638. package/dist/src/vite/searchRoute.js +4 -2
  639. package/dist/src/vite/shapeDocs.d.ts +36 -0
  640. package/dist/src/vite/shapeDocs.js +177 -0
  641. package/dist/src/vite/singleFileComponent.d.ts +17 -0
  642. package/dist/src/vite/singleFileComponent.js +83 -0
  643. package/dist/src/vite/sourceText.d.ts +34 -0
  644. package/dist/src/vite/sourceText.js +72 -0
  645. package/dist/src/vite/sourceTokens.d.ts +7 -0
  646. package/dist/src/vite/sourceTokens.js +7 -2
  647. package/dist/src/vite/stackLines.d.ts +49 -0
  648. package/dist/src/vite/stackLines.js +96 -0
  649. package/dist/src/vite/storyCode.d.ts +22 -7
  650. package/dist/src/vite/storyCode.js +263 -37
  651. package/dist/src/vite/storyCoverage.d.ts +48 -0
  652. package/dist/src/vite/storyCoverage.js +179 -0
  653. package/dist/src/vite/storyFilesModule.d.ts +48 -3
  654. package/dist/src/vite/storyFilesModule.js +105 -15
  655. package/dist/src/vite/storyPatterns.d.ts +31 -0
  656. package/dist/src/vite/storyPatterns.js +140 -5
  657. package/dist/src/vite/storyReach.d.ts +10 -2
  658. package/dist/src/vite/storyReach.js +15 -11
  659. package/dist/src/vite/storyTopLevel.d.ts +51 -0
  660. package/dist/src/vite/storyTopLevel.js +146 -0
  661. package/dist/src/vite/storylessRoutes.d.ts +4 -3
  662. package/dist/src/vite/storylessRoutes.js +210 -19
  663. package/dist/src/vite/switchValuesCheck.d.ts +19 -0
  664. package/dist/src/vite/switchValuesCheck.js +164 -0
  665. package/dist/src/vite/switchesDocument.d.ts +15 -0
  666. package/dist/src/vite/switchesDocument.js +47 -0
  667. package/dist/src/vite/tailwindConfigTokens.d.ts +41 -0
  668. package/dist/src/vite/tailwindConfigTokens.js +306 -0
  669. package/dist/src/vite/textImports.d.ts +15 -0
  670. package/dist/src/vite/textImports.js +58 -0
  671. package/dist/src/vite/textModules.d.ts +6 -5
  672. package/dist/src/vite/textModules.js +13 -8
  673. package/dist/src/vite/tokenAnswers.d.ts +6 -2
  674. package/dist/src/vite/tokenAnswers.js +11 -7
  675. package/dist/src/vite/typeParameters.d.ts +83 -0
  676. package/dist/src/vite/typeParameters.js +270 -0
  677. package/dist/src/vite/unionProps.d.ts +37 -0
  678. package/dist/src/vite/unionProps.js +121 -0
  679. package/dist/src/vite/unresolvedTokens.d.ts +20 -0
  680. package/dist/src/vite/unresolvedTokens.js +193 -0
  681. package/dist/src/vite/usageGraph.js +10 -52
  682. package/dist/src/vite/usageGuidance.d.ts +9 -2
  683. package/dist/src/vite/usageGuidance.js +36 -8
  684. package/dist/src/vite/usageImports.d.ts +35 -0
  685. package/dist/src/vite/usageImports.js +280 -0
  686. package/dist/src/vite/visibilityRoute.d.ts +16 -0
  687. package/dist/src/vite/visibilityRoute.js +320 -0
  688. package/dist/src/worstCase.d.ts +2 -0
  689. package/dist/src/worstCase.js +2 -0
  690. package/package.json +28 -8
package/README.md CHANGED
@@ -9,7 +9,12 @@ per story, switches for theme, contrast, motion and language, and a props table
9
9
  > and every change is in the
10
10
  > [changelog](https://github.com/ensiria/forgebook/blob/develop/packages/forgebook/CHANGELOG.md).
11
11
 
12
- **Requirements:** Node 22.18 or later · Vite 8.3.4+ (the catalogue is built on it; other bundlers are not supported) · React 19 through
12
+ New to it? The [documentation](https://github.com/ensiria/forgebook/blob/develop/docs/README.md) starts with
13
+ [getting started](https://github.com/ensiria/forgebook/blob/develop/docs/getting-started.md) and has the how-to guides and
14
+ [troubleshooting](https://github.com/ensiria/forgebook/blob/develop/docs/troubleshooting.md); this README is the full
15
+ reference.
16
+
17
+ **Requirements:** Node 22.18 or later (the catalogue is built on it; other bundlers are not supported) · React 19 through
13
18
  [`@forgebook/react`](https://www.npmjs.com/package/@forgebook/react), Vue 3.5 through
14
19
  [`@forgebook/vue`](https://www.npmjs.com/package/@forgebook/vue) (a Nuxt project's through
15
20
  [`@forgebook/nuxt`](https://www.npmjs.com/package/@forgebook/nuxt)), Svelte 5 through
@@ -47,9 +52,108 @@ sidebar's index, kept with the files they were read from, so a later start answe
47
52
  TypeScript until one of those files, a configuration or the lock file changes. Removing `node_modules/.vite` starts from
48
53
  nothing.
49
54
 
55
+ ## Start with one command
56
+
57
+ ```sh
58
+ npx forgebook init
59
+ ```
60
+
61
+ It asks nothing, so an agent can run it. In the folder of the package that holds the components, it reads the framework
62
+ (React, Vue, Svelte, Solid, Preact, Lit, Angular, Next.js, Nuxt, SvelteKit, React Native Web) and the package manager
63
+ from the project's files, and writes:
64
+
65
+ - `forgebook.config.ts`: the adapter, the title, and story globs over the folders that exist;
66
+ - `forgebook.preview.ts` (`.tsx` where stories are), when the app loads global style sheets: the imports of its entry
67
+ (Vite's `index.css`, a Next.js root layout's `globals.css`, a SvelteKit layout's, `angular.json`'s `styles`), since
68
+ stories look wrong without them. Nuxt's adapter reads `css` from `nuxt.config` itself, so it needs none.
69
+
70
+ Then it prints what is left, each thing named, and the next commands. The packages to add are in the exact command of
71
+ the project's package manager; `--install` runs it. It lists React even on Vue, say, because Forgebook's shell needs it and not every package manager installs a peer by
72
+ itself. Vite is Forgebook's own dependency: a project on an older one installs it beside its own, which stays as it is.
73
+
74
+ ```sh
75
+ npx forgebook new src/Badge.tsx # a component's first stories
76
+ npx forgebook dev # the catalogue, live
77
+ npx forgebook stories --json # what it lists, and what did not read
78
+ ```
79
+
80
+ It writes nothing and exits with an error when:
81
+
82
+ - a file is already there (a configuration or a preview, under any name it is read by): `--force` replaces it;
83
+ - `package.json` names no framework it supports, or two that stand on their own: `--framework <name>` chooses (`html`
84
+ for no framework). An adapter already in `package.json` settles it;
85
+ - a framework, React or Vite in `package.json` cannot reach the version Forgebook takes: the message names each.
86
+
87
+ - the project has a `.storybook` (or `.rnstorybook`) folder: `--from storybook` takes [that route](#from-storybook),
88
+ which loads its `main` and so runs its code, or `--framework <name>` starts from the dependencies;
89
+ - a file it would write is a link: it never writes through one, even with `--force`.
90
+
91
+ `init` runs no code of the project unless `--from storybook` or `--install` asks it to; `--install` is an install like
92
+ any other, with the project's package manager settings and the packages' scripts. `--json` prints the result as a document, a refusal
93
+ too (`refused`, `message`, `hint`, `supported`, exit code 1; a wrong command line is exit code 2, with no document), with `nextSteps` as `{ kind, file, message }`: `kind` is `style-sheet`,
94
+ `provider`, `portal`, `head`, `font`, `postcss`, `setup`, `version` or `storybook`.
95
+
96
+ ### What init cannot work out
97
+
98
+ A catalogue runs no entry of the app, so what one does for the app does not happen for a story. Each of these is
99
+ reported with the file it was read from:
100
+
101
+ - **Providers**, the components that wrap the app, and what it installs (`app.use(router)`, `provideRouter()`): a decorator
102
+ in the preview gives them to the stories that need them.
103
+ - **Portals**: an element beside the app's root in its page (`#modal-root`). A decorator adds it.
104
+ - **The page's head**: a font's or a CDN's `<link>` goes to `head` in the configuration.
105
+
106
+ ### The app's build
107
+
108
+ A catalogue draws your components with your app's build, with nothing to write:
109
+
110
+ | What | Where it is read from | Runs your code? |
111
+ |---|---|---|
112
+ | Aliases | `tsconfig.json`'s `paths` and `baseUrl` (through `extends` and `references`) | No: read as text, Vite resolves them |
113
+ | Aliases, `define`, Sass options, `.env` settings, your Vite plugins (Tailwind's, SVGR…) | `vite.config.*` beside the catalogue's configuration | **Yes**, as `vite dev` does |
114
+ | Tailwind before 4, Autoprefixer, any PostCSS plugin | `postcss.config.*`, `.postcssrc*`, `package.json`'s `postcss`, up to the repository's root | **Yes**: a script, and the plugins any of them names |
115
+
116
+ So every command that starts the catalogue runs those files, on purpose: `forgebook stories` and `check` as well as `dev`.
117
+ The catalogue's own configuration and your components already run there, and this is the build you run every day. A first
118
+ `dev` start loads a `vite.config` twice, as its pre-bundling runs in a process of its own. `forgebook init` never runs them:
119
+ it reads their names and reports them (`appBuild` in `--json`, with `runsCode`). `forgebook dev` prints what it read; what
120
+ could not be read is said on stderr by every command.
121
+
122
+ From a `vite.config`, a catalogue takes how modules and style sheets resolve and compile, and never the app's page,
123
+ server or output (`root`, `base`, `build`, `server`), from the file and from what its plugins' `config` hooks return; a
124
+ plugin that changes the configuration in place is not stopped. A plugin's `configureServer`, where one starts a backend or a
125
+ watcher, runs on `forgebook dev` and not on a command's own server (`stories`, `check`, `verify`, `mcp`). Its plugins go in, apart from
126
+ two kinds: the framework's own, which the adapter brings, and those known to build an app rather than draw a component
127
+ (routers, service workers, source-map uploads, type checkers). That second list is names, so an upload plugin it does not
128
+ know runs on `forgebook build`: name it in `skipPlugins`. A plugin's `transformIndexHtml` reaches the frames, not the
129
+ catalogue's page. A `define` that writes out a whole `process.env` is left out, since a catalogue bundles code the app does
130
+ not. A file that fails to load is said with what to do; stories that do not need it still draw.
131
+
132
+ Not read: the options of the framework's own plugin (`react({ jsxImportSource })` goes to the adapter), and `css.modules`
133
+ (Lightning CSS has `css.lightningcss.cssModules`, and no `localsConvention`); both are said. A workspace's other packages'
134
+ `tsconfig` paths are not looked for, only the catalogue's own folder's, as `extends` and `references` lead on from it.
135
+
136
+ A `vite.config` holding only Vite's import and the framework's plugin is not loaded at all, so a new project pays for
137
+ none of this. Next.js, Nuxt, SvelteKit, Angular and React Native read what is theirs themselves, as their own sections say.
138
+
139
+ To turn it off:
140
+
141
+ ```ts
142
+ export default defineConfig({
143
+ // …
144
+ appBuild: false // or each part:
145
+ // appBuild: { viteConfig: false, postcss: false, tsconfigPaths: false, skipPlugins: ["some-plugin"], keepPlugins: ["react-router"] }
146
+ });
147
+ ```
148
+
149
+ A plugin's name is the one `forgebook dev` prints, not its package's. A PostCSS configuration in YAML is not read (`init`
150
+ says so). PostCSS runs on plain CSS and on a component's `<style>` block, with the sheets they import by relative path; a
151
+ Sass file goes through its own compiler alone. When a framework plugin or the app's `vite.config` sets
152
+ `css.transformer: "postcss"`, Vite runs the project's PostCSS itself and the catalogue does not run it a second time.
153
+
50
154
  ## A first catalogue
51
155
 
52
- A component, with its props typed and documented:
156
+ The same by hand, which is also what the command writes. A component, with its props typed and documented:
53
157
 
54
158
  ```tsx
55
159
  // src/Badge.tsx
@@ -137,16 +241,20 @@ too, with a warning.
137
241
  edit that adds, renames or retitles a story reloads the pages, as an edit of an Angular story file does. On macOS
138
242
  the files you work on (the story files the open frames show, and each file they load once you have edited it) are
139
243
  watched one by one, so an edit reaches the page without the system's change events' wait of a tenth of a second or
140
- more. Where the system's change events come late or never (a container's mounted volume, a Windows drive under WSL,
244
+ more. A checkout that moves the repository to another commit (`git switch`, `git reset --hard`, a pull) is heard
245
+ through git's own files, and each file it wrote reaches the dev server at once: the branch's stories, a removed one
246
+ gone, a new folder's shown, with no restart. Where the system's change events come late or never (a container's mounted volume, a Windows drive under WSL,
141
247
  a network drive), `forgebook dev --poll` checks the files itself.
142
248
  - **Switches** for theme, contrast and motion, and the languages you declare; a library adds its own (density, brand)
143
249
  through a preset. A direction switch draws every story right to left, and a language declared `dir: "rtl"` does
144
250
  it by itself.
145
251
  - **A toolbar each reader arranges**: whoever uses the catalogue pins the controls they use to the toolbar, orders
146
252
  them and hides the rest in the View menu; their browser keeps it ([below](#the-toolbar)).
147
- - **A light and a dark catalogue**: the reader picks Light, Dark or System at the sidebar's foot (their browser keeps
148
- it); `appearance` in the configuration sets the default. The stories keep their own theme, from the view's switches.
149
- - **Keys and named views**: a key cycles a control's values (`t` the theme, Shift+`t` back); the catalogue sets the
253
+ - **A light and a dark catalogue**: the reader picks Light, Dark or System in the Interface menu at the sidebar's foot
254
+ (their browser keeps it); `appearance` in the configuration sets the default. The stories keep their own theme, from the view's switches.
255
+ - **Keys and named views**: `?` lists the keys, as does the menu at the sidebar's foot, where a reader can turn off every
256
+ key without a modifier for this browser; a key pressed inside a story, in a text field or in a custom element stays
257
+ theirs. A key cycles a control's values (`t` the theme, Shift+`t` back); the catalogue sets the
150
258
  key of any control (`keys: { width: "w" }`), a reader changes theirs in the View menu. The View menu's values are
151
259
  saved under a name and picked again; `views` in the configuration offers some to every reader. A dot marks each
152
260
  control whose value is not its default.
@@ -157,7 +265,8 @@ too, with a warning.
157
265
  - **Widths** to draw a story at, and a **compare** view that draws the same story once per value of one or two
158
266
  switches (every theme at both contrasts), per text size or per style sheet, side by side.
159
267
  - **Props from the types**: the API table and the panel's controls come from the component's TypeScript props and
160
- their TSDoc, nothing written twice.
268
+ their TSDoc, nothing written twice: objects and lists as nested fields, mixed unions, tokens and named values too
269
+ ([below](#the-panels-controls)).
161
270
  - **Props in groups**: a component with many props lists them under the groups their TSDoc names (`@group Paging`),
162
271
  and a prop typed with a documented object (`texts?: FinderTexts`) unfolds to list its members
163
272
  ([below](#props-in-groups)).
@@ -165,11 +274,20 @@ too, with a warning.
165
274
  reader turns the ordering off with a switch ([below](#required-props-first)).
166
275
  - **Shared values, checked**: the values set in the Props tab stay in the address (`args=`), so a link shares them.
167
276
  Since whoever writes a link chooses them, a story receives only the props it declares (its component's props, its
168
- `argTypes`, its own args) that the panel lets a person set, each with a value of that prop's type; anything else
169
- (`onclick`, `innerHTML`, a text for a number) is left out and listed above the story, with a button that removes it
170
- from the address. A value that is code never comes from a link.
277
+ `argTypes`, its own args) that the panel lets a person set, each with a value of that prop's type, an object with only
278
+ the fields its type declares; anything else (`onclick`, `innerHTML`, a text for a number) is left out and listed above
279
+ the story, with a button that removes it from the address, as is one that cannot be read at all. A value that is code
280
+ never comes from a link.
281
+ - **Code as you wrote it**: the Code tab and Show code give a story's `render` as written in its file (its own, else
282
+ the meta's; one kept in a constant or a function of the file shows as that code), with its hooks and compound
283
+ components as they are. A story drawn from its args shows its component with each arg the file writes as code
284
+ (`onClick: fn()`, `icon: <IconStar />`, a constant of the file) as written, spreads of the file's objects and of
285
+ another story's args followed, and the plain values as they are now. A value set in the Props tab is written from
286
+ that value. `forgebook story --json` gives the same text as `code`. Vue and Svelte bind such an arg as written
287
+ (`:on-close="fn()"`); Angular, HTML and Web Components still write the plain values only. A story made by a
288
+ helper, imported from another file or written in CSF 4 (`meta.story(…)`) is written from its values.
171
289
  - **The worst case in one press**: the Props tab's Worst case button gives every text prop a long text with a word too
172
- long to break and every number a huge one, kept in the address; the elements that then spill out of their parents
290
+ long to break, every number a huge one and every list many items, nested ones too, kept in the address; the elements that then spill out of their parents
173
291
  are outlined and counted, as the browser tests find them. Reset undoes it.
174
292
  - **Examples that fill the page**: on a component's page, any story's box opens over the page, at a width of its own,
175
293
  without loading its story again.
@@ -228,6 +346,64 @@ shows nowhere, not even on the toolbar, and keeps its default (the width can sti
228
346
  may set both; the catalogue's `toolbar` wins, and a control is off when any of them turns it off. A name in `toolbar`
229
347
  that is no control at all stops the catalogue with an error saying which.
230
348
 
349
+ ### Several visual themes
350
+
351
+ A library with several looks offers them as a switch whose `control` is a gallery: a menu whose items show each look, so a
352
+ reader sees it before applying it.
353
+
354
+ ```ts
355
+ switches: [
356
+ { ...themeSwitch(), label: "Appearance" },
357
+ {
358
+ id: "look",
359
+ label: "Theme",
360
+ control: "gallery",
361
+ apply: { kind: "attribute", name: "data-look" },
362
+ default: "plain",
363
+ values: [
364
+ { value: "plain", label: "Plain", isUnset: true },
365
+ { value: "paper", label: "Paper", preview: { image: "previews/paper.png" }, sheet: "looks/paper.css" },
366
+ {
367
+ value: "night",
368
+ label: "Night",
369
+ preview: { swatches: ["#0b1020", "#7c8cff"], font: "Harbor Sans" },
370
+ implies: { theme: "dark" },
371
+ sheet: "looks/night.css"
372
+ }
373
+ ]
374
+ }
375
+ ]
376
+ ```
377
+
378
+ - **`control: "gallery"`** beside `segments` and `list`. The first load carries only its button: the menu's code, the
379
+ previews and their pictures load when it first opens. Radio buttons, as the shell's other menus: one tab stop, the arrow
380
+ keys move and choose, Escape closes. Each item is named by the value's `label`; a value with no preview shows its first
381
+ letter.
382
+ - **`preview`** is `{ image }`, a file by its path from the configuration's folder (absolute in a preset), or
383
+ `{ swatches, font }`, 1 to 8 plain colours and a font's name. A font is only a name: drawn in it where the reader has it
384
+ installed, never fetched. A preview loads nothing from an address: the configuration's check refuses one, and a `url()`.
385
+ - **`implies`** sets other switches while the value is drawn: a look drawn only for dark selects dark by itself. The
386
+ implied control is off and says what sets it, and its key does nothing. The address keeps the reader's own value, which
387
+ comes back when the value is left: `?look=night&theme=light` draws dark, and the link stays as written. An implied
388
+ value wins over the address and over a story's `globals`; between two values that imply different values of one switch,
389
+ the switch declared first wins; an implied value implies nothing further, which the check enforces. Compare leaves
390
+ out a cell it contradicts (with `look,theme`, Night only at Dark) and does not offer a switch implied now.
391
+ - **`sheet`** is a style sheet of that value alone, processed by Vite in dev and in a build, and fetched only while
392
+ the value is drawn. It comes after the source's sheets, the switches' in the order declared, and only with Styles › Full,
393
+ as the source's theme. Its path may not be an address; its contents are your own CSS, so what it imports is yours to
394
+ decide, as in a source's sheets. On a change the old sheet stays until the new one has loaded, and the frame's root changes with it,
395
+ so a story is never drawn with neither.
396
+
397
+ A source's page colour can follow such a switch, so a story's box waits on the colour it will have:
398
+ `background: { light, dark, bySwitch: { look: { night: { dark: "#0b1020" } } } }`. The first declared switch whose value
399
+ gives the scheme's colour wins; otherwise `light` and `dark`.
400
+
401
+ The catalogue's own menu, at the sidebar's foot, is named Interface, so it reads apart from a switch named Appearance: it
402
+ colours the catalogue around the stories, never the stories. `strings: { appearance: "…" }` renames it; the
403
+ configuration's `appearance` key and `data-forgebook-appearance` keep their names.
404
+
405
+ ### Backgrounds
406
+
231
407
  The Background control offers Forgebook's five pictures and the catalogue's own:
232
408
  `backgrounds: { builtIn: ["checkerboard"], custom: [{ id: "paper", label: "Paper", light: { color: "#fffdf5" } }] }`
233
409
  keeps one picture and adds a plain paper colour (`layers` puts CSS backgrounds over it, `dark` sets another look for the
@@ -434,8 +610,8 @@ export type FinderProps = {
434
610
 
435
611
  - The API reference lists the props that name no group first, then each group under its name, in the order the
436
612
  groups first appear among the props; the events keep their own heading after them. The Props tab does the same: the
437
- props that name no group by control, as before, then each group with its controls, its toggles and the props it
438
- cannot set.
613
+ props that name no group in the order the source declares them, whatever their control, then each group with its
614
+ controls in that order and the props it cannot set.
439
615
  - Every group starts open; a reader folds one away from its name.
440
616
  - To show some groups first, name them in order: `propGroups: ["Selection", "Paging"]` in the configuration for every
441
617
  component, or `parameters: { propGroups: ["Texts"] }` in a component's meta, written as a list of plain strings.
@@ -446,6 +622,33 @@ export type FinderProps = {
446
622
  - With `eslint-plugin-tsdoc`, declare the tag in your `tsdoc.json`:
447
623
  `{ "tagName": "@group", "syntaxKind": "block", "allowMultiple": false }`.
448
624
 
625
+ ## Props a type cannot list plainly
626
+
627
+ Some props types say more than a list of props. The API reference reads them as TypeScript does, and says what it
628
+ could not read:
629
+
630
+ ```tsx
631
+ export type ActionProps<TItem> = (
632
+ | { readonly kind: "link"; readonly href: string }
633
+ | { readonly kind: "button"; readonly onClick: () => void }
634
+ ) & { readonly label: string; readonly items?: readonly TItem[] };
635
+ ```
636
+
637
+ - **A union of variants** lists every variant's props, not only the ones they share. A prop only some variants declare
638
+ is never marked required, and says when it applies: `href` reads "Only when `kind` is `"link"`". The discriminant is
639
+ the shared prop each variant gives one literal value (or leaves out), the one with the most values when several do.
640
+ A prop of a variant that takes the discriminant left out (`mode?: "single"`) says "or left out".
641
+ A prop the variants type differently shows all their types (`Date | Date[] | DateRange`).
642
+ - **A generic component** writes each type parameter it leaves open as the component's constraint, else its default,
643
+ else `unknown`, and says which under the prop: `items` is `readonly unknown[]`, "`TItem` is generic, with no
644
+ constraint". A props type the component fills in (`BaseProps<string>`) is read with what it was given.
645
+ - **A type it cannot read** says so instead of showing nothing: a name the checker cannot find (a missing import), a
646
+ prop typed `any`, props typed `any`, or a component whose props all come from outside its package (an element's
647
+ attributes, which the reference leaves out).
648
+ - `forgebook story --json` and `get_story` carry the same as `onlyWhen`, `notes` on a prop and `propsNote` on the
649
+ component; `forgebook story` writes `href (when kind is link)`, and `CATALOG.md` `href:string[kind=link]` (`[mode?=single]`
650
+ when it also applies with `mode` left out).
651
+
449
652
  ## Required props first
450
653
 
451
654
  The API reference and the Props tab list a component's required props before the others, so a reader sees at once
@@ -474,6 +677,104 @@ export default { component: Finder, parameters: { requiredFirst: false } } satis
474
677
  - Agents get the props in the order of the source and the names of the required ones at the top of
475
678
  `forgebook story --json` and `get_story` (`requiredProps`): the setting shapes the pages only.
476
679
 
680
+ ## The panel's controls
681
+
682
+ The Props tab draws a control for each prop from its type, with nothing to write:
683
+
684
+ | The prop's type | Its control |
685
+ |---|---|
686
+ | `string`, `number`, `boolean` | a field, a number, a toggle; a text with a line break becomes a text area |
687
+ | `"sm" \| "md"` | buttons or a list; a search past 12 values |
688
+ | `readonly string[]`, `{ a: string; b?: number }` | nested fields, with add, remove and reorder by buttons, so a keyboard does it too |
689
+ | `[number, number]`, `Record<string, number>` | a field per item; names and values |
690
+ | `"sm" \| number`, `string \| string[]` | choose the type, then the value |
691
+ | `unknown`, `object`, a type too deep or wider than 40 fields | JSON, checked as it is typed |
692
+ | a component, a function, a node | what the source's `namedValues` offer for its type, searched by name; a node takes a text too |
693
+
694
+ A story names another control the way Storybook's do, and a few of Forgebook's own:
695
+
696
+ ```ts
697
+ argTypes: {
698
+ note: { control: "textarea" },
699
+ options: { control: "object" }, // fields from the type, else from the story's own arg, else JSON
700
+ accent: { control: { type: "token", of: "color" } }, // from the catalogue's `tokens`
701
+ gap: { control: { type: "token", of: "space", format: "var(--{name})" } }, // writes `var(--space-small)`
702
+ cover: { control: { type: "file", accept: "image/*" } }
703
+ }
704
+ ```
705
+
706
+ `of` is a token's type or a part of its name. A prop asks for tokens from its TSDoc as well (`@token color`). The tokens
707
+ load when such a control is drawn; without any to offer it stays a text field.
708
+
709
+ Each value has three states, and the panel keeps them apart: the story's own (nothing in the address), the panel's (an
710
+ empty text included), and no value at all, where the component receives `undefined` over what the story's args give it.
711
+ Beside each field, one button leaves it with no value and another goes back to the story's; a cleared number has no
712
+ value. The address writes no value as `{"forgebookUnset":true}`.
713
+
714
+ Every value is plain JSON, kept in `args=`, text in any script included, and checked when a link is opened, in an embed
715
+ too: an object may hold only the fields its type declares. What JSON's fallback holds has no type to check against, so
716
+ what would run if a component spread the object on an element is left out (`onclick`, `innerHTML`, `srcdoc`, Vue's
717
+ `.innerHTML`, an address that starts with `javascript:`), as is a named value; `__proto__`, `constructor`, `prototype` and
718
+ values nested over 16 levels are not read at all. A token's value is a plain text, as a colour's is, and a link may give
719
+ another. A file is kept in the link as a `data:` address, so a `file` control takes about 6 KB, of a picture, sound, film,
720
+ plain text or a PDF. An object of exactly `of` and `named` reads as a named value. A very long value makes a very long
721
+ address, which some servers refuse, so the worst case leaves out a value too long for one.
722
+
723
+ A `Date` prop gets a date and time field, and the story receives a `Date`; a link writes it as `{"forgebookDate":"<ISO>"}`.
724
+ The `date` control a story names sets a number of ms instead, as Storybook's does.
725
+
726
+ The editors are one chunk that loads when the first such prop is drawn: a catalogue of plain props never asks for it.
727
+
728
+ ### Controls of your own
729
+
730
+ A control the panel lacks is a module of yours, registered by name and loaded when a story names it. A catalogue that
731
+ registers none loads nothing for this.
732
+
733
+ ```ts
734
+ // forgebook.config.ts
735
+ export default defineConfig({ /* … */ argControls: { rating: "./controls/rating.tsx" } });
736
+
737
+ // a story
738
+ argTypes: { score: { control: { type: "rating", settings: { stars: 7 } } } }
739
+ ```
740
+
741
+ ```tsx
742
+ // controls/rating.tsx
743
+ import type { ArgControlProps, ValueSchema } from "forgebook/arg-control";
744
+ import { createRoot } from "react-dom/client";
745
+
746
+ export const schema = { type: "integer", minimum: 0, maximum: 10 } satisfies ValueSchema;
747
+
748
+ export const mount = (element: HTMLElement, props: ArgControlProps) => {
749
+ const root = createRoot(element);
750
+ root.render(<Rating {...props} />);
751
+ return () => root.unmount();
752
+ };
753
+ ```
754
+
755
+ `mount(element, { value, onChange, argType })` draws in the element and returns what takes it away. It is a function rather
756
+ than a component, so it can be written in any framework, whatever the stories' is: `createApp` in Vue, `mount` in Svelte,
757
+ plain DOM. `argType` holds the arg's `name`, `label` and `description`, and the control's `options`, `min`, `max`, `step`
758
+ and `settings`. The control keeps what it draws: it is mounted again only when the value changes from outside it.
759
+
760
+ `schema` says what the value looks like, in JSON Schema's words: `type`, `enum`, `const`, `minimum`, `maximum`, `minLength`,
761
+ `maxLength`, `pattern`, `items`, `minItems`, `maxItems`, `properties`, `required`, `additionalProperties`, `anyOf`. Any other
762
+ keyword is refused, since a schema that says less than it seems to would let a link through, as is a keyword holding what it
763
+ cannot use. A `pattern` has the `u` flag, and may not repeat a repeat (`(a+)+`), which could hang the page. The value is
764
+ always JSON, so a link keeps it and an agent sets it with no UI; what JSON cannot hold goes through named values, as
765
+ `{ of, named }`.
766
+
767
+ A link's value is checked against the schema before it reaches the story, and each `onChange` too. A control no one
768
+ registered, a module that fails to load, a `mount` that throws and a value that does not fit each give a sentence beside the
769
+ field; the other fields go on working. An error the control throws later, in its own event handlers, is out of reach: it is
770
+ the page's.
771
+
772
+ **A custom control runs in the shell's page, with a plugin's trust.** It can read and do whatever the catalogue's page can;
773
+ unlike a story, it has no origin of its own to keep it apart. Register only code you would run as a plugin. To be read by
774
+ agents its module also loads on the dev server when a command asks about a story that names it, for its `schema`: keep what
775
+ touches the page inside `mount`. A name that no control has (`control: "selct"`) is read as a custom control, and says so
776
+ beside the field.
777
+
477
778
  ## Docs pages
478
779
 
479
780
  Guides, foundations and recipes are Markdown files with a little front matter, not MDX: a page is read at build time, and
@@ -503,27 +804,6 @@ The buttons read their colours from the page's theme.
503
804
  ```story acme:actions-button--primary
504
805
  ```
505
806
 
506
- ## Search
507
-
508
- The field at the top of the sidebar searches the whole catalogue. The tree filters by name as you type, for browsing;
509
- beside it a list ranks everything the words find, each component or page with what matched inside it and why (a prop,
510
- an event, a heading, a sentence, a story), the words marked. `/` or ⌘K (Ctrl+K) comes to the field from anywhere (with the sidebar hidden, ⌘K alone,
511
- which shows it), ↑ and ↓ move, Enter opens at the exact heading or prop, ⌘Enter or a modified press opens a new tab, Escape empties the field.
512
-
513
- A prop has an address of its own, so a link to one can be pasted anywhere: `?component=acme:inputs-select#prop.value`,
514
- and `#prop.Group.label` for a prop of a part named in `subcomponents`. A heading of a component's documentation file
515
- has one too (`#accessibility`), as a docs page's has.
516
-
517
- There is no search server and nothing to set up: the plugin builds the index with the catalogue, and the shell loads it
518
- the first time someone types, so a reader who never searches pays nothing. A static build searches as the dev server
519
- does. Only what the page does not already hold goes in the index: under 4 KB gzipped for a small library of ten components
520
- with their documentation and a few guides. On a dev server, the first search waits for your packages' TypeScript for the props; names and docs
521
- pages answer first.
522
-
523
- Search and `forgebook find` rank alike, with the same synonyms: `modal` finds a `Dialog`, and a name counts more than a
524
- sentence. A sentence copied from a page finds that page first. Change the words people see with `strings`, as any
525
- other text of the shell (`"search.kindPage": "Guides"`).
526
-
527
807
  ## The props
528
808
 
529
809
  ```props acme:actions-button
@@ -647,7 +927,7 @@ docs page, with every block above, a few values and the generated home's pieces
647
927
 
648
928
  ````md
649
929
  ---
650
- description: "{{components}} components in {{libraries}} libraries, version {{version}}."
930
+ description: "{{components}} components and {{stories}} stories, version {{version}}."
651
931
  ---
652
932
 
653
933
  Our design system, for every product team.
@@ -687,6 +967,31 @@ page of the catalogue's own `docs`; a library's page is linked by its address (`
687
967
  the file are listed above the home and by `forgebook pages`, and `forgebook page home` reads it as an agent would. Restart
688
968
  `forgebook dev` after adding or removing the file.
689
969
 
970
+ ## Search
971
+
972
+ The field at the top of the sidebar searches the whole catalogue. The tree filters by name as you type, for browsing;
973
+ beside it a list ranks everything the words find, each component or page with what matched inside it and why (a prop,
974
+ an event, a heading, a sentence, a story), the words marked. `/` or ⌘K (Ctrl+K) comes to the field from anywhere (with the sidebar hidden, ⌘K alone,
975
+ which shows it), ↑ and ↓ move, Enter opens at the exact heading or prop, ⌘Enter or a modified press opens a new tab, Escape empties the field.
976
+
977
+ A prop has an address of its own, so a link to one can be pasted anywhere: `?component=acme:inputs-select#prop.value`,
978
+ and `#prop.Group.label` for a prop of a part named in `subcomponents`. A heading of a component's documentation file
979
+ has one too (`#accessibility`), as a docs page's has.
980
+
981
+ There is no search server and nothing to set up: the plugin builds the index with the catalogue, and the shell loads it
982
+ the first time someone types, so a reader who never searches pays nothing. A static build searches as the dev server
983
+ does. Only what the page does not already hold goes in the index: under 4 KB gzipped for a small library of ten components
984
+ with their documentation and a few guides. On a dev server, the first search waits for your packages' TypeScript for the props; names and docs
985
+ pages answer first.
986
+
987
+ Search and `forgebook find` rank alike, with the same synonyms: `modal` finds a `Dialog`, and a name counts more than a
988
+ sentence. A sentence copied from a page finds that page first. For `forgebook find`, `forgebook search`, the dev
989
+ server's API and MCP, a word nothing holds as typed is read as the nearest name, one letter away for a word of four
990
+ to seven letters and two from eight: `buton` finds `Button`, and the answer says what it read. A word that finds
991
+ something is never read as another, so a typo never changes an exact answer. The shell's search reads words as
992
+ typed: reading typos would cost more than its first search's weight allows. Change the words people see with `strings`, as any
993
+ other text of the shell (`"search.kindPage": "Guides"`).
994
+
690
995
  ## Design links
691
996
 
692
997
  A component carries its own link to Figma, on its meta; a story with a design of its own writes it over the meta's:
@@ -724,13 +1029,82 @@ blocks it uses Open in Figma. A catalogue published with a Content Security Poli
724
1029
  `forgebook story` and `get_story` return `design`: the link, the `fileKey` and `nodeId` a Figma tool takes, and the
725
1030
  `address` of the Design tab to hand a person (it opens the story alone without the plugin). `list_stories` gives each component's, and `CATALOG.md` lists it.
726
1031
 
1032
+ ## Stepping through a play
1033
+
1034
+ The Interactions tab lists a play's named steps and each action it took through the `canvas` and `userEvent` of its context,
1035
+ with its time and its failure. **Step through** mounts the story again and stops before each action and each `step`: **Next**
1036
+ does that one, **Continue** runs the rest. A `getBy…` query is logged but cannot stop, as it returns at once. What a play
1037
+ imports itself (`storybook/test`, `@testing-library/user-event`) runs unrecorded: use the context's tools to see it here.
1038
+
1039
+ ## Plays when a story opens
1040
+
1041
+ A story's `play` runs when it opens on a dev server, where its author is checking it. In a build it waits: a reader of
1042
+ published docs did not ask for it, and the Interactions tab offers it with **Run**. A reader changes this for themself in
1043
+ that tab or the View menu (kept in their browser), an address says it for one link (`?play=off`, `?play=on`), and
1044
+ `play: "on"` or `"off"` in the configuration sets the default. Tests, `forgebook check` and `check_story` open a frame with
1045
+ no such word, so they run every play whatever a reader or a catalogue chose.
1046
+
1047
+ ## Tags
1048
+
1049
+ Tag stories as CSF does, in the preview, a file's meta or a story; a `!name` takes one away:
1050
+
1051
+ ```ts
1052
+ export default { component: Button, tags: ["beta"] } satisfies Meta<typeof Button>;
1053
+
1054
+ export const Experiment: StoryObj = { tags: ["!beta", "wip"] };
1055
+ ```
1056
+
1057
+ When any story has a tag of its own, the sidebar offers a filter beside the search: tick a tag to keep the stories that
1058
+ hold it, press its other button to leave them out. A story stays when it holds any tag asked for and none left out. The
1059
+ filter lives in the address (`?tag=beta&tag=!wip`), so a link keeps it, and it holds from page to page; a page opened by
1060
+ its address shows even if the filter leaves it out. `dev`, `test`, `autodocs`, `play-fn` and `test-fn` say what a tool
1061
+ does with a story, and are not offered. Agents ask the same way: `forgebook stories --tag beta --tag '!wip'`, or `tags`
1062
+ on `list_stories`. A tag can also be a [status](#statuses), shown as a badge.
1063
+
1064
+ ## Statuses
1065
+
1066
+ A component's status (waiting for review, experimental, deprecated) is a tag the catalogue declares as a status. Write
1067
+ it on the file's meta for the component, or on a story for that story alone:
1068
+
1069
+ ```ts
1070
+ export default { component: Card, tags: ["review"] } satisfies Meta<typeof Card>;
1071
+
1072
+ export const Flipped: StoryObj = { tags: ["experimental"] };
1073
+ ```
1074
+
1075
+ `review`, `experimental` and `deprecated` are declared by default. A catalogue restyles or renames one, declares its
1076
+ own, or turns one off with `false`; `tone` is `neutral`, `info`, `positive`, `caution` or `critical`:
1077
+
1078
+ ```ts
1079
+ export default defineConfig({
1080
+ statuses: { review: { label: "In review" }, beta: { label: "Beta", tone: "positive" }, experimental: false }
1081
+ });
1082
+ ```
1083
+
1084
+ Once any story has a tag, a status shows as a badge in the component's sidebar entry and at the top of its page, and a
1085
+ story's own beside its example; a page without one looks as before, and a catalogue with no tags loads nothing for them.
1086
+ A component written in several files takes its first file's meta, as its docs do. The [tag filter](#tags) filters by a
1087
+ status as by any tag (`?tag=review`), and shows it as its badge. The default labels are shell texts
1088
+ (`strings: { "statuses.review": "In revisione" }`), and the `caution-text` and `positive-text` theme roles colour their
1089
+ tones. Storybook's status addons write `parameters.status` (`"beta"`, `{ type: "beta" }`): it is read as tags, so declare
1090
+ those statuses to show them.
1091
+
1092
+ In a catalogue with tags, a component deprecated in its TSDoc (`@deprecated`) shows the `deprecated` badge on its page,
1093
+ with the reason in its tooltip, even without the tag. The sidebar reads tags only, so `forgebook story` and `get_story`
1094
+ name the component whose TSDoc and meta disagree: tag the meta so the sidebar and the filter say it, or write
1095
+ `@deprecated` so `check-code` warns where it is imported. Agents read `statuses` on each component and story of
1096
+ `forgebook stories --json`, `list_stories`, `forgebook story --json` and `get_story`, and filter with `--tag review` or
1097
+ `tags`.
1098
+
727
1099
  ## Coming from Storybook
728
1100
 
729
1101
  Forgebook reads Storybook's story files as they are: CSF 3 and CSF 2 (`Template.bind({})`), titles of any depth and
730
1102
  titles from the file's path, `args` and `argTypes` (with their controls), actions from `fn()` or an `argTypes` action,
731
1103
  `play` with Testing Library (`@testing-library/dom` and `@testing-library/user-event`, optional peers), `loaders`,
732
- `tags` (`!dev`, `!test`), a story's `globals`, JSX in `.js` story files (listed and shown as code; Vite compiles JSX only in
733
- `.jsx` and `.tsx`, so such a library adds the plugin its own Storybook uses for them, through the framework's plugins),
1104
+ `tags` (`!dev`, `!test`, and your own for the [tag filter](#tags)), a story's `globals`, JSX in `.js` files, stories and components alike (Vite compiles JSX only in `.jsx` and
1105
+ `.tsx`; with React, Preact or Next.js, Forgebook compiles the catalogue's own `.js` files that hold JSX itself, with the
1106
+ project's JSX options, `jsxInject` and Fast Refresh, and leaves installed packages, the workspace's other packages and
1107
+ `?raw`, `?url` or `?worker` imports alone; a project that sets `oxc: false` compiles its scripts its own way),
734
1108
  hooks in a `render` or a decorator (React and
735
1109
  Preact, with the story's state kept when a decorator draws `<Story />`), Storybook's preview hooks from
736
1110
  `storybook/preview-api` in a React story file (`useArgs`, whose update and reset change the story's args as the panel
@@ -747,6 +1121,14 @@ cannot load (it uses one so, or one of its own files reads `document`) leaves th
747
1121
  answers working: it is left out of them and named among their problems, with what it used. A
748
1122
  `**` pattern skips `node_modules` unless it names it.
749
1123
 
1124
+ A link keeps working too: `args=` reads Storybook's form (`label:Hello+world;count:5;open:!true;tags[0]:a;tags[1]:b`,
1125
+ with `!null`, `!hex(…)`, `!rgb(…)`, `!hsl(…)` and `!date(…)`) as well as Forgebook's own JSON, told apart by JSON's first
1126
+ `{`. Its values are typed by the prop that receives them, so `5` is a number for a number and stays `5` for a text, and they
1127
+ meet the same check as any link's. Forgebook writes its own form once a value changes in the panel. What an arg here
1128
+ cannot hold (an object such as `style.color:red`, a list with a gap) is named above the story, not dropped
1129
+ in silence. An arg's `argTypes.<name>.if` (`{ arg: "kind", eq: "link" }`, `{ global: "theme", neq: "dark" }`, with `truthy`,
1130
+ `exists`, `eq` or `neq`) hides its control the same way Storybook's does, and leaves its value alone.
1131
+
750
1132
  It lists what Storybook's indexer lists:
751
1133
 
752
1134
  - every named export as a story, whatever writes its value: an object, a function, a helper's result
@@ -773,6 +1155,8 @@ and whose root holds the stories, with the paths to the packages' sources, gets
773
1155
  It does not read MDX, doc blocks or addons. Actions are explicit only: an `on*` prop is not turned into an action by
774
1156
  its name.
775
1157
 
1158
+ ### From Storybook
1159
+
776
1160
  To try it on a Storybook project, run `npx forgebook init --from storybook` in the folder that holds `.storybook`. It
777
1161
  writes `forgebook.config.ts`: the story globs of `main` (the MDX pages left out), the preview as Forgebook's preview,
778
1162
  and a switch for each toolbar global of the preview, applied by code as its decorators expect. `main` is loaded, so a
@@ -834,6 +1218,41 @@ A monorepo that points its packages at their sources with an export condition (`
834
1218
  `forgebook` command: its dev server reads the stories and previews it answers tools with on Node under the same
835
1219
  conditions, those of other runtimes (`browser`) aside, unless a plugin names the server's own.
836
1220
 
1221
+ ## Other catalogues, already published
1222
+
1223
+ A catalogue can list another one, built and deployed elsewhere, after its own stories: a product's catalogue showing the
1224
+ design system it uses, from the design system's own site. Each is named in `refs`, by an id of lower-case words:
1225
+
1226
+ ```ts
1227
+ export default defineConfig({
1228
+ framework: react(),
1229
+ title: "Checkout",
1230
+ stories: ["src/**/*.stories.tsx"],
1231
+ refs: {
1232
+ "design-system": { title: "Acme design system", url: "https://design.acme.dev/" }
1233
+ }
1234
+ });
1235
+ ```
1236
+
1237
+ - **What the other catalogue needs.** It is built with `forgebook build --agent-index`, so `forgebook-agent.json` sits
1238
+ beside its pages, and its host lets this catalogue fetch that file (an `Access-Control-Allow-Origin` header) and frame
1239
+ its page (no `frame-ancestors` that leaves this catalogue out). Without the index its section says so, and why.
1240
+ - **Lazy.** Its section starts shut, and its index is fetched only when it is first opened, or when an address shows one
1241
+ of its stories. A catalogue without `refs` loads none of this code.
1242
+ - **Read-only, on its own origin.** A story is drawn by the other catalogue's own embed page (`?embed`), with its own
1243
+ preview and theme, in a frame on its origin, sandboxed as a story's frame is and given only the browser features that
1244
+ ask the reader nothing (full screen, video, writing to the clipboard). Nothing it runs reaches this page, and this page
1245
+ sends it nothing but an address: its controls, panel and docs are in its own page, one click away (*Open in …*). One
1246
+ served on the origin this catalogue's stories run on is refused.
1247
+ - **The toolbar's switches cross.** Every switch of this catalogue goes in the address, its value included when it is
1248
+ the default; the other catalogue keeps those it declares, with values it knows (the theme of both, say), and drops the
1249
+ rest. The width, the device and the panel's values do not cross.
1250
+ - **The address** of one of its stories is `?ref=<id>&story=<its id>`, so it can be shared like any other; a `ref` that
1251
+ names none of them (`?ref=newsletter`, another site's mark) leaves the story this catalogue's. No switch may be named
1252
+ `ref`.
1253
+ - **Not searched.** The search and the tag filter read this catalogue only: searching another would fetch its whole index
1254
+ at the first key. Agents read a published catalogue on its own with `forgebook mcp --from <its address>`.
1255
+
837
1256
  ## A lighter catalogue
838
1257
 
839
1258
  Two features cost the most and are on by default: the accessibility check, which ships axe (about 180 KB gzipped in a
@@ -863,17 +1282,78 @@ export default defineConfig({
863
1282
  with no `docs`, and `forgebook changed` says it finds no story through the imports. `forgebook docs` and `forgebook new`
864
1283
  still read the types when run, since they are asked for that. `usedIn: true` with it is an error.
865
1284
 
1285
+ ## When a configuration is refused
1286
+
1287
+ Everything below stops every command with an exit code of 1 and a message that names the mistake, and a Vite build with
1288
+ the plugin too, since each would otherwise give a catalogue that looks right and is not:
1289
+
1290
+ - **A key nothing reads.** `toolbr: […]` says `it has no key "toolbr". Did you mean toolbar?`; a preset's keys and those of
1291
+ `build`, `shell`, `a11y`, `backgrounds`, `widthRange` and `controls` are checked too. An adapter's and a plugin's options
1292
+ are their own functions' arguments, so nothing adds a key to the configuration.
1293
+ - **A toolbar, a key or a view the shell cannot use**, as [the toolbar](#the-toolbar) says.
1294
+ - **A file that does not load.** A syntax error is named as `/path/forgebook.config.ts:3:3: …`, in the configuration or in a
1295
+ TypeScript file it imports. In a JavaScript file it imports, Node gives no place, and the message names the configuration.
1296
+ - **A story pattern that matches nothing**, for `forgebook build`, `stories` and `check`: each pattern is read on its own,
1297
+ so a mistaken one beside one that works is named as well, and what a `!` pattern leaves out does not count. `verify`
1298
+ answers `not-verified` with the pattern in `skipped` when the change touches a UI file, and still gives the rest of its
1299
+ answer (what changed, the stories that ran, what they found), so the empty pattern never hides a failure. A change with
1300
+ no UI file, such as the commit of `init`'s own files before a first story, is `nothing-to-verify`, with the pattern and
1301
+ how to write the first story in `skipped`.
1302
+ `forgebook dev` warns instead and opens a home that says where it looks, since you may be about to write the first story;
1303
+ saving a file the patterns match shows it. A source's own patterns are its module's to read, and a list of `docs` globs
1304
+ may match nothing.
1305
+ - **Story files in a hidden folder**: a pattern's `**` does not enter a folder whose name starts with a dot
1306
+ (`docs/.vitepress`). Files a pattern would match there are named, with the pattern that lists them
1307
+ (`docs/.vitepress/**/*.stories.ts`): a warning from `forgebook dev`, a problem in `stories`, and the hint when a pattern
1308
+ matches nothing. Nothing stops on them; a `!` pattern for the folder (`!docs/.vitepress/**`) says it is left out on
1309
+ purpose and ends the notice.
1310
+
1311
+ ## Stories that load
1312
+
1313
+ A frame says a story is ready only once what the story loads is in the page, so `check`, `verify`, `shot`, the generated
1314
+ tests and the compare view read the content and never a fallback. A play function starts after the same wait, and the
1315
+ frame waits again after it, for what its clicks load. For React (Next.js and React Native too) and Vue (Nuxt too), that
1316
+ is every `Suspense` boundary, whoever wrote it, however deep; in React also a transition or a deferred value still
1317
+ loading, which shows no fallback.
1318
+
1319
+ The wait is bounded: 10 s by default. Past it the frame's status is `pending`, with the reason on the page and in
1320
+ `data-forgebook-pending-reason`. `check` reports the story `notVerified` and exits non-zero, `verify` answers
1321
+ `not-verified`, `shot` marks the picture `pending`, the generated test fails and the Accessibility card does not pass it:
1322
+ what shows is not what you meant to check. Say so when a story is meant to stay there, or give it longer:
1323
+
1324
+ ```tsx
1325
+ export const Loading = { parameters: { suspense: { expected: true } } }; // a loading state: ready at once
1326
+ export const Slow = { parameters: { suspense: { timeout: 15_000 } } }; // in ms; in the preview, for every story
1327
+ ```
1328
+
1329
+ `check` stops listening to a frame at 30 s, and a generated test at 25 s: past that a longer `timeout` fails as a frame
1330
+ that never answered, never as a pass. A story with `expected` is checked as it first drew, and `verify` names it in
1331
+ `skipped`, so a preview cannot turn the wait off unseen.
1332
+
1333
+ React and Vue do not say what is pending in public, so the adapters read their private tree. Each page first tries that
1334
+ reading on a boundary known to be pending and on one known not to be; on a version of React or Vue where it no longer
1335
+ works, every story is `pending` with that reason instead of ready on a guess. A cost of about one tree walk per story,
1336
+ in the adapter. A root a story creates itself with `createRoot` is out of reach, and so is what a story loads without
1337
+ `Suspense` (a `useEffect` fetch with a spinner): a play function can wait for that with `findBy…`.
1338
+
1339
+ The other adapters have no such wait. Angular's `drawn` waits for the application to be stable. Preact's
1340
+ `preact/compat` `Suspense` and Solid's `<Suspense>` are not read; a story using them is ready once drawn, so its play
1341
+ function has to wait for the content. Svelte, Web Components and plain HTML have no fallback to read (Svelte's `{#await}`
1342
+ is a state of the component: the same).
1343
+
866
1344
  ## Commands
867
1345
 
868
1346
  | Command | What it does |
869
1347
  |---|---|
870
- | `forgebook dev` / `forgebook build` | Runs the catalogue of `forgebook.config.ts`, or builds it into static files |
1348
+ | `forgebook dev` / `forgebook build` | Runs the catalogue of `forgebook.config.ts`, or builds it into static files; see [a story file that cannot be read](#a-story-file-that-cannot-be-read) |
1349
+ | `forgebook build --watch` | Builds again when a file the catalogue reads changes; see [building on every change](#building-on-every-change) |
871
1350
  | `forgebook prebundle` | Pre-bundles the catalogue's dependencies, as `dev` does on a first start: before it, in CI or an image |
872
1351
  | `forgebook stories` | Lists every story with its id and links; fails when the story index has problems |
873
1352
  | `forgebook story <id>` | One story: its args, its component's props, its links in a view (`--view theme=dark`) |
874
- | `forgebook init --from storybook` | Writes `forgebook.config.ts` from a project's `.storybook` (or on-device `.rnstorybook`) folder: its framework, story globs, preview and toolbar globals |
875
- | `forgebook new <file>` | Writes a component's first stories from its props: the main story, one per choice, the worst case |
1353
+ | `forgebook init` | Writes `forgebook.config.ts`, and a preview with the app's global style sheets, from the project's framework; names what it could not work out; `--install` installs, `--json` answers for agents ([more](#start-with-one-command)). `--from storybook` reads a project's `.storybook` (or on-device `.rnstorybook`) folder instead: framework, story globs, preview and toolbar globals |
1354
+ | `forgebook new <file>` | Writes a component's first stories from its props and from where the application draws it: the main story with the values the application gives most, one story per other way it is drawn, one per choice, the worst case; the file says which props it was written for, and `verify` fails when they change. `--repair` draws them in a browser and, when an error says a story must be drawn inside a component the application exports (`useSidebar must be used within a SidebarProvider`), draws them inside it, at most twice |
876
1355
  | `forgebook check <id>` | Runs the catalogue's browser checks on a story (or a component's stories): accessibility, spills, overlays, errors; with `@forgebook/testing` |
1356
+ | `forgebook check <id> --stress` | Draws the story in the states nobody wrote: long text, unbreakable words, huge numbers, empty, right to left, 200 % zoom, narrow, dark, more contrast, and reports what each breaks |
877
1357
  | `forgebook errors` | Lists what the open frames reported while you edited (a story that could not be shown, a failed play); `--follow` keeps listing |
878
1358
  | `forgebook shot <id>` | Takes a story's pictures, one PNG per view, at the view's width and the story's height (framed in a device a view names); with `@forgebook/testing` |
879
1359
  | `forgebook pages` | Lists the docs pages with their ids and addresses; fails when the index has problems |
@@ -882,17 +1362,48 @@ export default defineConfig({
882
1362
  | `forgebook mcp` | Serves the same answers to an agent over the Model Context Protocol |
883
1363
  | `forgebook check-page` | Runs the checks on a real page of the application, by its address |
884
1364
  | `forgebook changed` | Lists the stories a change touches, through what they import |
885
- | `forgebook verify` | Runs the checks on every story a change touches, with one exit code |
1365
+ | `forgebook verify` | Says whether a change is done: every changed UI file in stories that ran, in every variant, and `check-code`, with one exit code |
1366
+ | `forgebook proof` | Compares a change's states with where it started, both drawn in one run, for a pull request's comment |
1367
+ | `forgebook visibility` | Lists the published components an agent cannot see, with the fix for each |
886
1368
  | `forgebook find` | Finds components by what they are for, in your own words |
887
1369
  | `forgebook search` | Searches the whole catalogue by its text: docs pages, props, descriptions, stories and names, with the address of each match |
1370
+ | `forgebook graph` | A map of the components and tokens, generated from the source: what exists, what each is for, how to choose |
1371
+ | `forgebook audit` | The colours, sizes and components a project actually uses, and the components with no story or no use, with no catalogue |
888
1372
  | `forgebook tokens` | The design tokens, one of them, or the token nearest a value (`--nearest "#1c1b1b"`) |
889
1373
  | `forgebook check-code` | Checks what a change adds against the design system, with an exit code for CI |
890
- | `forgebook agents` | Adds Forgebook's instructions to the project's `AGENTS.md` (and an [Agent Skill](https://agentskills.io) with `--skill`, in `.agents/skills` and `.claude/skills`) |
1374
+ | `forgebook init --agents` | What a project's coding agents need too: `.mcp.json`, instructions and skill, CI, a hook running `verify`; `--browser` installs the testing package and its browser, `--draw` draws a story ([more](#set-a-project-up-in-one-prompt)) |
1375
+ | `forgebook hook <assistant>` | What an assistant's hook runs when it is about to finish: `verify` on the change, sending the agent back on red |
1376
+ | `forgebook browser` | Installs the browser the checks run on, with the Playwright that will open it, whatever other Playwright the project has; it adds that one build and never removes another project's; `--with-deps` also installs what it needs of the system |
1377
+ | `forgebook agents` | Adds Forgebook's short instructions to the project's `AGENTS.md` (and an [Agent Skill](https://agentskills.io) with `--skill`, in `.agents/skills` and `.claude/skills`) |
1378
+ | `forgebook guide` | Prints the rest of the instructions on demand: a framework's or a topic's full text |
891
1379
  | `forgebook docs` | Writes a package's `CATALOG.md` and `llms.txt` from its exports, their TSDoc and its stories |
1380
+ | `forgebook migrate` | Rewrites a project for a breaking change: lists the changes (exit 1 while unwritten), writes them with `--write` ([more](#upgrading)) |
892
1381
  | `forgebook-texts` | Checks a package's story texts and lists what each language still has to translate |
893
1382
 
894
1383
  Each command prints its options with `--help`; `stories` and `story` print JSON with `--json`.
895
1384
 
1385
+ ### A story file that cannot be read
1386
+
1387
+ On a dev server, a story file that does not parse, or that has no meta, is one problem and the rest of the catalogue
1388
+ keeps drawing. The problem names the file with its line and column, on the page, in `forgebook stories`, `forgebook
1389
+ errors` and their MCP tools. Saving the fix is enough, with no restart: a story already drawn stays drawn while its file
1390
+ is broken, and redraws in place. `forgebook build` and a test run still fail on it: a build ends with
1391
+ `src/Bad.stories.tsx:4:45 does not parse: …` and a non-zero exit, and only `--verbose` adds the bundler's stack.
1392
+
1393
+ A component, or any other of the project's scripts, that does not parse is one problem too, named with its line and
1394
+ column on the page, in `forgebook stories`, `forgebook errors` and their MCP tools, before any frame loads it; the
1395
+ stories that import it say why in their frame and in `forgebook check`, and the others draw. Saving the fix takes the
1396
+ problem away. Neither it nor a story file stops Vite's dependency scan on a first start: the packages it imports are
1397
+ still pre-bundled with the others', and `forgebook prebundle` prints one line per such script
1398
+ (`The dependency scan skipped src/Broken.tsx:3:24 does not parse: Unexpected token`). What a scan found is kept for
1399
+ later starts; a script broken while no server ran is named once it is edited, or by the frames that import it.
1400
+
1401
+ A story that loads but cannot be drawn says why in its frame and in `forgebook check`. On the dev server, the stack under
1402
+ the reason gives the lines of the files as written: the frame sends it, and the server maps it through the source maps of
1403
+ the modules it served, so the frame loads no map. `forgebook errors` and `recent_errors` give the error's `place`, the
1404
+ first of those lines outside `node_modules` (`src/Button.stories.tsx:3:11`). A static build's stack keeps the lines of the
1405
+ built code.
1406
+
896
1407
  `forgebook build` names each script it writes by its hash alone (`assets/3f9a1c2b.js`): a catalogue names every story
897
1408
  file's scripts once per loader, so shorter names make a smaller build. To read what a build holds, name each script after
898
1409
  its module too (`assets/Button-3f9a1c2b.js`), for one build with `forgebook build --readable-names`, or for every build in
@@ -902,9 +1413,10 @@ the configuration:
902
1413
  export default defineConfig({ /* … */ build: { readableNames: true } });
903
1414
  ```
904
1415
 
905
- A component's docs, a story file's code and a component's page are data, not scripts: a build writes each as a gzipped
906
- `.bin` file, which the page unpacks when it shows it, or in the story index itself when it is shorter than that file
907
- (a story file whose stories are all args has no code).
1416
+ A component's docs, a story file's code and a component's page are data, not scripts: a build writes them gzipped in
1417
+ `.bin` files, neighbouring texts together up to 64 KB of JSON each so they compress as one, which the page unpacks when
1418
+ it shows one; a text no longer than its loader goes in the story index itself (a story file whose stories are all args
1419
+ has no code).
908
1420
 
909
1421
  ## Mocking an API
910
1422
 
@@ -960,39 +1472,109 @@ say what a catalogue has.
960
1472
 
961
1473
  The contract, with how to write one and what it leaves out, is [PLUGINS.md](https://github.com/ensiria/forgebook/blob/develop/packages/forgebook/PLUGINS.md).
962
1474
 
1475
+ ## The states nobody wrote a story for
1476
+
1477
+ `forgebook check <id> --stress` draws a story, then draws it again in each case below, with no story written and nothing
1478
+ saved to the project. Each case lists only what it finds that the plain story does not, so a problem the story already
1479
+ has is not blamed on the case. `check_story` with `stress: true` does the same for an agent.
1480
+
1481
+ | Case | What it gives the story |
1482
+ |---|---|
1483
+ | `long-text`, `unbreakable`, `empty` | every text prop: a long text, a word with no place to break, nothing |
1484
+ | `huge-number` | every number prop: its highest value, or 123,456,789,012 |
1485
+ | `rtl` | text in a right-to-left script, drawn right to left |
1486
+ | `zoom-200` | the story laid out at half the window's width, as a browser at 200 % lays it out |
1487
+ | `narrow` | long text at 320 px |
1488
+ | `dark`, `contrast` | the catalogue's dark scheme and more contrast, when it has them |
1489
+
1490
+ Values reach the story from a page on the catalogue's origin, as the props panel gives them, since a frame takes no values
1491
+ from its address. A case with nothing to set (no text prop, no dark scheme) is in `skipped`, never counted as passed.
1492
+ Overlays and focus order are left to `forgebook check`: no case changes them. A text prop that names something rather
1493
+ than shows it (an id, a class, an address, an icon's slot) is left alone, and in `empty` a missing accessible name is the
1494
+ value's doing and not reported. A frame that does not answer the page (its catalogue set on another origin with
1495
+ `frames.origins`) is reported as not judged, never as passed. It exits non-zero when a case adds a problem or cannot be
1496
+ judged; `--stress` takes no `--view`, `--all-variants` or `--semantic`.
1497
+
1498
+ ## Building on every change
1499
+
1500
+ `forgebook build --watch` stays running and builds again when a file the catalogue reads changes, a new story file or
1501
+ docs page included, for a folder a host, an embedding app or another machine serves. A failed build says why on one line,
1502
+ leaves the last good output and waits for the next edit. A rebuild takes about two thirds of a whole `forgebook build`
1503
+ (2.2 to 2.9 s against 3 to 4 s on 5000 stories) and writes the whole folder again; the process holds about 2 GB there. Use
1504
+ `forgebook dev` to work on stories: it redraws in place.
1505
+
963
1506
  ## A preview for every pull request
1507
+
964
1508
  `forgebook build` writes static files, so any static host gives each pull request its own catalogue, for free. `--base` is
965
1509
  for a host that serves it under a sub-path. A host that sets a `Content-Security-Policy` needs `blob:` in `script-src` for
966
1510
  the Accessibility card: a build keeps axe gzipped, and the frame runs it from a blob once unpacked. It also needs the
967
1511
  catalogue's own origin in `connect-src` (`'self'`): the page fetches the docs, code, pages and "Used in" a build keeps
968
1512
  gzipped. This workflow builds on
969
1513
  every pull request and keeps the result as an artefact; the last step is yours, and any host works:
1514
+
970
1515
  ```yaml
971
1516
  # .github/workflows/catalogue-preview.yml
972
1517
  name: catalogue preview
973
1518
  on:
974
1519
  pull_request:
1520
+
975
1521
  permissions:
976
1522
  contents: read
1523
+
977
1524
  jobs:
978
1525
  preview:
979
1526
  runs-on: ubuntu-latest
980
1527
  steps:
981
- - uses: actions/checkout@v4
982
- - uses: actions/setup-node@v4
1528
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
1529
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
983
1530
  with:
984
1531
  node-version: 24
985
1532
  cache: npm
986
1533
  - run: npm ci
987
1534
  - run: npx forgebook build --out preview --base "/pr-${{ github.event.number }}/"
988
- - uses: actions/upload-artifact@v4
1535
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
1536
+ with:
989
1537
  name: catalogue-preview
990
1538
  path: preview
991
1539
  # then publish the folder, for example:
992
1540
  # GitHub Pages: actions/upload-pages-artifact, then actions/deploy-pages (one site, so without --base per PR)
993
1541
  # Cloudflare: npx wrangler pages deploy preview --branch "pr-${{ github.event.number }}"
994
1542
  # Your server: rsync -az preview/ "user@host:/var/www/previews/pr-${{ github.event.number }}/"
1543
+ ```
1544
+
995
1545
  A pull request from a fork gets no secrets, so a step that deploys only works for branches of your own repository.
1546
+
1547
+ ## Proof in the pull request, made by CI
1548
+
1549
+ `forgebook proof --base origin/main` draws the states a change touches twice in one run, from the commit it is compared with and
1550
+ with the change, and writes `comment.md`, `proof.json`, `index.html` and the pictures. `forgebook proof
1551
+ --write-workflow` writes a GitHub workflow that posts that comment, one per pull request, replaced on each push. Nothing runs
1552
+ outside GitHub, and the pictures are the run's artefact.
1553
+
1554
+ - **No baseline, so nothing for an agent to approve.** The "before" is drawn in this run from where the change left the base (on a pull request's run, the base's tip), in a checkout
1555
+ with its own install and server, and thrown away. `forgebook-baselines` is never read, and `proof` has no `--update`.
1556
+ - **What differs is pictured again.** A state that also differs between two pictures of the same code is `unstable`, and its
1557
+ difference proves nothing. `forgebook proof --base HEAD --all` shows whether a project's pictures hold still between two
1558
+ builds of one commit.
1559
+ - **It says what it did not check:** what `verify` skipped, UI files no story reaches, stories past `--max-stories`, a state
1560
+ that did not draw, and real pages, which no story shows.
1561
+ - **A changed picture is for a person to judge.** The command exits zero once it has a proof, unless `--fail-on-verdict`
1562
+ holds it to `verify`'s verdict, as the workflow does.
1563
+ - **It cannot defend against the code it runs.** The branch's code runs in the comparing job, and a `postinstall` before it,
1564
+ so a hostile branch can forge the result or edit the workflow: no baseline can be approved, but a result can be faked. So
1565
+ that job holds no write token and keeps no credential. The posting job runs nothing of the branch, writes the comment
1566
+ itself from `proof.json` with every name in a code span or a fence, and lists from GitHub which files shape the run
1567
+ (`.github/`, `patches/`, `package.json`, lockfiles, `.npmrc`, the catalogue's configuration and preview). The comment says
1568
+ this at its top. Protect `.github/` with code owners if agents push to your repository, and treat `index.html` in a
1569
+ stranger's artefact as any download.
1570
+ - **A fork's pull request gets no comment.** GitHub gives its run a read-only token, so posting fails and the job goes on:
1571
+ the proof stays in the run's summary and its artefact. Never run this on `pull_request_target`, which would hand a fork's
1572
+ code a write token.
1573
+ - **A picture needs a download.** GitHub cannot show an artefact's picture in a comment, so the comment links the artefact:
1574
+ open `index.html` in it.
1575
+ - **A picture with something from the network proves little.** A story loading a random image reads as `unstable`, or as
1576
+ changed when it differs only between the two sides. Mock what a story fetches.
1577
+
996
1578
  ## Stories on an origin of their own
997
1579
 
998
1580
  A story's code, or a value a shared link puts in one of its props (an `href`, an `html`), runs in its frame. So that it
@@ -1018,6 +1600,10 @@ catalogue as before; `forgebook dev --frames same-origin` does the same for one
1018
1600
  worker, the clipboard, full screen, the camera and the microphone. A story's link can no longer take the catalogue's
1019
1601
  tab to another address.
1020
1602
 
1603
+ A story's style sheets never leave its frame, on any origin: every story draws in a document of its own, so a story
1604
+ file that styles `body` or every `button` leaves the next story, the catalogue's page and the other frames of a docs page
1605
+ as they were, on the dev server and in a static build. What one origin changes is scripts, as above.
1606
+
1021
1607
  What stays reachable from a frame: the code it runs (your stories, their components, what the catalogue imports), the
1022
1608
  errors Vite sends every page while you edit, and `forgebook errors`, where a frame reports its own errors. If the
1023
1609
  default port is taken, the frames move to the next free one, so their storage moves with them; give `--frame-port` to
@@ -1049,8 +1635,10 @@ A command, an agent or `curl` sends no browser headers: `forgebook mcp`, `forgeb
1049
1635
  network, so use it only on one you trust.
1050
1636
 
1051
1637
  ## Your look in the shell
1638
+
1052
1639
  The catalogue's page can take your library's colours, fonts and corners. Nothing runs in the browser for it: the theme is
1053
1640
  written into the page at build, and the frames are left alone, since they belong to your stories.
1641
+
1054
1642
  ```ts
1055
1643
  // forgebook.config.ts
1056
1644
  shell: {
@@ -1059,16 +1647,31 @@ shell: {
1059
1647
  dark: { accent: "#b28bff" },
1060
1648
  fonts: { sans: "Inter, sans-serif" },
1061
1649
  radius: { control: "4px", card: "8px" }
1650
+ }
1062
1651
  }
1652
+ ```
1653
+
1654
+ A library with design tokens (`tokens` in the configuration) can theme the shell from them in a few lines. Each role takes the
1655
+ token's value in both appearances, its `light` and `dark` themes first; colours written by hand win, and a token that
1656
+ is not there or is no colour is warned about and leaves the shell's own. The theme is read when the configuration is, so
1657
+ restart after editing the tokens.
1658
+
1659
+ ```ts
1660
+ shell: { theme: { fromTokens: { accent: "color.brand.primary", surface: "color.background.card" } } }
1661
+ ```
1662
+
1063
1663
  Every role is optional, and typed by `ShellTheme` (`import type { ShellTheme } from "forgebook/shell-theme"`): the grounds
1064
1664
  `window`, `sidebar`, `surface`; `separator`, `hover`; the texts `text`, `text-secondary`, `text-tertiary`, `accent-text`,
1065
- `danger-text`; `accent`; and the `code-*` colours. Renaming or removing a role is a breaking change. A preset can give a
1665
+ `danger-text`, `caution-text`, `positive-text` (the last two colour the [status badges](#statuses)); `accent`; and the `code-*` colours. Renaming or removing a role is a breaking change. A preset can give a
1066
1666
  theme too, and the catalogue's wins role by role.
1067
- The reader's Appearance menu also offers **Follow the story**, where the catalogue has a theme switch: a dark story in a
1667
+
1668
+ The reader's Interface menu also offers **Follow the story**, where the catalogue has a theme switch: a dark story in a
1068
1669
  dark shell. It stays on the system's while comparing, since several themes share the stage. `appearance: "story"` makes
1069
1670
  it the catalogue's default; a reader's own choice always wins.
1671
+
1070
1672
  When the catalogue starts, a role that does not exist is named, and so is a hex colour that leaves a text or code under
1071
1673
  4.5:1 on its ground, or the accent, which draws the keyboard's focus, under 3:1. Other colour notations are not checked.
1674
+
1072
1675
  Fonts are yours to load: a web font goes in a style sheet of your own, `shell.css`, with `@font-face`. That sheet loads
1073
1676
  after the shell's. It is also an escape hatch, since the shell's class names are not public API and can change in any
1074
1677
  release. Layout is not themable, though a font does change how wide text runs.
@@ -1120,31 +1723,80 @@ missing-story messages, and the box a frame shows when a story fails.
1120
1723
 
1121
1724
  ## For agents
1122
1725
 
1123
- `forgebook agents` gives a project's coding agents what they need without being told: how to write a story file here,
1124
- and the commands that check one, as a section of `AGENTS.md` (renewed in place when it runs again; `--skill` writes
1125
- the same as an Agent Skill any agent can load).
1726
+ ### Set a project up in one prompt
1727
+
1728
+ ```sh
1729
+ npx forgebook init --agents --browser --draw --json
1730
+ ```
1731
+
1732
+ Unattended, it writes the catalogue's files, then:
1733
+
1734
+ - **`.mcp.json`**, with Forgebook's server beside the ones it holds.
1735
+ - **`AGENTS.md`** (Forgebook's section, its other sections kept) **and the skill**, in `.agents/skills` and `.claude/skills`.
1736
+ - **A CI workflow**, `.github/workflows/forgebook-verify.yml`, running `forgebook verify` against a pull request's target.
1737
+ - **A hook that runs `verify`**, so an agent cannot finish on red. `--hooks` names them; by default those of the assistants
1738
+ the repository shows signs of, otherwise the commit's.
1739
+
1740
+ `--browser` installs `@forgebook/testing` and its browser, about 200 MB, and implies `--install`. `--draw` then writes a
1741
+ component's first stories and draws them in the browser, trying components until one draws and removing the stories of those
1742
+ that do not. If components fail for want of a provider, on React, the wrappers the app's entry mounts it in are copied into the
1743
+ preview as a decorator (`draw.liftedProviders`), and stay there if a story then draws. When none does, each attempt is in `draw.attempts` with a `kind` (`missing-import`, `provider`, `style-sheet`,
1744
+ `server-only`, `native-build`, `blank`…), what was said and what to do; the exit code is then 1.
1745
+
1746
+ `--agents` merges and never replaces what the project wrote (the skill's file is Forgebook's own, and is renewed): a JSON file it cannot parse, a link, a workflow or a commit hook already there stays as
1747
+ it is and is named in `nextSteps`. It keeps a catalogue already there and starts beside a Storybook, loading nothing of it.
1748
+ In a workspace's package, the files go at the repository's root, and find the package through its folder; a repository that
1749
+ does not track the package (a home folder kept in git, say) is not used, and they go in the package's folder.
1750
+
1751
+ | `--hooks` | Writes | When | On red |
1752
+ |---|---|---|---|
1753
+ | `claude` | `.claude/settings.json`, `Stop` | Claude Code is about to finish | Sent back (exit 2) |
1754
+ | `codex` | `.codex/hooks.json`, `Stop` | Codex is about to finish, once the hook is reviewed and trusted | Sent back (exit 2) |
1755
+ | `gemini` | `.gemini/settings.json`, `AfterAgent` | Gemini CLI's turn ends | Sent back (exit 2) |
1756
+ | `cursor` | `.cursor/hooks.json`, `stop` | Cursor's agent ends | Another turn starts with the reason: its `stop` hook cannot refuse |
1757
+ | `pre-commit` | `.husky/pre-commit`, else `.git/hooks/pre-commit` | A commit (`verify --quick`) | The commit is refused |
1758
+
1759
+ Those formats are the ones each assistant's documentation gives; no assistant was run against them here. An assistant not
1760
+ listed reads the instructions, and meets the commit's hook.
1761
+
1762
+ The hook is `forgebook hook <assistant>`. Each time an assistant stops, it loads the catalogue's configuration, so the
1763
+ project's code runs unattended there as it does for `verify`. A branch that changed no UI file since it left its default
1764
+ branch starts no server. A failure that comes back the same while the hook itself is what continued the turn lets the agent
1765
+ finish, told not to call the change done: an agent that cannot fix something must not spin on it. A hook that cannot run lets
1766
+ the agent finish, with a word on stderr, because no agent can repair it. The commit's hook refuses a commit the same way, on
1767
+ what the branch changed and not only what is staged; `git commit --no-verify` is the way past it, and a clone that has not
1768
+ installed yet commits as before.
1769
+
1770
+ `forgebook init` alone runs none of the project's code. `--draw` does, as starting a catalogue does: see [the app's
1771
+ build](#the-apps-build). An install runs what the project's package manager settings and the packages' scripts say.
1772
+
1773
+ ### What agents read
1774
+
1775
+ A story's values can be set without the panel: `controls` in `forgebook story --json` and `get_story` says what each prop
1776
+ takes, and `forgebook story <id> --args '<json>'` or `story_address` with `args` checks the values as a link's are and
1777
+ answers the links that carry them ([the panel's controls](#the-panels-controls)).
1778
+
1779
+ `forgebook agents` gives a project's coding agents what they need without being told, as a section of `AGENTS.md` of under
1780
+ 3 KB (renewed in place when it runs again; `--skill` writes the same as an Agent Skill any agent can load): what to run
1781
+ before saying a change is done, how to look things up, and how to write a story in this project's framework, read from its
1782
+ catalogue or its `package.json` (`--framework` names another). Agents work better with text they ask for than with a long
1783
+ file, so the rest waits for them: `forgebook guide` lists the topics (a framework, `stories`, `devices`, `switches`, `docs-pages`,
1784
+ `links`, `commands`, `setup`), `forgebook guide <topic>` prints one and `forgebook guide all` the whole guide.
1126
1785
 
1127
1786
  A coding agent can use the catalogue while it works: find a story's id, read a story's args and its component's
1128
1787
  props, and hand a person the link that opens it. Add the MCP server to the project's agent configuration, for
1129
1788
  example `.mcp.json` for Claude Code:
1130
1789
 
1131
- ```
1132
-
1133
- A library with design tokens (`tokens` in the configuration) can theme the shell from them in a few lines. Each role takes the
1134
- token's value in both appearances, its `light` and `dark` themes first; colours written by hand win, and a token that
1135
- is not there or is no colour is warned about and leaves the shell's own. The theme is read when the configuration is, so
1136
- restart after editing the tokens.
1137
-
1138
- ```ts
1139
- shell: { theme: { fromTokens: { accent: "color.brand.primary", surface: "color.background.card" } } }
1140
1790
  ```json
1141
1791
  { "mcpServers": { "forgebook": { "command": "npx", "args": ["forgebook", "mcp"] } } }
1142
1792
  ```
1143
1793
 
1144
- It offers eighteen tools: `visual_diff`, `check_code`, `check_page`, which checks a real page of the application, `list_stories`, `changed_stories`, `find_component`, which finds a component by what it is for, `get_story`, `story_address`, `new_stories`, which writes a component's first stories from its props and answers the text without writing a file, `check_story`, which runs the catalogue's browser checks on a story and answers its problems (the project needs `@forgebook/testing` and Playwright for it), `recent_errors`, what the frames open in a browser reported while the agent edited (numbered: `since` gives only the new ones), and `story_shot`, a story's pictures in the answer itself, so the agent looks at what it made, `list_pages` and `get_page`, which read the catalogue's docs pages as Markdown, and `search_catalogue`, the search people use. `check`, `shot` and their tools take a view in the address's form (`theme=dark&width=360`) or as words (`"dark it 360"`); every story's `links.component` opens its component's page in that view, so `--view audience=designer` on `forgebook story` and `get_story` gives a link to send a designer. `get_story` also gives the components whose stories use the story's component (`usedIn`), so an agent finds a real use before writing one; `list_stories` gives it for every component when asked (`usedIn: true`, or `forgebook stories --used-in`), since it reads the package's import graph. Run from the catalogue's folder (or give
1794
+ It offers 23 tools: `verify`, which says whether a change is done, `visual_diff`, `check_code`, `component_graph`, a map of the components and tokens to read instead of opening files, `check_page`, which checks a real page of the application, `list_stories`, `changed_stories`, `find_component`, which finds a component by what it is for, `get_story`, `story_address`, `new_stories`, which writes a component's first stories from its props and answers the text without writing a file, `check_story`, which runs the catalogue's browser checks on a story and answers its problems (the project needs `@forgebook/testing` and Playwright for it), `recent_errors`, what the frames open in a browser reported while the agent edited (numbered: `since` gives only the new ones), and `story_shot`, a story's pictures in the answer itself, so the agent looks at what it made, `list_pages` and `get_page`, which read the catalogue's docs pages as Markdown, `search_catalogue`, the search people use, `list_tokens`, `get_token` and `nearest_token`, the design tokens, `list_plugins`, what the catalogue's plugins add, `list_switches`, its switches and each value's view, and `get_guide`, the guide above, a topic at a time. `check`, `shot` and their tools take a view in the address's form (`theme=dark&width=360`) or as words (`"dark it 360"`); every story's `links.component` opens its component's page in that view, so `--view audience=designer` on `forgebook story` and `get_story` gives a link to send a designer. `get_story` also gives the components whose stories use the story's component (`usedIn`), so an agent finds a real use before writing one; `list_stories` gives it for every component when asked (`usedIn: true`, or `forgebook stories --used-in`), since it reads the package's import graph. Run from the catalogue's folder (or give
1145
1795
  `--config`), it uses the running `forgebook dev` when there is one, and starts a dev server of its own otherwise,
1146
1796
  kept while the agent's session lasts; that server keeps its pre-bundled dependencies in
1147
- `node_modules/.vite/forgebook-commands`, apart from those of a `forgebook dev` running in the same folder. The links name `http://localhost:5173` unless `--url` (or `FORGEBOOK_URL`) says
1797
+ `node_modules/.vite/forgebook-commands`, apart from those of a `forgebook dev` running in the same folder; a second
1798
+ command's server running at the same time (a `verify` while the MCP server serves) uses a folder of its own beside it,
1799
+ removed when it stops. The links name `http://localhost:5173` unless `--url` (or `FORGEBOOK_URL`) says
1148
1800
  where `forgebook dev` runs.
1149
1801
 
1150
1802
  `get_story` gives a story's design too (`design`, [above](#design-links)), so an agent can read the node with a Figma tool
@@ -1167,31 +1819,41 @@ page's words are replaceable as the shell's are (`strings`): `previewOpen`, `pre
1167
1819
 
1168
1820
  A component's TSDoc can say what a person knows and an agent cannot guess: `@useWhen`, `@avoidWhen`, `@alternatives`,
1169
1821
  `@deprecated` and `@replacedBy`. `forgebook story` and `get_story` return them as `docs.guidance`.
1170
- The most common mistake of an agent working on a design system is a colour or a size written by hand. Name your
1171
- [DTCG](https://www.designtokens.org/tr/2025.10/) files in the configuration, the base first and each theme in a file of
1172
- its own, and agents can ask what to write instead:
1822
+
1823
+ The most common mistake of an agent working on a design system is a colour or a size written by hand. Agents can ask what
1824
+ to write instead, with nothing set up: Forgebook reads what the application already declares (see `check-code` below). To
1825
+ say it yourself, name your [DTCG](https://www.designtokens.org/tr/2025.10/) files in the configuration, the base first and
1826
+ each theme in a file of its own, and those are the system:
1827
+
1173
1828
  ```ts
1174
1829
  tokens: ["tokens.json", { file: "dark.tokens.json", mode: "dark" }]
1175
1830
  ```
1831
+
1176
1832
  A library gives its tokens to every catalogue that shows it: the same list on its source, by path from the module that
1177
1833
  declares the source. It is read from that module's text, never by running it, so a broken story cannot hide a token: write
1178
1834
  it in the object of `export const source`, with plain strings and paths inside the package. A source re-exported or
1179
1835
  spread from another module gives no tokens.
1836
+
1180
1837
  ```ts
1181
1838
  export const source: StorySource = { id: "acme-ui", tokens: ["tokens.json"] /* … */ };
1182
1839
  ```
1840
+
1183
1841
  A catalogue reads each source's files in its `sources` order, then its own, so its aliases reach a library's palette. When
1184
1842
  two authors give one token different values in the same theme the last stands, which makes the catalogue's own the final
1185
1843
  word: it is what puts the libraries together. The answer says so in `clashes` (`kept`, `replaced`), the command warns,
1186
1844
  and neither fails: a clash is a choice to review, not a token that cannot be read. A file over another may write only
1187
1845
  `$value`: the token keeps its type, description and deprecation.
1846
+
1188
1847
  ```sh
1189
1848
  npx forgebook tokens --category color --json
1190
1849
  npx forgebook tokens --nearest "#1c1b1b" --json # the nearest tokens, and whether each is really close
1850
+ ```
1851
+
1191
1852
  `forgebook mcp` offers the same as `list_tokens`, `get_token` and `nearest_token`. References (`{a.b}`, `$ref`), `$extends`
1192
1853
  and `$root` are followed, and a base alias follows what a theme overrides. Deprecated tokens are never suggested. Colours
1193
1854
  in sRGB, Display P3, Oklab, Oklch and HSL are compared; other spaces are listed but counted as `uncompared`. A theme can
1194
- reference the base; a `$ref` reaches only its own file.
1855
+ reference the base; a `$ref` reaches only its own file. A token whose aliases lead back to it, lead nowhere, or come to an
1856
+ empty value is named in `problems` and left out, since a browser would draw it with nothing.
1195
1857
 
1196
1858
  An agent that cannot find a component writes a new one, often because the code and the designers use different words.
1197
1859
  `forgebook build --agent-index` adds `forgebook-agent.json` to the built catalogue, and `forgebook mcp --from <address or
@@ -1202,7 +1864,9 @@ tokens, and anyone who reaches the site can read it, so it is written only when
1202
1864
  `forgebook find` and `find_component` search names, the meta's `keywords`, titles and stories, with the usual synonyms
1203
1865
  (`modal` finds a `Dialog`): write `keywords: ["radio tile group"]` on `OptionCards` and it is found.
1204
1866
  `forgebook search` and `search_catalogue` read the rest, with the same ranking: a prop's name, a sentence of a docs page,
1205
- each result with the words it missed and the address that opens the exact heading or prop.
1867
+ each result with the words it missed and the address that opens the exact heading or prop. Both answers carry
1868
+ `corrections`, each word read as another (`{ "typed": "buton", "read": "button" }`), empty when the query was read as
1869
+ typed.
1206
1870
 
1207
1871
  `forgebook check <id> --semantic` also asks a model what axe cannot see: whether a heading describes its section, an
1208
1872
  image's text says what it shows, a label says what its control does. It is off unless asked, and sends each story's
@@ -1211,10 +1875,155 @@ when it needs one, `FORGEBOOK_SEMANTIC_KEY`. No model comes with Forgebook and n
1211
1875
  `judgements`, apart from the problems, as an opinion: it does not fail the check.
1212
1876
 
1213
1877
  `forgebook check-code` and `check_code` read what a change adds, new files included, from where it left `--since`: a colour
1214
- written by hand, with the token to use when one clearly fits; a size that equals a token; a check turned off with no
1878
+ written by hand, with the token to use when one clearly fits; a size that equals a token, in a sheet, a class's brackets
1879
+ or a React style object, where a bare number is pixels (`style={{ padding: 16 }}`, a `CSSProperties`, `styled.div({ … })`).
1880
+ A bare number on a line that does not say its object is a style is only `advice`, since an option has the same keys
1881
+ (`fitView({ padding: 16 })`). Then a check turned off with no
1215
1882
  reason (`@ts-ignore`, `eslint-disable`, `biome-ignore`, `stylelint-disable`); a test deleted. Only styles and components
1216
1883
  are read for values: stories, tests, token definitions and generated files are left alone. A fix is a token's name, not
1217
- code to paste. It does not check props, imports or deprecated components. It exits non-zero on a problem, for CI.
1884
+ code to paste. It does not check props, which the type checker does. It exits non-zero on a problem, for CI.
1885
+
1886
+ It also reads what a change reuses. An added import of a component whose own TSDoc says `@deprecated` or `@replacedBy` fails,
1887
+ naming what to use. A new exported component fails as `duplicate-component` when its code is a copy of another's under any name;
1888
+ or when it has the name of one that exists, past words like `Primary` or `Custom`, and two signs of being it (a telling root
1889
+ such as `button`, shared props, nearly the same classes); or when `Button` exists and a new `CustomButton` renders a plain
1890
+ `<button>`, though not a `SubmitButton`, which says what it is for. New means new since the commit compared with: an edit or a
1891
+ moved file is not. It compares only what the file could use, in its package and those its package depends on. It passes if it
1892
+ renders the other, which is reuse, or if a comment says why, above it: `// forgebook-ignore duplicate-component: why`, listed
1893
+ in `excused`. One sign, and what `@useWhen` and `@avoidWhen` say of a component just imported, are `advice`, which fails nothing.
1894
+ Imports are followed relative, through `@/`, `~/` and `#/` under the importing file's own folders, and by a workspace package's
1895
+ name; not through a third party.
1896
+
1897
+ **It needs no tokens file.** With none named, it compares with what the application already declares, read as text and never
1898
+ run: custom properties at the root and in theme selectors (`.dark`, `[data-theme]`, a colour-scheme query), and a selector
1899
+ holding a dozen or more of them, as a library's root does; Tailwind 4's `@theme` and default theme; a Tailwind configuration
1900
+ and its presets, as far as they are written plainly; the sheet and the configuration `components.json` names. `tokenSources`
1901
+ says which files were read and `tokenNotes` what needs running to know. A token a browser would give no value is a problem,
1902
+ as a broken tokens file is: one whose references lead back to itself, or one that reads a name with no fallback that
1903
+ nothing declares: no sheet read, no `@property`, no package sheet it imports, and no file of the repository that sets it
1904
+ (in quotes, as `next/font`'s `variable: "--font-sans"`, or as a declaration in a template or a `.vue` style block).
1905
+ Tailwind's `@theme inline { --font-sans: var(--font-sans); }` reads the name set elsewhere, which is no cycle. Where that
1906
+ cannot be known (a package sheet not read, names a Sass loop builds, a cycle only inside a theme, which depends on the
1907
+ element the theme is set on), the token is a note instead, which fails nothing. A name only code builds (`` `--${key}` ``)
1908
+ is not seen: give such a reference a fallback. Fewer than five colours is not a palette, so colours
1909
+ are then left to `skipped`. A value it cannot judge takes a comment on its line or the one above, with the reason:
1910
+ `/* forgebook-ignore raw-color: a brand's own colour */`; the answer lists each one in `excused`, with its reason. Only files
1911
+ in the catalogue's folder are compared (`notCompared` names the others), since another package has its own system. Nothing
1912
+ outside the repository is read, whatever a file names, and a catalogue's `build --agent-index` carries these tokens. `tokens:
1913
+ []` in the configuration says the application is not to be read: with no source giving tokens, values are then not checked,
1914
+ `colours and sizes not checked: no tokens file`.
1915
+
1916
+ What it leaves alone on purpose, since these are where false alarms came from on real projects: a drawing's colours (`<path
1917
+ fill>`, gradient stops, a canvas), masks, fully transparent ends of gradients, black or white in a shadow, a `var()`'s fallback,
1918
+ what the page's head reads (`theme-color`), emails and generated social images. A size is compared with tokens of its own
1919
+ role (spacing, radius, font size) that are steps of a scale, so `--sidebar-padding: 16px` does not make every `16px` a
1920
+ mistake; Tailwind's own scale counts only where a class's brackets hold the whole value (`p-[16px]`, not `h-[calc(100%-16px)]`).
1921
+
1922
+ A design system can say how to choose among fixed patterns and how its parts fit, in a few tags of a component's TSDoc, with
1923
+ nothing new to learn:
1924
+
1925
+ ```ts
1926
+ /**
1927
+ * Pick one of a few options, all in view.
1928
+ *
1929
+ * @intent choose-one: up to five options, all visible
1930
+ * @parent Form, Fieldset
1931
+ * @children Radio
1932
+ * @insteadOf select
1933
+ */
1934
+ export const RadioGroup = …
1935
+ ```
1936
+
1937
+ Components sharing an `@intent` are the choices for it, and agents read them with `forgebook graph --intent choose-one` or
1938
+ `component_graph`, or as `advice` when they import one. `check-code` enforces what can be checked, in `.tsx` and `.jsx` only,
1939
+ as `composition`: an element under a component `@parent` does not allow; a component `@children` or `@siblings` does not allow;
1940
+ a plain `<select>` where `@insteadOf` names one. An element at the root of what a component returns, or held in a prop, may be
1941
+ rendered anywhere, so its parent is not judged; a component above that itself renders an allowed parent passes; and which pattern a screen should have used is not something a check can tell. A file beside a
1942
+ component that cannot carry a comment says the same, named after the file or the component: `radio-group.rules.json` or
1943
+ `RadioGroup.rules.json`, `{ "RadioGroup": { "intent": ["choose-one: up to five options"], "parent": ["Form"] } }`. A meant exception takes `// forgebook-ignore composition:
1944
+ why`, listed in `excused`.
1945
+
1946
+ `forgebook graph` is the map itself, generated from the source so it cannot drift: components, what each is for, what renders
1947
+ what, token counts; `--component Button` adds what renders it and the tokens its file uses. It needs no catalogue.
1948
+
1949
+ `forgebook audit` reports what a project actually uses, read from its files, with no catalogue, no configuration and no code
1950
+ run: `37 greys, 5 used 90 % of the time`. It is for a project with no design system as much as one with: colours in any
1951
+ notation counted as one, how many go through tokens and how many are written by hand, sizes by what they are for, and
1952
+ components that look like one, by name and by what they render, take and carry, never by name alone. It also says where
1953
+ a catalogue rots: exported components no story file imports (`withoutStories`), and components with stories that nothing
1954
+ but stories and tests imports or draws (`storiesUnused`), each with its story files. Pages, layouts and routes are in
1955
+ neither list. A package that goes to a registry (named and not private) never has its components called unused, since
1956
+ their users are elsewhere; a workspace's private package is judged by what the repository does with it, so audit the
1957
+ repository's root to see its users. An import it cannot follow (a barrel, an alias, a package's name) counts for every
1958
+ component of that name, so a listed component is one nothing in the project could be. It exits 0: it is a report, and `check-code` is what fails. With `--json`, `actions` lists the next steps, the largest first, each with the
1959
+ command that lists what to edit:
1960
+
1961
+ ```sh
1962
+ npx forgebook audit --json
1963
+ npx forgebook audit --value "#64748b" --json # every line that writes it by hand
1964
+ ```
1965
+
1966
+ It does not read a tokens file a catalogue names, only what the application declares, and a `.js` file's JSX is not read.
1967
+ A component a framework registers by its folder (Nuxt's `<BaseButton>` for `components/base/Button.vue`) is matched only by
1968
+ its own name, so it can be listed as unused.
1969
+
1970
+ `forgebook verify` and `verify` are what an agent runs before saying a change is done, and what a pull request's workflow
1971
+ runs. A change cannot pass on nothing:
1972
+
1973
+ ```sh
1974
+ $ npx forgebook verify --since origin/develop
1975
+ src/Badge.tsx not verified: no story reaches it. Fix: npx forgebook new src/Badge.tsx
1976
+ 2 changed UI files, 1 with stories: not verified; colours and sizes not checked: no tokens file
1977
+ ```
1978
+
1979
+ - **Every changed UI file is covered or fails.** A UI file is a component or a style sheet by its extension (`.tsx`, `.jsx`,
1980
+ `.vue`, `.svelte`, `.astro`, `.component.ts`, `.component.html`, `.css`, `.scss`, `.sass`, `.less`), a story file, or a
1981
+ script whose text defines or draws a component (`customElements.define`, `LitElement`, `@Component`, `defineComponent`,
1982
+ JSX in a `.js` file). Tests, type declarations and generated files are not, and neither is any other script: a helper
1983
+ or a hook does not fail, and the stories it reaches still run. What `check-code` finds in a file no one sees (a turned-off
1984
+ check, a deleted test) is a note in the answer; `check-code` itself still fails on it.
1985
+ - **A file used through another component counts, and says so.** Stories reach a file through what they render and what
1986
+ those files import, by the file that declares each imported name, so being exported from a barrel covers nothing. A
1987
+ sheet counts through whatever imports it, `@use` and `@import` followed; a preview and the sheets it names are shown by
1988
+ every story. Only stories that ran count: a project with no browser gets `not-verified`, and the reason.
1989
+ - **What was not checked is never reported as passed.** `skipped` is in the verdict (`partly-verified`) and in the line:
1990
+ colours and sizes without a tokens file or with one that cannot be read, accessibility with `a11y: false`, a UI file only
1991
+ another catalogue of the repository can answer for. None of these fails. A UI file nothing reaches in a package with no
1992
+ catalogue of its own does: it is this catalogue's to show. So does a package whose types point at its build, since
1993
+ imports stop there.
1994
+ - **Only what the change brought fails.** The stories that found something run again on the commit the change starts
1995
+ from, checked out in a worktree beside the repository (`.<repository>-forgebook-base-<commit>-<process>`) and removed
1996
+ after, the working tree untouched; the base's configuration and stories run there, as yours do. A problem
1997
+ they had there too is set apart in `existing` and said in the line ("2 problems the stories had before the change not
1998
+ counted"), so an application whose stories already break a rule can still be verified. `--all-problems` fails on
1999
+ every problem. When the base cannot run, every problem counts and `skipped` says why.
2000
+ - **Stories written for other props fail.** A story file `forgebook new` wrote says which props it was written for
2001
+ (`// forgebook-props: 1a2b3c4d`). When a change reaches it and the component's props no longer match, `verify` lists the
2002
+ file in `outdated` and fails, since a framework ignores a prop that is gone and never shows one that is new: check the
2003
+ args, then set the line to the signature it names, or write the file again with `forgebook new <component file> --force`, which replaces any edit.
2004
+ - **It compares from where the branch left.** `--since <ref>` starts from the merge base, so what the base gained since is
2005
+ not read as your change; with no `--since`, from the default branch (`origin/HEAD`, then `main` or `master`), so what you
2006
+ committed counts. A branch cut from another, as `develop`, gives it with `--since`. With no `--since`, an empty change
2007
+ is `not-verified`: the work may be committed where this cannot see, as in a shallow clone. CI gives `--since` and the
2008
+ history: `fetch-depth: 0`.
2009
+ - **A published component an agent cannot see fails.** A component a package's entries export, when the change edits it or
2010
+ starts exporting it, needs a story about it (its meta names it, or a search finds it by name), one story not tagged
2011
+ `!dev`, props an agent can read, and TSDoc on it or a `docs.description.component`. Each finding names its fix. A part
2012
+ named after its component (`DialogTrigger`) is seen on that page, and a provider owes no story. An application publishes
2013
+ nothing, so this asks nothing of it. `forgebook visibility` lists every such component in the repository, for a first look:
2014
+
2015
+ ```sh
2016
+ $ npx forgebook visibility
2017
+ src/Avatar.tsx agents cannot see it: no story is about Avatar, so a search for it finds nothing. Fix: npx forgebook new src/Avatar.tsx
2018
+ 12 published component files, 1 agents cannot see.
2019
+ ```
2020
+ - **Every variant by default**, each story in light, dark, both at more contrast, the structure only, and narrow, on one
2021
+ browser, four pages at once. `--quick` runs the default view, and the verdict says so.
2022
+
2023
+ The exit is non-zero on `failed` and `not-verified`, zero on `verified`, `partly-verified` and `nothing-to-verify`. The
2024
+ JSON answer is schema 2: `verdict`, `summary`, `skipped`, `since`, `base`, `variants`, `files`, `uiFiles` (each with its
2025
+ `coverage`, and its `reason` and `fix` when not covered), `storyCount`, `stories` (the first twenty, with their links),
2026
+ `ran`, `failures` (only what found something), `notVerified` (stories still loading when the frame gave up), `code` (`checked`, `problems`, `notes`) and `problems`.
1218
2027
 
1219
2028
  A library tells agents what it offers with `forgebook docs`, run in its folder: `CATALOG.md`, one dense line per
1220
2029
  component, hook, helper and style module (what it is, how to import it, its props, the id of a story that shows it),
@@ -1226,9 +2035,42 @@ package's `package.json`:
1226
2035
  { "forgebook": { "catalog": { "file": "CATALOG.md", "sections": ["components", "pages", "modules"], "exclude": ["./internal/*"] } } }
1227
2036
  ```
1228
2037
 
1229
- `forgebook docs --check` fails in CI when either file is stale. In CI, `forgebook stories --json` fails on a broken story file (a title taken twice, a title that cannot be placed) or a
2038
+ `forgebook docs --check` fails in CI when either file is stale. In CI, `forgebook stories --json` fails on a broken story file (a title taken twice, a title that cannot be placed, a file that does not parse) or a
1230
2039
  docs page that names what is not there, and its JSON lists every story for a script.
1231
2040
 
2041
+ ## Upgrading
2042
+
2043
+ While Forgebook is 0.x, a minor version (0.3 to 0.4) may break, and a patch never does. Every breaking change is in the
2044
+ package's changelog with what to do, and where the rewrite is mechanical, `forgebook migrate` makes it:
2045
+
2046
+ ```sh
2047
+ npx forgebook migrate --from 0.3.3 # lists what changes since 0.3.3, writes nothing
2048
+ npx forgebook migrate --from 0.3.3 --write # makes the changes
2049
+ npx forgebook migrate src/preset.ts # a library's preset module too, beside the configuration
2050
+ ```
2051
+
2052
+ It reads the configuration and the files given as text, runs none of their code, and keeps their formatting: only what a
2053
+ codemod rewrites moves, and each file is written whole or not at all. A file given must be inside the folder it runs in
2054
+ and outside `node_modules`. Run twice, it finds nothing the second time. It exits 1 while it lists changes it has not
2055
+ written, and 0 otherwise: `advice` (what a codemod could not see into, such as a configuration built by a function) and
2056
+ `notes` (the breaking changes no codemod can make) are to read, and leave the exit code at 0. `--json` answers `changes`,
2057
+ `advice`, `skipped` and `notes`. With no `--from` it runs only the rewrites of what no longer works; a codemod that keeps
2058
+ an old behaviour (`play: "on"`) runs when `--from` says the project comes from before it, or by name with `--only`.
2059
+ `--from` names `forgebook`'s version; a note of another package says that package's version and is always listed.
2060
+
2061
+ | From forgebook 0.3 to 0.4 | `forgebook migrate` |
2062
+ |---|---|
2063
+ | The strings `propGroups.choice`, `.text`, `.structured` and `.toggle` are gone: the Props tab lists props in their source's order | removes them from `strings` (`prop-group-strings`) |
2064
+ | A built catalogue no longer runs a story's play when it opens | writes `play: "on"` to keep it (`play-on-in-builds`); leave it out for the new default |
2065
+ | A configuration key nothing reads, a toolbar naming no control and a story pattern matching no file stop the commands, which name them | in `notes`; fix what they name |
2066
+ | The catalogue draws stories with the app's own build: tsconfig paths, the `vite.config` beside it (its code runs) and PostCSS | in `notes`; `appBuild: false`, or one part off, for a catalogue that set them up by hand |
2067
+ | `verify` fails on a changed UI file with no story that ran, its JSON is schema 2, and it fails on a published component agents cannot see | in `notes` |
2068
+ | `check-code` reads the application's design system with no tokens file, compares bare sizes in React style objects, and fails on duplicate and deprecated components | in `notes`; `tokens: []` says there is no system |
2069
+ | `@forgebook/story-format` 0.3: a story file's code entries are `StoryCode \| StoryArgsCode` | in `notes`; narrow with `"text" in entry` |
2070
+
2071
+ What counts as breaking, how long a deprecation lasts and what must be true before 1.0:
2072
+ [the version policy](https://github.com/ensiria/forgebook/blob/develop/CONTRIBUTING.md#version-policy).
2073
+
1232
2074
  ## Packages
1233
2075
 
1234
2076
  | Package | What it is |