brut 0.0.26 → 0.0.28

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 (386) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/brutrb.com/.vitepress/config.mjs +2 -0
  4. data/brutrb.com/ai.md +6 -1
  5. data/brutrb.com/components.md +1 -1
  6. data/brutrb.com/dev-environment.md +6 -5
  7. data/brutrb.com/doc-conventions.md +1 -1
  8. data/brutrb.com/forms.md +22 -26
  9. data/brutrb.com/getting-started.md +94 -23
  10. data/brutrb.com/instrumentation.md +12 -0
  11. data/brutrb.com/layouts.md +130 -0
  12. data/brutrb.com/lsp.md +23 -0
  13. data/docs/404.html +2 -2
  14. data/docs/ai.html +5 -5
  15. data/docs/api/Brut/BackEnd/SeedData.html +1 -1
  16. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +1 -1
  17. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +1 -1
  18. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +1 -1
  19. data/docs/api/Brut/BackEnd/Sidekiq.html +1 -1
  20. data/docs/api/Brut/BackEnd/Validators/FormValidator.html +1 -1
  21. data/docs/api/Brut/BackEnd/Validators.html +1 -1
  22. data/docs/api/Brut/BackEnd.html +1 -1
  23. data/docs/api/Brut/CLI/App.html +38 -13
  24. data/docs/api/Brut/CLI/AppRunner.html +1 -1
  25. data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +2 -2
  26. data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +2 -2
  27. data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +2 -2
  28. data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +2 -2
  29. data/docs/api/Brut/CLI/Apps/BuildAssets.html +1 -1
  30. data/docs/api/Brut/CLI/Apps/DB/Create.html +2 -2
  31. data/docs/api/Brut/CLI/Apps/DB/Drop.html +2 -2
  32. data/docs/api/Brut/CLI/Apps/DB/Migrate.html +9 -3
  33. data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +11 -11
  34. data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +2 -2
  35. data/docs/api/Brut/CLI/Apps/DB/Seed.html +2 -2
  36. data/docs/api/Brut/CLI/Apps/DB/Status.html +12 -12
  37. data/docs/api/Brut/CLI/Apps/DB.html +1 -1
  38. data/docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html +270 -0
  39. data/docs/api/Brut/CLI/Apps/DeployBase.html +257 -0
  40. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html +585 -0
  41. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html +196 -0
  42. data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +1 -1
  43. data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +2 -2
  44. data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +2 -2
  45. data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +2 -2
  46. data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +2 -2
  47. data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +2 -2
  48. data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +1 -1
  49. data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +2 -2
  50. data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +1 -1
  51. data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +2 -2
  52. data/docs/api/Brut/CLI/Apps/Scaffold.html +1 -1
  53. data/docs/api/Brut/CLI/Apps/Test/Audit.html +12 -10
  54. data/docs/api/Brut/CLI/Apps/Test/E2e.html +8 -8
  55. data/docs/api/Brut/CLI/Apps/Test/JS.html +9 -9
  56. data/docs/api/Brut/CLI/Apps/Test/Run.html +18 -18
  57. data/docs/api/Brut/CLI/Apps/Test.html +1 -1
  58. data/docs/api/Brut/CLI/Apps.html +2 -2
  59. data/docs/api/Brut/CLI/Command.html +113 -28
  60. data/docs/api/Brut/CLI/Error.html +1 -1
  61. data/docs/api/Brut/CLI/ExecutionResults/Result.html +1 -1
  62. data/docs/api/Brut/CLI/ExecutionResults.html +1 -1
  63. data/docs/api/Brut/CLI/Executor.html +169 -38
  64. data/docs/api/Brut/CLI/InvalidOption.html +1 -1
  65. data/docs/api/Brut/CLI/Options.html +68 -19
  66. data/docs/api/Brut/CLI/Output.html +1 -1
  67. data/docs/api/Brut/CLI/SystemExecError.html +1 -1
  68. data/docs/api/Brut/CLI.html +1 -1
  69. data/docs/api/Brut/FactoryBot.html +1 -1
  70. data/docs/api/Brut/Framework/App.html +1 -1
  71. data/docs/api/Brut/Framework/Config.html +1 -1
  72. data/docs/api/Brut/Framework/Container.html +110 -29
  73. data/docs/api/Brut/Framework/Error.html +1 -1
  74. data/docs/api/Brut/Framework/Errors/AbstractMethod.html +89 -1
  75. data/docs/api/Brut/Framework/Errors/Bug.html +1 -1
  76. data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +1 -1
  77. data/docs/api/Brut/Framework/Errors/MissingParameter.html +1 -1
  78. data/docs/api/Brut/Framework/Errors/NoClassForPath.html +1 -1
  79. data/docs/api/Brut/Framework/Errors/NotFound.html +1 -1
  80. data/docs/api/Brut/Framework/Errors/NotImplemented.html +1 -1
  81. data/docs/api/Brut/Framework/Errors.html +31 -8
  82. data/docs/api/Brut/Framework/FussyTypeEnforcement.html +1 -1
  83. data/docs/api/Brut/Framework/MCP.html +1 -1
  84. data/docs/api/Brut/Framework/ProjectEnvironment.html +1 -1
  85. data/docs/api/Brut/Framework.html +1 -1
  86. data/docs/api/Brut/FrontEnd/AssetPathResolver.html +1 -1
  87. data/docs/api/Brut/FrontEnd/Component/Helpers.html +36 -26
  88. data/docs/api/Brut/FrontEnd/Component.html +7 -7
  89. data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +1 -1
  90. data/docs/api/Brut/FrontEnd/Components/FormTag.html +37 -29
  91. data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +1 -1
  92. data/docs/api/Brut/FrontEnd/Components/Input.html +1 -1
  93. data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +1 -1
  94. data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +20 -117
  95. data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +25 -23
  96. data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +73 -380
  97. data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +22 -138
  98. data/docs/api/Brut/FrontEnd/Components/Inputs.html +1 -1
  99. data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +1 -1
  100. data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +1 -1
  101. data/docs/api/Brut/FrontEnd/Components/TimeTag.html +1 -1
  102. data/docs/api/Brut/FrontEnd/Components/Traceparent.html +1 -1
  103. data/docs/api/Brut/FrontEnd/Components.html +23 -2
  104. data/docs/api/Brut/FrontEnd/Download.html +1 -1
  105. data/docs/api/Brut/FrontEnd/Flash.html +1 -1
  106. data/docs/api/Brut/FrontEnd/Form.html +1 -1
  107. data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +24 -68
  108. data/docs/api/Brut/FrontEnd/Forms/Input.html +1 -1
  109. data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +4 -4
  110. data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +1 -1
  111. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +1 -1
  112. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +1 -1
  113. data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +1 -1
  114. data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +1 -1
  115. data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +72 -22
  116. data/docs/api/Brut/FrontEnd/Forms.html +1 -1
  117. data/docs/api/Brut/FrontEnd/GenericResponse.html +1 -1
  118. data/docs/api/Brut/FrontEnd/Handler.html +1 -1
  119. data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +1 -1
  120. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +1 -1
  121. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +1 -1
  122. data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +1 -1
  123. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +1 -1
  124. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +1 -1
  125. data/docs/api/Brut/FrontEnd/Handlers.html +1 -1
  126. data/docs/api/Brut/FrontEnd/HandlingResults.html +1 -1
  127. data/docs/api/Brut/FrontEnd/HttpMethod.html +1 -1
  128. data/docs/api/Brut/FrontEnd/HttpStatus.html +1 -1
  129. data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +1 -1
  130. data/docs/api/Brut/FrontEnd/Layout.html +1 -1
  131. data/docs/api/Brut/FrontEnd/Middleware.html +1 -1
  132. data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +1 -1
  133. data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +1 -1
  134. data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +1 -1
  135. data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +6 -2
  136. data/docs/api/Brut/FrontEnd/Middlewares.html +1 -1
  137. data/docs/api/Brut/FrontEnd/Page.html +1 -1
  138. data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +1 -1
  139. data/docs/api/Brut/FrontEnd/Pages.html +1 -1
  140. data/docs/api/Brut/FrontEnd/RequestContext.html +1 -1
  141. data/docs/api/Brut/FrontEnd/RouteHook.html +1 -1
  142. data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +1 -1
  143. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +1 -1
  144. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +1 -1
  145. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +1 -1
  146. data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +1 -1
  147. data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +1 -1
  148. data/docs/api/Brut/FrontEnd/RouteHooks.html +1 -1
  149. data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +1 -1
  150. data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +1 -1
  151. data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +1 -1
  152. data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +1 -1
  153. data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +1 -1
  154. data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +1 -1
  155. data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +1 -1
  156. data/docs/api/Brut/FrontEnd/Routing/Route.html +1 -1
  157. data/docs/api/Brut/FrontEnd/Routing.html +1 -1
  158. data/docs/api/Brut/FrontEnd/Session.html +1 -1
  159. data/docs/api/Brut/FrontEnd.html +1 -1
  160. data/docs/api/Brut/I18n/BaseMethods.html +1 -1
  161. data/docs/api/Brut/I18n/ForBackEnd.html +1 -1
  162. data/docs/api/Brut/I18n/ForCLI.html +1 -1
  163. data/docs/api/Brut/I18n/ForHTML.html +1 -1
  164. data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +1 -1
  165. data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +1 -1
  166. data/docs/api/Brut/I18n.html +1 -1
  167. data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +1 -1
  168. data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +1 -1
  169. data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +1 -1
  170. data/docs/api/Brut/Instrumentation/OpenTelemetry.html +1 -1
  171. data/docs/api/Brut/Instrumentation.html +1 -1
  172. data/docs/api/Brut/SinatraHelpers/ClassMethods.html +1 -1
  173. data/docs/api/Brut/SinatraHelpers.html +1 -1
  174. data/docs/api/Brut/SpecSupport/ClockSupport.html +1 -1
  175. data/docs/api/Brut/SpecSupport/ComponentSupport.html +1 -1
  176. data/docs/api/Brut/SpecSupport/E2ETestServer.html +20 -20
  177. data/docs/api/Brut/SpecSupport/E2eSupport.html +1 -1
  178. data/docs/api/Brut/SpecSupport/EnhancedNode.html +1 -1
  179. data/docs/api/Brut/SpecSupport/FlashSupport.html +1 -1
  180. data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +1 -1
  181. data/docs/api/Brut/SpecSupport/GeneralSupport.html +1 -1
  182. data/docs/api/Brut/SpecSupport/HandlerSupport.html +2 -2
  183. data/docs/api/Brut/SpecSupport/Matchers/BeABug.html +142 -0
  184. data/docs/api/Brut/SpecSupport/Matchers/BePageFor.html +142 -0
  185. data/docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html +155 -0
  186. data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +55 -25
  187. data/docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html +149 -0
  188. data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +46 -19
  189. data/docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html +149 -0
  190. data/docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html +149 -0
  191. data/docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html +165 -0
  192. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html +158 -0
  193. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html +156 -0
  194. data/docs/api/Brut/SpecSupport/Matchers.html +2 -2
  195. data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +24 -24
  196. data/docs/api/Brut/SpecSupport/RSpecSetup.html +55 -20
  197. data/docs/api/Brut/SpecSupport/SessionSupport.html +1 -1
  198. data/docs/api/Brut/SpecSupport.html +1 -1
  199. data/docs/api/Brut.html +1 -1
  200. data/docs/api/Clock.html +1 -1
  201. data/docs/api/RichString.html +1 -1
  202. data/docs/api/SemanticLogger/Appender/Async.html +1 -1
  203. data/docs/api/Sequel/Extensions/BrutInstrumentation.html +5 -1
  204. data/docs/api/Sequel/Extensions/BrutMigrations.html +36 -28
  205. data/docs/api/Sequel/Extensions.html +1 -1
  206. data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +1 -1
  207. data/docs/api/Sequel/Plugins/CreatedAt.html +1 -1
  208. data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +1 -1
  209. data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +1 -1
  210. data/docs/api/Sequel/Plugins/ExternalId.html +1 -1
  211. data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +1 -1
  212. data/docs/api/Sequel/Plugins/FindBang.html +1 -1
  213. data/docs/api/Sequel/Plugins.html +1 -1
  214. data/docs/api/Sequel.html +1 -1
  215. data/docs/api/SpecSupport/Matchers/BeABug.html +143 -0
  216. data/docs/api/_index.html +92 -1
  217. data/docs/api/class_list.html +1 -1
  218. data/docs/api/file.README.html +1 -1
  219. data/docs/api/index.html +1 -1
  220. data/docs/api/method_list.html +392 -336
  221. data/docs/api/top-level-namespace.html +1 -1
  222. data/docs/assets/{ai.md.tZrjP9im.js → ai.md._6HCDL6d.js} +1 -1
  223. data/docs/assets/ai.md._6HCDL6d.lean.js +1 -0
  224. data/docs/assets/{app.D_yaTITQ.js → app.BX81XO4N.js} +1 -1
  225. data/docs/assets/chunks/@localSearchIndexroot.CoYzciVi.js +1 -0
  226. data/docs/assets/chunks/{VPLocalSearchBox.B2-ZzyTY.js → VPLocalSearchBox.gABXcTWp.js} +1 -1
  227. data/docs/assets/chunks/{theme.CfGFVRvE.js → theme.DwUXXAL3.js} +2 -2
  228. data/docs/assets/{components.md.eCttGlN-.js → components.md.CRUMdRoN.js} +1 -1
  229. data/docs/assets/{configuration.md.BRriU0cL.js → configuration.md.BGHl8oRC.js} +1 -1
  230. data/docs/assets/{dev-environment.md.BNc8AYiK.js → dev-environment.md.GZv6xvi9.js} +1 -1
  231. data/docs/assets/doc-conventions.md.-kN3Xo5C.js +1 -0
  232. data/docs/assets/{doc-conventions.md.DCfRXXi-.lean.js → doc-conventions.md.-kN3Xo5C.lean.js} +1 -1
  233. data/docs/assets/{forms.md.CBTYQ_Cz.js → forms.md.B-koVgyw.js} +23 -23
  234. data/docs/assets/{forms.md.CBTYQ_Cz.lean.js → forms.md.B-koVgyw.lean.js} +1 -1
  235. data/docs/assets/getting-started.md.Ciz82L0m.js +25 -0
  236. data/docs/assets/getting-started.md.Ciz82L0m.lean.js +1 -0
  237. data/docs/assets/{instrumentation.md.CL6ax7nT.js → instrumentation.md.a9Pjps4P.js} +2 -2
  238. data/docs/assets/{instrumentation.md.CL6ax7nT.lean.js → instrumentation.md.a9Pjps4P.lean.js} +1 -1
  239. data/docs/assets/layouts.md.cPnh3NId.js +51 -0
  240. data/docs/assets/layouts.md.cPnh3NId.lean.js +1 -0
  241. data/docs/assets/lsp.md.Bsu-f6VU.js +1 -0
  242. data/docs/assets/lsp.md.Bsu-f6VU.lean.js +1 -0
  243. data/docs/assets/{overview.md.CDalkuxV.js → overview.md.C5wlBcR5.js} +3 -3
  244. data/docs/assets/recipes_authentication.md.CAsXf7hk.js +1 -0
  245. data/docs/assets/recipes_authentication.md.CAsXf7hk.lean.js +1 -0
  246. data/docs/assets.html +4 -4
  247. data/docs/brut-js/api/AjaxSubmit.html +1 -1
  248. data/docs/brut-js/api/AjaxSubmit.js.html +1 -1
  249. data/docs/brut-js/api/Autosubmit.html +1 -1
  250. data/docs/brut-js/api/Autosubmit.js.html +1 -1
  251. data/docs/brut-js/api/BaseCustomElement.html +1 -1
  252. data/docs/brut-js/api/BaseCustomElement.js.html +1 -1
  253. data/docs/brut-js/api/BrutCustomElements.html +1 -1
  254. data/docs/brut-js/api/BufferedLogger.html +1 -1
  255. data/docs/brut-js/api/ConfirmSubmit.html +1 -1
  256. data/docs/brut-js/api/ConfirmSubmit.js.html +1 -1
  257. data/docs/brut-js/api/ConfirmationDialog.html +1 -1
  258. data/docs/brut-js/api/ConfirmationDialog.js.html +1 -1
  259. data/docs/brut-js/api/ConstraintViolationMessage.html +1 -1
  260. data/docs/brut-js/api/ConstraintViolationMessage.js.html +1 -1
  261. data/docs/brut-js/api/ConstraintViolationMessages.html +1 -1
  262. data/docs/brut-js/api/ConstraintViolationMessages.js.html +1 -1
  263. data/docs/brut-js/api/CopyToClipboard.html +1 -1
  264. data/docs/brut-js/api/CopyToClipboard.js.html +1 -1
  265. data/docs/brut-js/api/Form.html +1 -1
  266. data/docs/brut-js/api/Form.js.html +1 -1
  267. data/docs/brut-js/api/I18nTranslation.html +1 -1
  268. data/docs/brut-js/api/I18nTranslation.js.html +1 -1
  269. data/docs/brut-js/api/LocaleDetection.html +1 -1
  270. data/docs/brut-js/api/LocaleDetection.js.html +1 -1
  271. data/docs/brut-js/api/Logger.html +1 -1
  272. data/docs/brut-js/api/Logger.js.html +1 -1
  273. data/docs/brut-js/api/Message.html +1 -1
  274. data/docs/brut-js/api/Message.js.html +1 -1
  275. data/docs/brut-js/api/PrefixedLogger.html +1 -1
  276. data/docs/brut-js/api/RichString.html +1 -1
  277. data/docs/brut-js/api/RichString.js.html +1 -1
  278. data/docs/brut-js/api/Tabs.html +1 -1
  279. data/docs/brut-js/api/Tabs.js.html +1 -1
  280. data/docs/brut-js/api/Tracing.html +1 -1
  281. data/docs/brut-js/api/Tracing.js.html +1 -1
  282. data/docs/brut-js/api/external-CustomElementRegistry.html +1 -1
  283. data/docs/brut-js/api/external-Performance.html +1 -1
  284. data/docs/brut-js/api/external-Promise.html +1 -1
  285. data/docs/brut-js/api/external-ValidityState.html +1 -1
  286. data/docs/brut-js/api/external-Window.html +1 -1
  287. data/docs/brut-js/api/external-fetch.html +1 -1
  288. data/docs/brut-js/api/global.html +1 -1
  289. data/docs/brut-js/api/index.html +1 -1
  290. data/docs/brut-js/api/index.js.html +1 -1
  291. data/docs/brut-js/api/module-testing.html +1 -1
  292. data/docs/brut-js/api/testing.AssetMetadata.html +1 -1
  293. data/docs/brut-js/api/testing.AssetMetadataLoader.html +1 -1
  294. data/docs/brut-js/api/testing.CustomElementTest.html +1 -1
  295. data/docs/brut-js/api/testing.DOMCreator.html +1 -1
  296. data/docs/brut-js/api/testing_AssetMetadata.js.html +1 -1
  297. data/docs/brut-js/api/testing_AssetMetadataLoader.js.html +1 -1
  298. data/docs/brut-js/api/testing_CustomElementTest.js.html +1 -1
  299. data/docs/brut-js/api/testing_DOMCreator.js.html +1 -1
  300. data/docs/brut-js/api/testing_index.js.html +1 -1
  301. data/docs/brut-js.html +4 -4
  302. data/docs/business-logic.html +4 -4
  303. data/docs/cli.html +4 -4
  304. data/docs/components.html +6 -6
  305. data/docs/configuration.html +5 -5
  306. data/docs/css.html +4 -4
  307. data/docs/custom-element-tests.html +4 -4
  308. data/docs/database-access.html +4 -4
  309. data/docs/database-schema.html +4 -4
  310. data/docs/deployment.html +4 -4
  311. data/docs/dev-environment.html +5 -5
  312. data/docs/doc-conventions.html +5 -5
  313. data/docs/end-to-end-tests.html +4 -4
  314. data/docs/flash-and-session.html +4 -4
  315. data/docs/forms.html +27 -27
  316. data/docs/getting-started.html +29 -6
  317. data/docs/handlers.html +4 -4
  318. data/docs/hashmap.json +1 -1
  319. data/docs/hooks.html +4 -4
  320. data/docs/i18n.html +4 -4
  321. data/docs/index.html +3 -3
  322. data/docs/instrumentation.html +5 -5
  323. data/docs/javascript.html +4 -4
  324. data/docs/jobs.html +4 -4
  325. data/docs/keyword-injection.html +4 -4
  326. data/docs/layouts.html +74 -0
  327. data/docs/lsp.html +24 -0
  328. data/docs/markdown-examples.html +4 -4
  329. data/docs/middleware.html +4 -4
  330. data/docs/not-released.html +4 -4
  331. data/docs/overview.html +8 -8
  332. data/docs/pages.html +5 -5
  333. data/docs/recipes/authentication.html +24 -0
  334. data/docs/routes.html +4 -4
  335. data/docs/security.html +4 -4
  336. data/docs/seed-data.html +4 -4
  337. data/docs/space-time-continuum.html +4 -4
  338. data/docs/tutorial.html +4 -4
  339. data/docs/unit-tests.html +4 -4
  340. data/lib/brut/cli/app.rb +7 -2
  341. data/lib/brut/cli/apps/deploy_base.rb +86 -0
  342. data/lib/brut/cli/apps/heroku_container_based_deploy.rb +194 -0
  343. data/lib/brut/cli/apps/test.rb +2 -1
  344. data/lib/brut/cli/command.rb +7 -13
  345. data/lib/brut/cli/executor.rb +31 -5
  346. data/lib/brut/cli/options.rb +4 -0
  347. data/lib/brut/cli.rb +4 -3
  348. data/lib/brut/framework/container.rb +25 -7
  349. data/lib/brut/framework/errors/abstract_method.rb +7 -0
  350. data/lib/brut/framework/errors.rb +4 -2
  351. data/lib/brut/front_end/component.rb +33 -9
  352. data/lib/brut/front_end/components/inputs/select_tag_with_options.rb +16 -74
  353. data/lib/brut/front_end/forms/constraint_violation.rb +2 -18
  354. data/lib/brut/front_end/forms/input.rb +8 -8
  355. data/lib/brut/front_end/forms/input_declarations.rb +3 -3
  356. data/lib/brut/front_end/forms/radio_button_group_input.rb +1 -1
  357. data/lib/brut/front_end/forms/select_input.rb +1 -1
  358. data/lib/brut/front_end/forms/validity_state.rb +23 -0
  359. data/lib/brut/front_end/middlewares/reload_app.rb +2 -0
  360. data/lib/brut/spec_support/handler_support.rb +1 -1
  361. data/lib/brut/spec_support/matcher.rb +1 -1
  362. data/lib/brut/spec_support/matchers/be_a_bug.rb +11 -0
  363. data/lib/brut/spec_support/matchers/be_page_for.rb +10 -0
  364. data/lib/brut/spec_support/matchers/be_routing_for.rb +18 -0
  365. data/lib/brut/spec_support/matchers/have_constraint_violation.rb +10 -0
  366. data/lib/brut/spec_support/matchers/have_generated.rb +28 -0
  367. data/lib/brut/spec_support/matchers/have_html_attribute.rb +10 -0
  368. data/lib/brut/spec_support/matchers/have_i18n_string.rb +13 -0
  369. data/lib/brut/spec_support/matchers/have_link_to.rb +15 -0
  370. data/lib/brut/spec_support/matchers/have_redirected_to.rb +23 -0
  371. data/lib/brut/spec_support/matchers/have_returned_http_status.rb +20 -0
  372. data/lib/brut/spec_support/matchers/have_returned_rack_response.rb +22 -0
  373. data/lib/brut/spec_support/rspec_setup.rb +42 -2
  374. data/lib/brut/version.rb +1 -1
  375. data/lib/sequel/extensions/brut_instrumentation.rb +4 -0
  376. metadata +51 -24
  377. data/docs/assets/ai.md.tZrjP9im.lean.js +0 -1
  378. data/docs/assets/chunks/@localSearchIndexroot.BsN5i0Fi.js +0 -1
  379. data/docs/assets/doc-conventions.md.DCfRXXi-.js +0 -1
  380. data/docs/assets/getting-started.md.Bz2s1Vjb.js +0 -2
  381. data/docs/assets/getting-started.md.Bz2s1Vjb.lean.js +0 -1
  382. data/lib/brut/spec_support/matchers/have_rendered.rb +0 -14
  383. /data/docs/assets/{components.md.eCttGlN-.lean.js → components.md.CRUMdRoN.lean.js} +0 -0
  384. /data/docs/assets/{configuration.md.BRriU0cL.lean.js → configuration.md.BGHl8oRC.lean.js} +0 -0
  385. /data/docs/assets/{dev-environment.md.BNc8AYiK.lean.js → dev-environment.md.GZv6xvi9.lean.js} +0 -0
  386. /data/docs/assets/{overview.md.CDalkuxV.lean.js → overview.md.C5wlBcR5.lean.js} +0 -0
data/docs/404.html CHANGED
@@ -9,13 +9,13 @@
9
9
  <link rel="preload stylesheet" href="/assets/style.D73IYGCX.css" as="style">
10
10
  <link rel="preload stylesheet" href="/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/assets/app.D_yaTITQ.js"></script>
12
+ <script type="module" src="/assets/app.BX81XO4N.js"></script>
13
13
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
14
14
  <script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
15
15
  </head>
16
16
  <body>
17
17
  <div id="app"></div>
18
- <script>window.__VP_HASH_MAP__=JSON.parse("{\"ai.md\":\"tZrjP9im\",\"assets.md\":\"D3wunzLx\",\"brut-js.md\":\"o2DAO2s2\",\"business-logic.md\":\"BY4hGy0m\",\"cli.md\":\"RmeA2b0i\",\"components.md\":\"eCttGlN-\",\"configuration.md\":\"BRriU0cL\",\"css.md\":\"DJgj2clw\",\"custom-element-tests.md\":\"BrYJQEl3\",\"database-access.md\":\"C7l-Vuvb\",\"database-schema.md\":\"BUjR0VS1\",\"deployment.md\":\"Dbka4OTr\",\"dev-environment.md\":\"BNc8AYiK\",\"doc-conventions.md\":\"DCfRXXi-\",\"end-to-end-tests.md\":\"yfQHC0b5\",\"flash-and-session.md\":\"BXY8RvT0\",\"forms.md\":\"CBTYQ_Cz\",\"getting-started.md\":\"Bz2s1Vjb\",\"handlers.md\":\"089DVD3v\",\"hooks.md\":\"C4-moMny\",\"i18n.md\":\"Do9i1qWl\",\"index.md\":\"B28EwVpq\",\"instrumentation.md\":\"CL6ax7nT\",\"javascript.md\":\"GWbhRS51\",\"jobs.md\":\"S-2amAYp\",\"keyword-injection.md\":\"Dt2tKREs\",\"markdown-examples.md\":\"CCFEQO44\",\"middleware.md\":\"Czz_UlJN\",\"not-released.md\":\"BBy28McC\",\"overview.md\":\"CDalkuxV\",\"pages.md\":\"BE3kfOc5\",\"routes.md\":\"BMM7peut\",\"security.md\":\"C668yXCi\",\"seed-data.md\":\"BvFZlqIk\",\"space-time-continuum.md\":\"KPUIKysQ\",\"tutorial.md\":\"BnoGjrdK\",\"unit-tests.md\":\"DUGrnLj5\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Brut RB\",\"description\":\"Documentation for the Brut.RB web framework.\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"search\":{\"provider\":\"local\"},\"nav\":[{\"text\":\"Home\",\"link\":\"/\"},{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Overview\",\"link\":\"/overview\"},{\"text\":\"Brut API\",\"link\":\"/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutCSS\",\"link\":\"/brut-css/index.html\",\"target\":\"_self\"}],\"outline\":[2,3],\"sidebar\":[{\"text\":\"Overview\",\"collapsed\":false,\"items\":[{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Concepts\",\"link\":\"/overview\"},{\"text\":\"Documentation Conventions\",\"link\":\"/doc-conventions\"},{\"text\":\"Tutorial\",\"link\":\"/tutorial\"},{\"text\":\"Dev Environment\",\"link\":\"/dev-environment\"},{\"text\":\"AI Declaration\",\"link\":\"/ai\"}]},{\"text\":\"Front-End\",\"collapsed\":false,\"items\":[{\"text\":\"Routes\",\"link\":\"/routes\"},{\"text\":\"Pages\",\"link\":\"/pages\"},{\"text\":\"Forms\",\"link\":\"/forms\"},{\"text\":\"Handlers and Actions\",\"link\":\"/handlers\"},{\"text\":\"Components\",\"link\":\"/components\"},{\"text\":\"Flash and Session\",\"link\":\"/flash-and-session\"},{\"text\":\"Space/Time Continuum\",\"link\":\"/space-time-continuum\"},{\"text\":\"JavaScript\",\"link\":\"/javascript\"},{\"text\":\"CSS\",\"link\":\"/css\"},{\"text\":\"Assets\",\"link\":\"/assets\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js\"}]},{\"text\":\"Back-End\",\"collapsed\":false,\"items\":[{\"text\":\"Database Schema\",\"link\":\"/database-schema\"},{\"text\":\"Database Access\",\"link\":\"/database-access\"},{\"text\":\"Seed Data\",\"link\":\"/seed-data\"},{\"text\":\"Jobs\",\"link\":\"/jobs\"},{\"text\":\"Business Logic\",\"link\":\"/business-logic\"}]},{\"text\":\"Framework\",\"collapsed\":false,\"items\":[{\"text\":\"Configuration\",\"link\":\"/configuration\"},{\"text\":\"Keyword Injection\",\"link\":\"/keyword-injection\"},{\"text\":\"I18n\",\"link\":\"/i18n\"},{\"text\":\"CLI / Tasks\",\"link\":\"/cli\"},{\"text\":\"Deployment\",\"link\":\"/deployment\"}]},{\"text\":\"Testing\",\"collapsed\":false,\"items\":[{\"text\":\"Unit Tests\",\"link\":\"/unit-tests\"},{\"text\":\"End-to-End Tests\",\"link\":\"/end-to-end-tests\"},{\"text\":\"Testing Custom Elements\",\"link\":\"/custom-element-tests\"}]},{\"text\":\"Advanced Topics\",\"collapsed\":false,\"items\":[{\"text\":\"Route Hooks\",\"link\":\"/hooks\"},{\"text\":\"Middleware\",\"link\":\"/middleware\"},{\"text\":\"Instrumentation\",\"link\":\"/instrumentation\"},{\"text\":\"Security\",\"link\":\"/security\"}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/thirdtank/brut\"}]},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
18
+ <script>window.__VP_HASH_MAP__=JSON.parse("{\"ai.md\":\"_6HCDL6d\",\"assets.md\":\"D3wunzLx\",\"brut-js.md\":\"o2DAO2s2\",\"business-logic.md\":\"BY4hGy0m\",\"cli.md\":\"RmeA2b0i\",\"components.md\":\"CRUMdRoN\",\"configuration.md\":\"BGHl8oRC\",\"css.md\":\"DJgj2clw\",\"custom-element-tests.md\":\"BrYJQEl3\",\"database-access.md\":\"C7l-Vuvb\",\"database-schema.md\":\"BUjR0VS1\",\"deployment.md\":\"Dbka4OTr\",\"dev-environment.md\":\"GZv6xvi9\",\"doc-conventions.md\":\"-kN3Xo5C\",\"end-to-end-tests.md\":\"yfQHC0b5\",\"flash-and-session.md\":\"BXY8RvT0\",\"forms.md\":\"B-koVgyw\",\"getting-started.md\":\"Ciz82L0m\",\"handlers.md\":\"089DVD3v\",\"hooks.md\":\"C4-moMny\",\"i18n.md\":\"Do9i1qWl\",\"index.md\":\"B28EwVpq\",\"instrumentation.md\":\"a9Pjps4P\",\"javascript.md\":\"GWbhRS51\",\"jobs.md\":\"S-2amAYp\",\"keyword-injection.md\":\"Dt2tKREs\",\"layouts.md\":\"cPnh3NId\",\"lsp.md\":\"Bsu-f6VU\",\"markdown-examples.md\":\"CCFEQO44\",\"middleware.md\":\"Czz_UlJN\",\"not-released.md\":\"BBy28McC\",\"overview.md\":\"C5wlBcR5\",\"pages.md\":\"BE3kfOc5\",\"recipes_authentication.md\":\"CAsXf7hk\",\"routes.md\":\"BMM7peut\",\"security.md\":\"C668yXCi\",\"seed-data.md\":\"BvFZlqIk\",\"space-time-continuum.md\":\"KPUIKysQ\",\"tutorial.md\":\"BnoGjrdK\",\"unit-tests.md\":\"DUGrnLj5\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Brut RB\",\"description\":\"Documentation for the Brut.RB web framework.\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"search\":{\"provider\":\"local\"},\"nav\":[{\"text\":\"Home\",\"link\":\"/\"},{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Overview\",\"link\":\"/overview\"},{\"text\":\"Brut API\",\"link\":\"/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutCSS\",\"link\":\"/brut-css/index.html\",\"target\":\"_self\"}],\"outline\":[2,3],\"sidebar\":[{\"text\":\"Overview\",\"collapsed\":false,\"items\":[{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Concepts\",\"link\":\"/overview\"},{\"text\":\"Documentation Conventions\",\"link\":\"/doc-conventions\"},{\"text\":\"Tutorial\",\"link\":\"/tutorial\"},{\"text\":\"Dev Environment\",\"link\":\"/dev-environment\"},{\"text\":\"AI Declaration\",\"link\":\"/ai\"}]},{\"text\":\"Front-End\",\"collapsed\":false,\"items\":[{\"text\":\"Routes\",\"link\":\"/routes\"},{\"text\":\"Pages\",\"link\":\"/pages\"},{\"text\":\"Layouts\",\"link\":\"/layouts\"},{\"text\":\"Forms\",\"link\":\"/forms\"},{\"text\":\"Handlers and Actions\",\"link\":\"/handlers\"},{\"text\":\"Components\",\"link\":\"/components\"},{\"text\":\"Flash and Session\",\"link\":\"/flash-and-session\"},{\"text\":\"Space/Time Continuum\",\"link\":\"/space-time-continuum\"},{\"text\":\"JavaScript\",\"link\":\"/javascript\"},{\"text\":\"CSS\",\"link\":\"/css\"},{\"text\":\"Assets\",\"link\":\"/assets\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js\"}]},{\"text\":\"Back-End\",\"collapsed\":false,\"items\":[{\"text\":\"Database Schema\",\"link\":\"/database-schema\"},{\"text\":\"Database Access\",\"link\":\"/database-access\"},{\"text\":\"Seed Data\",\"link\":\"/seed-data\"},{\"text\":\"Jobs\",\"link\":\"/jobs\"},{\"text\":\"Business Logic\",\"link\":\"/business-logic\"}]},{\"text\":\"Framework\",\"collapsed\":false,\"items\":[{\"text\":\"Configuration\",\"link\":\"/configuration\"},{\"text\":\"Keyword Injection\",\"link\":\"/keyword-injection\"},{\"text\":\"I18n\",\"link\":\"/i18n\"},{\"text\":\"CLI / Tasks\",\"link\":\"/cli\"},{\"text\":\"Deployment\",\"link\":\"/deployment\"}]},{\"text\":\"Testing\",\"collapsed\":false,\"items\":[{\"text\":\"Unit Tests\",\"link\":\"/unit-tests\"},{\"text\":\"End-to-End Tests\",\"link\":\"/end-to-end-tests\"},{\"text\":\"Testing Custom Elements\",\"link\":\"/custom-element-tests\"}]},{\"text\":\"Advanced Topics\",\"collapsed\":true,\"items\":[{\"text\":\"Route Hooks\",\"link\":\"/hooks\"},{\"text\":\"Middleware\",\"link\":\"/middleware\"},{\"text\":\"Instrumentation\",\"link\":\"/instrumentation\"},{\"text\":\"Security\",\"link\":\"/security\"},{\"text\":\"LSP Support\",\"link\":\"/lsp\"}]},{\"text\":\"Recipes\",\"collapsed\":true,\"items\":[{\"text\":\"Authentication\",\"link\":\"/recipes/authentication\"},{\"text\":\"Form Validations\",\"link\":\"/recipes/form-validations\"},{\"text\":\"Database Migrations\",\"link\":\"/recipes/database-migrations\"},{\"text\":\"Ajax Form Submission\",\"link\":\"/recipes/ajax-form\"},{\"text\":\"Custom Telemetry\",\"link\":\"/recipes/telemetry\"},{\"text\":\"CLI App/Task\",\"link\":\"/recipes/cli-app\"}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/thirdtank/brut\"}]},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
19
19
 
20
20
  </body>
21
21
  </html>
data/docs/ai.html CHANGED
@@ -9,16 +9,16 @@
9
9
  <link rel="preload stylesheet" href="/assets/style.D73IYGCX.css" as="style">
10
10
  <link rel="preload stylesheet" href="/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/assets/app.D_yaTITQ.js"></script>
13
- <link rel="modulepreload" href="/assets/chunks/theme.CfGFVRvE.js">
12
+ <script type="module" src="/assets/app.BX81XO4N.js"></script>
13
+ <link rel="modulepreload" href="/assets/chunks/theme.DwUXXAL3.js">
14
14
  <link rel="modulepreload" href="/assets/chunks/framework.1L-BeKqY.js">
15
- <link rel="modulepreload" href="/assets/ai.md.tZrjP9im.lean.js">
15
+ <link rel="modulepreload" href="/assets/ai.md._6HCDL6d.lean.js">
16
16
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
17
17
  <script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
18
18
  </head>
19
19
  <body>
20
- <div id="app"><div class="Layout" data-v-d8b57b2d><!--[--><!--]--><!--[--><span tabindex="-1" data-v-fcbfc0e0></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-fcbfc0e0>Skip to content</a><!--]--><!----><header class="VPNav" data-v-d8b57b2d data-v-7ad780c2><div class="VPNavBar" data-v-7ad780c2 data-v-9fd4d1dd><div class="wrapper" data-v-9fd4d1dd><div class="container" data-v-9fd4d1dd><div class="title" data-v-9fd4d1dd><div class="VPNavBarTitle has-sidebar" data-v-9fd4d1dd data-v-9f43907a><a class="title" href="/" data-v-9f43907a><!--[--><!--]--><!----><span data-v-9f43907a>Brut RB</span><!--[--><!--]--></a></div></div><div class="content" data-v-9fd4d1dd><div class="content-body" data-v-9fd4d1dd><!--[--><!--]--><div class="VPNavBarSearch search" data-v-9fd4d1dd><!--[--><!----><div id="local-search"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><span class="vp-icon DocSearch-Search-Icon"></span><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-9fd4d1dd data-v-afb2845e><span id="main-nav-aria-label" class="visually-hidden" data-v-afb2845e> Main Navigation </span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>Home</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/getting-started.html" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>Getting Started</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/overview.html" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>Overview</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/api/index.html" target="_self" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>Brut API</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/brut-js/api/index.html" target="_self" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>BrutJS</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/brut-css/index.html" target="_self" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>BrutCSS</span><!--]--></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-9fd4d1dd data-v-3f90c1a5><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-3f90c1a5 data-v-be9742d9 data-v-b4ccac88><span class="check" data-v-b4ccac88><span class="icon" data-v-b4ccac88><!--[--><span class="vpi-sun sun" data-v-be9742d9></span><span class="vpi-moon moon" data-v-be9742d9></span><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-9fd4d1dd data-v-ef6192dc data-v-e71e869c><!--[--><a class="VPSocialLink no-icon" href="https://github.com/thirdtank/brut" aria-label="github" target="_blank" rel="noopener" data-v-e71e869c data-v-60a9a2d3><span class="vpi-social-github"></span></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-9fd4d1dd data-v-f953d92f data-v-bfe7971f><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-bfe7971f><span class="vpi-more-horizontal icon" data-v-bfe7971f></span></button><div class="menu" data-v-bfe7971f><div class="VPMenu" data-v-bfe7971f data-v-20ed86d6><!----><!--[--><!--[--><!----><div class="group" data-v-f953d92f><div class="item appearance" data-v-f953d92f><p class="label" data-v-f953d92f>Appearance</p><div class="appearance-action" data-v-f953d92f><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-f953d92f data-v-be9742d9 data-v-b4ccac88><span class="check" data-v-b4ccac88><span class="icon" data-v-b4ccac88><!--[--><span class="vpi-sun sun" data-v-be9742d9></span><span class="vpi-moon moon" data-v-be9742d9></span><!--]--></span></span></button></div></div></div><div class="group" data-v-f953d92f><div class="item social-links" data-v-f953d92f><div class="VPSocialLinks social-links-list" data-v-f953d92f data-v-e71e869c><!--[--><a class="VPSocialLink no-icon" href="https://github.com/thirdtank/brut" aria-label="github" target="_blank" rel="noopener" data-v-e71e869c data-v-60a9a2d3><span class="vpi-social-github"></span></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-9fd4d1dd data-v-6bee1efd><span class="container" data-v-6bee1efd><span class="top" data-v-6bee1efd></span><span class="middle" data-v-6bee1efd></span><span class="bottom" data-v-6bee1efd></span></span></button></div></div></div></div><div class="divider" data-v-9fd4d1dd><div class="divider-line" data-v-9fd4d1dd></div></div></div><!----></header><div class="VPLocalNav has-sidebar empty" data-v-d8b57b2d data-v-2488c25a><div class="container" data-v-2488c25a><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-2488c25a><span class="vpi-align-left menu-icon" data-v-2488c25a></span><span class="menu-text" data-v-2488c25a>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-2488c25a data-v-6b867909><button data-v-6b867909>Return to top</button><!----></div></div></div><aside class="VPSidebar" data-v-d8b57b2d data-v-42c4c606><div class="curtain" data-v-42c4c606></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-42c4c606><span class="visually-hidden" id="sidebar-aria-label" data-v-42c4c606> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible has-active" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Overview</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/getting-started.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Getting Started</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/overview.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Concepts</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/doc-conventions.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Documentation Conventions</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/tutorial.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Tutorial</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/dev-environment.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Dev Environment</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/ai.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>AI Declaration</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Front-End</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/routes.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Routes</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/pages.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Pages</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/forms.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Forms</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/handlers.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Handlers and Actions</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/components.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Components</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/flash-and-session.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Flash and Session</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/space-time-continuum.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Space/Time Continuum</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/javascript.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>JavaScript</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/css.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>CSS</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/assets.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Assets</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/brut-js.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>BrutJS</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Back-End</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/database-schema.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Database Schema</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/database-access.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Database Access</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/seed-data.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Seed Data</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/jobs.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Jobs</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/business-logic.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Business Logic</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Framework</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/configuration.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Configuration</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/keyword-injection.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Keyword Injection</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/i18n.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>I18n</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/cli.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>CLI / Tasks</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/deployment.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Deployment</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Testing</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/unit-tests.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Unit Tests</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/end-to-end-tests.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>End-to-End Tests</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/custom-element-tests.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Testing Custom Elements</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Advanced Topics</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/hooks.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Route Hooks</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/middleware.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Middleware</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/instrumentation.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Instrumentation</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/security.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Security</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-d8b57b2d data-v-9a6c75ad><div class="VPDoc has-sidebar has-aside" data-v-9a6c75ad data-v-e6f2a212><!--[--><!--]--><div class="container" data-v-e6f2a212><div class="aside" data-v-e6f2a212><div class="aside-curtain" data-v-e6f2a212></div><div class="aside-container" data-v-e6f2a212><div class="aside-content" data-v-e6f2a212><div class="VPDocAside" data-v-e6f2a212 data-v-cb998dce><!--[--><!--]--><!--[--><!--]--><nav aria-labelledby="doc-outline-aria-label" class="VPDocAsideOutline" data-v-cb998dce data-v-f610f197><div class="content" data-v-f610f197><div class="outline-marker" data-v-f610f197></div><div aria-level="2" class="outline-title" id="doc-outline-aria-label" role="heading" data-v-f610f197>On this page</div><ul class="VPDocOutlineItem root" data-v-f610f197 data-v-53c99d69><!--[--><!--]--></ul></div></nav><!--[--><!--]--><div class="spacer" data-v-cb998dce></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-e6f2a212><div class="content-container" data-v-e6f2a212><!--[--><!--]--><main class="main" data-v-e6f2a212><div style="position:relative;" class="vp-doc _ai" data-v-e6f2a212><div><h1 id="ai-declaration-and-notes" tabindex="-1">AI Declaration and Notes <a class="header-anchor" href="#ai-declaration-and-notes" aria-label="Permalink to &quot;AI Declaration and Notes&quot;">​</a></h1><p>LLMs and AI tools are a current fact of life. We feel it&#39;s important to be realistic and up front about how they affect this project.</p><h2 id="levels-of-ai-use" tabindex="-1">Levels of AI Use <a class="header-anchor" href="#levels-of-ai-use" aria-label="Permalink to &quot;Levels of AI Use&quot;">​</a></h2><p>I created <a href="https://declare-ai.org/" target="_blank" rel="noreferrer">declare-ai.org</a> to allow precise documentation of how AI is used in a project. It defines four levels of AI use:</p><ol><li>No involvement at all.</li><li>Non-create assistance, such as the completions GitHub Copilot may make while you are typing.</li><li>Creative assistance, where an AI generated a large amount of code that you then modified. An example would be using a tool like Cursor to write code for your review.</li><li>Completely Produced by an AI, for example if you used Stable Diffusion to create your icon.</li></ol><h2 id="code" tabindex="-1">Code <a class="header-anchor" href="#code" aria-label="Permalink to &quot;Code&quot;">​</a></h2><p>The entirety of Brut&#39;s codebase could be grouped into three parts:</p><ul><li>The library code developers use. This is, roughly, the code in <code>lib</code>, <code>brut-js/src</code>, and <code>brut-css/src</code>.</li><li>Tests of the library code.</li><li>Tools used to manage the library code, such as what&#39;s in <code>bin/</code>, <code>brut-js/bin</code>, <code>brut-css/bin</code>, etc.</li></ul><h3 id="library-code-should-be-written-by-a-person" tabindex="-1">Library Code Should Be Written By a Person <a class="header-anchor" href="#library-code-should-be-written-by-a-person" aria-label="Permalink to &quot;Library Code Should Be Written By a Person&quot;">​</a></h3><p>We want the library code written by a person, i.e. it should have level 1 AI assistance: none. As of this writing—June 17, 2025—all library code was written by a person.</p><p>If some code is level 2—non-creative assistance—that is probably fine.</p><h3 id="tests-should-not-be-totally-written-by-ai" tabindex="-1">Tests Should Not Be Totally Written by AI <a class="header-anchor" href="#tests-should-not-be-totally-written-by-ai" aria-label="Permalink to &quot;Tests Should Not Be Totally Written by AI&quot;">​</a></h3><p>As of this writing—June 17, 2025—the library has no automated tests. The <code>adrs.cloud</code> app serves as the test suite.</p><p>That said, as tests are developed, they must never be written entirely by an AI without human review (level 4). Our preference is that all tests comply with level 1 or level 2, however we are open to creative assistance for tests as might be provided by a tool like Cursor.</p><p>In any case, the author of a test should understand it and the maintainers must be able to understand and modify all tests without the use of AI tools.</p><h3 id="management-tools-should-not-be-totally-written-by-ai" tabindex="-1">Management Tools Should Not Be Totally Written by AI <a class="header-anchor" href="#management-tools-should-not-be-totally-written-by-ai" aria-label="Permalink to &quot;Management Tools Should Not Be Totally Written by AI&quot;">​</a></h3><p>Like tests, management tools must be comprehensible by a person and the creator of the code must understand it. That said, some of the tools were created with level 3 AI assistance, and we expect these tools may continue to be created this way.</p><p>Nevertheless, this code must be reviewed and understood by a person.</p><h2 id="documentation" tabindex="-1">Documentation <a class="header-anchor" href="#documentation" aria-label="Permalink to &quot;Documentation&quot;">​</a></h2><p>We strive to have all documentation written by a real person. None of this documentation, or the API documentation, is produced by a machine, although spelling and grammar corrections will certainly have been suggested by automated tools.</p><p>We expect an LLM to be able to digest this documentation and source code and provide alternate analysis of how Brut works and how to use it. We hope such analysis is correct and useful, however that cannot be guaranteed, so this documentation is the second best source of truth, the source code being the best.</p><h2 id="logo" tabindex="-1">Logo <a class="header-anchor" href="#logo" aria-label="Permalink to &quot;Logo&quot;">​</a></h2><p>The logo is level 4 - ChatGPT created it. I&#39;d love to have a real person make a better one. I just needed something to get this launched. Please reach out if you want to make a better one + other assets. I&#39;m willing to pay a real person.</p><h2 id="ai-that-teachs-you-about-brut-does-not-currently-exist" tabindex="-1">AI That Teachs You About Brut Does Not Currently Exist <a class="header-anchor" href="#ai-that-teachs-you-about-brut-does-not-currently-exist" aria-label="Permalink to &quot;AI That Teachs You About Brut Does Not Currently Exist&quot;">​</a></h2><p>Due to how LLMs work, there is naturally nothing in any model about Brut. Anything an existing model tells you about Brut is <strong>100% untrustworthy</strong>. We hope to allow LLMs to consume Brut&#39;s code, documentation, and examples, so it can be an additional source of help, but currently that is not the case.</p><p><strong>Do not ask an LLM about Brut</strong> until this part of the documentation changes.</p></div></div></main><footer class="VPDocFooter" data-v-e6f2a212 data-v-1bcd8184><!--[--><!--]--><!----><nav class="prev-next" aria-labelledby="doc-footer-aria-label" data-v-1bcd8184><span class="visually-hidden" id="doc-footer-aria-label" data-v-1bcd8184>Pager</span><div class="pager" data-v-1bcd8184><a class="VPLink link pager-link prev" href="/dev-environment.html" data-v-1bcd8184><!--[--><span class="desc" data-v-1bcd8184>Previous page</span><span class="title" data-v-1bcd8184>Dev Environment</span><!--]--></a></div><div class="pager" data-v-1bcd8184><a class="VPLink link pager-link next" href="/routes.html" data-v-1bcd8184><!--[--><span class="desc" data-v-1bcd8184>Next page</span><span class="title" data-v-1bcd8184>Routes</span><!--]--></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><!----><!--[--><!--]--></div></div>
21
- <script>window.__VP_HASH_MAP__=JSON.parse("{\"ai.md\":\"tZrjP9im\",\"assets.md\":\"D3wunzLx\",\"brut-js.md\":\"o2DAO2s2\",\"business-logic.md\":\"BY4hGy0m\",\"cli.md\":\"RmeA2b0i\",\"components.md\":\"eCttGlN-\",\"configuration.md\":\"BRriU0cL\",\"css.md\":\"DJgj2clw\",\"custom-element-tests.md\":\"BrYJQEl3\",\"database-access.md\":\"C7l-Vuvb\",\"database-schema.md\":\"BUjR0VS1\",\"deployment.md\":\"Dbka4OTr\",\"dev-environment.md\":\"BNc8AYiK\",\"doc-conventions.md\":\"DCfRXXi-\",\"end-to-end-tests.md\":\"yfQHC0b5\",\"flash-and-session.md\":\"BXY8RvT0\",\"forms.md\":\"CBTYQ_Cz\",\"getting-started.md\":\"Bz2s1Vjb\",\"handlers.md\":\"089DVD3v\",\"hooks.md\":\"C4-moMny\",\"i18n.md\":\"Do9i1qWl\",\"index.md\":\"B28EwVpq\",\"instrumentation.md\":\"CL6ax7nT\",\"javascript.md\":\"GWbhRS51\",\"jobs.md\":\"S-2amAYp\",\"keyword-injection.md\":\"Dt2tKREs\",\"markdown-examples.md\":\"CCFEQO44\",\"middleware.md\":\"Czz_UlJN\",\"not-released.md\":\"BBy28McC\",\"overview.md\":\"CDalkuxV\",\"pages.md\":\"BE3kfOc5\",\"routes.md\":\"BMM7peut\",\"security.md\":\"C668yXCi\",\"seed-data.md\":\"BvFZlqIk\",\"space-time-continuum.md\":\"KPUIKysQ\",\"tutorial.md\":\"BnoGjrdK\",\"unit-tests.md\":\"DUGrnLj5\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Brut RB\",\"description\":\"Documentation for the Brut.RB web framework.\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"search\":{\"provider\":\"local\"},\"nav\":[{\"text\":\"Home\",\"link\":\"/\"},{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Overview\",\"link\":\"/overview\"},{\"text\":\"Brut API\",\"link\":\"/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutCSS\",\"link\":\"/brut-css/index.html\",\"target\":\"_self\"}],\"outline\":[2,3],\"sidebar\":[{\"text\":\"Overview\",\"collapsed\":false,\"items\":[{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Concepts\",\"link\":\"/overview\"},{\"text\":\"Documentation Conventions\",\"link\":\"/doc-conventions\"},{\"text\":\"Tutorial\",\"link\":\"/tutorial\"},{\"text\":\"Dev Environment\",\"link\":\"/dev-environment\"},{\"text\":\"AI Declaration\",\"link\":\"/ai\"}]},{\"text\":\"Front-End\",\"collapsed\":false,\"items\":[{\"text\":\"Routes\",\"link\":\"/routes\"},{\"text\":\"Pages\",\"link\":\"/pages\"},{\"text\":\"Forms\",\"link\":\"/forms\"},{\"text\":\"Handlers and Actions\",\"link\":\"/handlers\"},{\"text\":\"Components\",\"link\":\"/components\"},{\"text\":\"Flash and Session\",\"link\":\"/flash-and-session\"},{\"text\":\"Space/Time Continuum\",\"link\":\"/space-time-continuum\"},{\"text\":\"JavaScript\",\"link\":\"/javascript\"},{\"text\":\"CSS\",\"link\":\"/css\"},{\"text\":\"Assets\",\"link\":\"/assets\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js\"}]},{\"text\":\"Back-End\",\"collapsed\":false,\"items\":[{\"text\":\"Database Schema\",\"link\":\"/database-schema\"},{\"text\":\"Database Access\",\"link\":\"/database-access\"},{\"text\":\"Seed Data\",\"link\":\"/seed-data\"},{\"text\":\"Jobs\",\"link\":\"/jobs\"},{\"text\":\"Business Logic\",\"link\":\"/business-logic\"}]},{\"text\":\"Framework\",\"collapsed\":false,\"items\":[{\"text\":\"Configuration\",\"link\":\"/configuration\"},{\"text\":\"Keyword Injection\",\"link\":\"/keyword-injection\"},{\"text\":\"I18n\",\"link\":\"/i18n\"},{\"text\":\"CLI / Tasks\",\"link\":\"/cli\"},{\"text\":\"Deployment\",\"link\":\"/deployment\"}]},{\"text\":\"Testing\",\"collapsed\":false,\"items\":[{\"text\":\"Unit Tests\",\"link\":\"/unit-tests\"},{\"text\":\"End-to-End Tests\",\"link\":\"/end-to-end-tests\"},{\"text\":\"Testing Custom Elements\",\"link\":\"/custom-element-tests\"}]},{\"text\":\"Advanced Topics\",\"collapsed\":false,\"items\":[{\"text\":\"Route Hooks\",\"link\":\"/hooks\"},{\"text\":\"Middleware\",\"link\":\"/middleware\"},{\"text\":\"Instrumentation\",\"link\":\"/instrumentation\"},{\"text\":\"Security\",\"link\":\"/security\"}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/thirdtank/brut\"}]},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
20
+ <div id="app"><div class="Layout" data-v-d8b57b2d><!--[--><!--]--><!--[--><span tabindex="-1" data-v-fcbfc0e0></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-fcbfc0e0>Skip to content</a><!--]--><!----><header class="VPNav" data-v-d8b57b2d data-v-7ad780c2><div class="VPNavBar" data-v-7ad780c2 data-v-9fd4d1dd><div class="wrapper" data-v-9fd4d1dd><div class="container" data-v-9fd4d1dd><div class="title" data-v-9fd4d1dd><div class="VPNavBarTitle has-sidebar" data-v-9fd4d1dd data-v-9f43907a><a class="title" href="/" data-v-9f43907a><!--[--><!--]--><!----><span data-v-9f43907a>Brut RB</span><!--[--><!--]--></a></div></div><div class="content" data-v-9fd4d1dd><div class="content-body" data-v-9fd4d1dd><!--[--><!--]--><div class="VPNavBarSearch search" data-v-9fd4d1dd><!--[--><!----><div id="local-search"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><span class="vp-icon DocSearch-Search-Icon"></span><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-9fd4d1dd data-v-afb2845e><span id="main-nav-aria-label" class="visually-hidden" data-v-afb2845e> Main Navigation </span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>Home</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/getting-started.html" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>Getting Started</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/overview.html" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>Overview</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/api/index.html" target="_self" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>Brut API</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/brut-js/api/index.html" target="_self" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>BrutJS</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/brut-css/index.html" target="_self" tabindex="0" data-v-afb2845e data-v-815115f5><!--[--><span data-v-815115f5>BrutCSS</span><!--]--></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-9fd4d1dd data-v-3f90c1a5><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-3f90c1a5 data-v-be9742d9 data-v-b4ccac88><span class="check" data-v-b4ccac88><span class="icon" data-v-b4ccac88><!--[--><span class="vpi-sun sun" data-v-be9742d9></span><span class="vpi-moon moon" data-v-be9742d9></span><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-9fd4d1dd data-v-ef6192dc data-v-e71e869c><!--[--><a class="VPSocialLink no-icon" href="https://github.com/thirdtank/brut" aria-label="github" target="_blank" rel="noopener" data-v-e71e869c data-v-60a9a2d3><span class="vpi-social-github"></span></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-9fd4d1dd data-v-f953d92f data-v-bfe7971f><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-bfe7971f><span class="vpi-more-horizontal icon" data-v-bfe7971f></span></button><div class="menu" data-v-bfe7971f><div class="VPMenu" data-v-bfe7971f data-v-20ed86d6><!----><!--[--><!--[--><!----><div class="group" data-v-f953d92f><div class="item appearance" data-v-f953d92f><p class="label" data-v-f953d92f>Appearance</p><div class="appearance-action" data-v-f953d92f><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-f953d92f data-v-be9742d9 data-v-b4ccac88><span class="check" data-v-b4ccac88><span class="icon" data-v-b4ccac88><!--[--><span class="vpi-sun sun" data-v-be9742d9></span><span class="vpi-moon moon" data-v-be9742d9></span><!--]--></span></span></button></div></div></div><div class="group" data-v-f953d92f><div class="item social-links" data-v-f953d92f><div class="VPSocialLinks social-links-list" data-v-f953d92f data-v-e71e869c><!--[--><a class="VPSocialLink no-icon" href="https://github.com/thirdtank/brut" aria-label="github" target="_blank" rel="noopener" data-v-e71e869c data-v-60a9a2d3><span class="vpi-social-github"></span></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-9fd4d1dd data-v-6bee1efd><span class="container" data-v-6bee1efd><span class="top" data-v-6bee1efd></span><span class="middle" data-v-6bee1efd></span><span class="bottom" data-v-6bee1efd></span></span></button></div></div></div></div><div class="divider" data-v-9fd4d1dd><div class="divider-line" data-v-9fd4d1dd></div></div></div><!----></header><div class="VPLocalNav has-sidebar empty" data-v-d8b57b2d data-v-2488c25a><div class="container" data-v-2488c25a><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-2488c25a><span class="vpi-align-left menu-icon" data-v-2488c25a></span><span class="menu-text" data-v-2488c25a>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-2488c25a data-v-6b867909><button data-v-6b867909>Return to top</button><!----></div></div></div><aside class="VPSidebar" data-v-d8b57b2d data-v-42c4c606><div class="curtain" data-v-42c4c606></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-42c4c606><span class="visually-hidden" id="sidebar-aria-label" data-v-42c4c606> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible has-active" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Overview</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/getting-started.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Getting Started</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/overview.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Concepts</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/doc-conventions.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Documentation Conventions</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/tutorial.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Tutorial</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/dev-environment.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Dev Environment</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/ai.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>AI Declaration</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Front-End</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/routes.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Routes</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/pages.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Pages</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/layouts.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Layouts</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/forms.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Forms</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/handlers.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Handlers and Actions</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/components.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Components</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/flash-and-session.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Flash and Session</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/space-time-continuum.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Space/Time Continuum</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/javascript.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>JavaScript</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/css.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>CSS</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/assets.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Assets</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/brut-js.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>BrutJS</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Back-End</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/database-schema.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Database Schema</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/database-access.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Database Access</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/seed-data.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Seed Data</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/jobs.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Jobs</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/business-logic.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Business Logic</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Framework</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/configuration.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Configuration</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/keyword-injection.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Keyword Injection</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/i18n.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>I18n</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/cli.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>CLI / Tasks</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/deployment.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Deployment</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Testing</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/unit-tests.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Unit Tests</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/end-to-end-tests.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>End-to-End Tests</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/custom-element-tests.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Testing Custom Elements</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible collapsed" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Advanced Topics</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/hooks.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Route Hooks</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/middleware.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Middleware</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/instrumentation.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Instrumentation</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/security.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Security</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/lsp.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>LSP Support</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-51288d80><section class="VPSidebarItem level-0 collapsible collapsed" data-v-51288d80 data-v-0009425e><div class="item" role="button" tabindex="0" data-v-0009425e><div class="indicator" data-v-0009425e></div><h2 class="text" data-v-0009425e>Recipes</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0009425e><span class="vpi-chevron-right caret-icon" data-v-0009425e></span></div></div><div class="items" data-v-0009425e><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/recipes/authentication.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Authentication</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/recipes/form-validations.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Form Validations</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/recipes/database-migrations.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Database Migrations</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/recipes/ajax-form.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Ajax Form Submission</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/recipes/telemetry.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>Custom Telemetry</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0009425e data-v-0009425e><div class="item" data-v-0009425e><div class="indicator" data-v-0009425e></div><a class="VPLink link link" href="/recipes/cli-app.html" data-v-0009425e><!--[--><p class="text" data-v-0009425e>CLI App/Task</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-d8b57b2d data-v-9a6c75ad><div class="VPDoc has-sidebar has-aside" data-v-9a6c75ad data-v-e6f2a212><!--[--><!--]--><div class="container" data-v-e6f2a212><div class="aside" data-v-e6f2a212><div class="aside-curtain" data-v-e6f2a212></div><div class="aside-container" data-v-e6f2a212><div class="aside-content" data-v-e6f2a212><div class="VPDocAside" data-v-e6f2a212 data-v-cb998dce><!--[--><!--]--><!--[--><!--]--><nav aria-labelledby="doc-outline-aria-label" class="VPDocAsideOutline" data-v-cb998dce data-v-f610f197><div class="content" data-v-f610f197><div class="outline-marker" data-v-f610f197></div><div aria-level="2" class="outline-title" id="doc-outline-aria-label" role="heading" data-v-f610f197>On this page</div><ul class="VPDocOutlineItem root" data-v-f610f197 data-v-53c99d69><!--[--><!--]--></ul></div></nav><!--[--><!--]--><div class="spacer" data-v-cb998dce></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-e6f2a212><div class="content-container" data-v-e6f2a212><!--[--><!--]--><main class="main" data-v-e6f2a212><div style="position:relative;" class="vp-doc _ai" data-v-e6f2a212><div><h1 id="ai-declaration-and-notes" tabindex="-1">AI Declaration and Notes <a class="header-anchor" href="#ai-declaration-and-notes" aria-label="Permalink to &quot;AI Declaration and Notes&quot;">​</a></h1><p>LLMs and AI tools are a current fact of life. We feel it&#39;s important to be realistic and up front about how they affect this project.</p><h2 id="levels-of-ai-use" tabindex="-1">Levels of AI Use <a class="header-anchor" href="#levels-of-ai-use" aria-label="Permalink to &quot;Levels of AI Use&quot;">​</a></h2><p>I created <a href="https://declare-ai.org/" target="_blank" rel="noreferrer">declare-ai.org</a> to allow precise documentation of how AI is used in a project. It defines four levels of AI use:</p><ol><li>No involvement at all.</li><li>Non-create assistance, such as the completions GitHub Copilot may make while you are typing.</li><li>Creative assistance, where an AI generated a large amount of code that you then modified. An example would be using a tool like Cursor to write code for your review.</li><li>Completely Produced by an AI, for example if you used Stable Diffusion to create your icon.</li></ol><h2 id="code" tabindex="-1">Code <a class="header-anchor" href="#code" aria-label="Permalink to &quot;Code&quot;">​</a></h2><p>The entirety of Brut&#39;s codebase could be grouped into three parts:</p><ul><li>The library code developers use. This is, roughly, the code in <code>lib</code>, <code>brut-js/src</code>, and <code>brut-css/src</code>.</li><li>Tests of the library code.</li><li>Tools used to manage the library code, such as what&#39;s in <code>bin/</code>, <code>brut-js/bin</code>, <code>brut-css/bin</code>, etc.</li></ul><h3 id="library-code-should-be-written-by-a-person" tabindex="-1">Library Code Should Be Written By a Person <a class="header-anchor" href="#library-code-should-be-written-by-a-person" aria-label="Permalink to &quot;Library Code Should Be Written By a Person&quot;">​</a></h3><p>We want the library code written by a person, i.e. it should have level 1 AI assistance: none. As of this writing—June 17, 2025—all library code was written by a person.</p><p>If some code is level 2—non-creative assistance—that is probably fine.</p><h3 id="tests-should-not-be-totally-written-by-ai" tabindex="-1">Tests Should Not Be Totally Written by AI <a class="header-anchor" href="#tests-should-not-be-totally-written-by-ai" aria-label="Permalink to &quot;Tests Should Not Be Totally Written by AI&quot;">​</a></h3><p>As of this writing—June 17, 2025—the library has no automated tests. The <code>adrs.cloud</code> app serves as the test suite.</p><p>That said, as tests are developed, they must never be written entirely by an AI without human review (level 4). Our preference is that all tests comply with level 1 or level 2, however we are open to creative assistance for tests as might be provided by a tool like Cursor.</p><p>In any case, the author of a test should understand it and the maintainers must be able to understand and modify all tests without the use of AI tools.</p><h3 id="management-tools-should-not-be-totally-written-by-ai" tabindex="-1">Management Tools Should Not Be Totally Written by AI <a class="header-anchor" href="#management-tools-should-not-be-totally-written-by-ai" aria-label="Permalink to &quot;Management Tools Should Not Be Totally Written by AI&quot;">​</a></h3><p>Like tests, management tools must be comprehensible by a person and the creator of the code must understand it. That said, some of the tools were created with level 3 AI assistance, and we expect these tools may continue to be created this way.</p><p>Nevertheless, this code must be reviewed and understood by a person.</p><h2 id="documentation" tabindex="-1">Documentation <a class="header-anchor" href="#documentation" aria-label="Permalink to &quot;Documentation&quot;">​</a></h2><p>We strive to have all documentation written by a real person. None of this documentation, or the API documentation, is produced by a machine, although spelling and grammar corrections will certainly have been suggested by automated tools.</p><p>We expect an LLM to be able to digest this documentation and source code and provide alternate analysis of how Brut works and how to use it. We hope such analysis is correct and useful, however that cannot be guaranteed, so this documentation is the second best source of truth, the source code being the best.</p><h2 id="logo" tabindex="-1">Logo <a class="header-anchor" href="#logo" aria-label="Permalink to &quot;Logo&quot;">​</a></h2><p>The logo is level 4 - ChatGPT created it. I&#39;d love to have a real person make a better one. I just needed something to get this launched. Please reach out if you want to make a better one + other assets. I&#39;m willing to pay a real person.</p><h2 id="ai-completions-should-be-viewed-with-skepticism" tabindex="-1">AI Completions Should Be Viewed with Skepticism <a class="header-anchor" href="#ai-completions-should-be-viewed-with-skepticism" aria-label="Permalink to &quot;AI Completions Should Be Viewed with Skepticism&quot;">​</a></h2><p>Due to how LLMs work, there is naturally nothing in any model about Brut. Anything an existing model tells you about Brut is <strong>100% untrustworthy</strong>. We hope to allow LLMs to consume Brut&#39;s code, documentation, and examples, so it can be an additional source of help, but currently that is not the case.</p><p><strong>Do not ask an LLM about Brut</strong> until this part of the documentation changes.</p><p>For completion-based AI suggestions, <strong>view them with skepticism</strong>. In my experience, completions from e.g. GitHub CoPilot work OK when replicating a pattern in the file you are editing, but suggestions in a freshly-opened file tend to be entirely imaginary or Rails-based. Beware.</p></div></div></main><footer class="VPDocFooter" data-v-e6f2a212 data-v-1bcd8184><!--[--><!--]--><!----><nav class="prev-next" aria-labelledby="doc-footer-aria-label" data-v-1bcd8184><span class="visually-hidden" id="doc-footer-aria-label" data-v-1bcd8184>Pager</span><div class="pager" data-v-1bcd8184><a class="VPLink link pager-link prev" href="/dev-environment.html" data-v-1bcd8184><!--[--><span class="desc" data-v-1bcd8184>Previous page</span><span class="title" data-v-1bcd8184>Dev Environment</span><!--]--></a></div><div class="pager" data-v-1bcd8184><a class="VPLink link pager-link next" href="/routes.html" data-v-1bcd8184><!--[--><span class="desc" data-v-1bcd8184>Next page</span><span class="title" data-v-1bcd8184>Routes</span><!--]--></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><!----><!--[--><!--]--></div></div>
21
+ <script>window.__VP_HASH_MAP__=JSON.parse("{\"ai.md\":\"_6HCDL6d\",\"assets.md\":\"D3wunzLx\",\"brut-js.md\":\"o2DAO2s2\",\"business-logic.md\":\"BY4hGy0m\",\"cli.md\":\"RmeA2b0i\",\"components.md\":\"CRUMdRoN\",\"configuration.md\":\"BGHl8oRC\",\"css.md\":\"DJgj2clw\",\"custom-element-tests.md\":\"BrYJQEl3\",\"database-access.md\":\"C7l-Vuvb\",\"database-schema.md\":\"BUjR0VS1\",\"deployment.md\":\"Dbka4OTr\",\"dev-environment.md\":\"GZv6xvi9\",\"doc-conventions.md\":\"-kN3Xo5C\",\"end-to-end-tests.md\":\"yfQHC0b5\",\"flash-and-session.md\":\"BXY8RvT0\",\"forms.md\":\"B-koVgyw\",\"getting-started.md\":\"Ciz82L0m\",\"handlers.md\":\"089DVD3v\",\"hooks.md\":\"C4-moMny\",\"i18n.md\":\"Do9i1qWl\",\"index.md\":\"B28EwVpq\",\"instrumentation.md\":\"a9Pjps4P\",\"javascript.md\":\"GWbhRS51\",\"jobs.md\":\"S-2amAYp\",\"keyword-injection.md\":\"Dt2tKREs\",\"layouts.md\":\"cPnh3NId\",\"lsp.md\":\"Bsu-f6VU\",\"markdown-examples.md\":\"CCFEQO44\",\"middleware.md\":\"Czz_UlJN\",\"not-released.md\":\"BBy28McC\",\"overview.md\":\"C5wlBcR5\",\"pages.md\":\"BE3kfOc5\",\"recipes_authentication.md\":\"CAsXf7hk\",\"routes.md\":\"BMM7peut\",\"security.md\":\"C668yXCi\",\"seed-data.md\":\"BvFZlqIk\",\"space-time-continuum.md\":\"KPUIKysQ\",\"tutorial.md\":\"BnoGjrdK\",\"unit-tests.md\":\"DUGrnLj5\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Brut RB\",\"description\":\"Documentation for the Brut.RB web framework.\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"search\":{\"provider\":\"local\"},\"nav\":[{\"text\":\"Home\",\"link\":\"/\"},{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Overview\",\"link\":\"/overview\"},{\"text\":\"Brut API\",\"link\":\"/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js/api/index.html\",\"target\":\"_self\"},{\"text\":\"BrutCSS\",\"link\":\"/brut-css/index.html\",\"target\":\"_self\"}],\"outline\":[2,3],\"sidebar\":[{\"text\":\"Overview\",\"collapsed\":false,\"items\":[{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Concepts\",\"link\":\"/overview\"},{\"text\":\"Documentation Conventions\",\"link\":\"/doc-conventions\"},{\"text\":\"Tutorial\",\"link\":\"/tutorial\"},{\"text\":\"Dev Environment\",\"link\":\"/dev-environment\"},{\"text\":\"AI Declaration\",\"link\":\"/ai\"}]},{\"text\":\"Front-End\",\"collapsed\":false,\"items\":[{\"text\":\"Routes\",\"link\":\"/routes\"},{\"text\":\"Pages\",\"link\":\"/pages\"},{\"text\":\"Layouts\",\"link\":\"/layouts\"},{\"text\":\"Forms\",\"link\":\"/forms\"},{\"text\":\"Handlers and Actions\",\"link\":\"/handlers\"},{\"text\":\"Components\",\"link\":\"/components\"},{\"text\":\"Flash and Session\",\"link\":\"/flash-and-session\"},{\"text\":\"Space/Time Continuum\",\"link\":\"/space-time-continuum\"},{\"text\":\"JavaScript\",\"link\":\"/javascript\"},{\"text\":\"CSS\",\"link\":\"/css\"},{\"text\":\"Assets\",\"link\":\"/assets\"},{\"text\":\"BrutJS\",\"link\":\"/brut-js\"}]},{\"text\":\"Back-End\",\"collapsed\":false,\"items\":[{\"text\":\"Database Schema\",\"link\":\"/database-schema\"},{\"text\":\"Database Access\",\"link\":\"/database-access\"},{\"text\":\"Seed Data\",\"link\":\"/seed-data\"},{\"text\":\"Jobs\",\"link\":\"/jobs\"},{\"text\":\"Business Logic\",\"link\":\"/business-logic\"}]},{\"text\":\"Framework\",\"collapsed\":false,\"items\":[{\"text\":\"Configuration\",\"link\":\"/configuration\"},{\"text\":\"Keyword Injection\",\"link\":\"/keyword-injection\"},{\"text\":\"I18n\",\"link\":\"/i18n\"},{\"text\":\"CLI / Tasks\",\"link\":\"/cli\"},{\"text\":\"Deployment\",\"link\":\"/deployment\"}]},{\"text\":\"Testing\",\"collapsed\":false,\"items\":[{\"text\":\"Unit Tests\",\"link\":\"/unit-tests\"},{\"text\":\"End-to-End Tests\",\"link\":\"/end-to-end-tests\"},{\"text\":\"Testing Custom Elements\",\"link\":\"/custom-element-tests\"}]},{\"text\":\"Advanced Topics\",\"collapsed\":true,\"items\":[{\"text\":\"Route Hooks\",\"link\":\"/hooks\"},{\"text\":\"Middleware\",\"link\":\"/middleware\"},{\"text\":\"Instrumentation\",\"link\":\"/instrumentation\"},{\"text\":\"Security\",\"link\":\"/security\"},{\"text\":\"LSP Support\",\"link\":\"/lsp\"}]},{\"text\":\"Recipes\",\"collapsed\":true,\"items\":[{\"text\":\"Authentication\",\"link\":\"/recipes/authentication\"},{\"text\":\"Form Validations\",\"link\":\"/recipes/form-validations\"},{\"text\":\"Database Migrations\",\"link\":\"/recipes/database-migrations\"},{\"text\":\"Ajax Form Submission\",\"link\":\"/recipes/ajax-form\"},{\"text\":\"Custom Telemetry\",\"link\":\"/recipes/telemetry\"},{\"text\":\"CLI App/Task\",\"link\":\"/recipes/cli-app\"}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/thirdtank/brut\"}]},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
22
22
 
23
23
  </body>
24
24
  </html>
@@ -483,7 +483,7 @@ extends this one. Do not override this method.</p>
483
483
  </div>
484
484
 
485
485
  <div id="footer">
486
- Generated on Wed Jun 25 22:57:20 2025 by
486
+ Generated on Wed Jul 2 21:45:27 2025 by
487
487
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
488
488
  0.9.37 (ruby-3.4.4).
489
489
  </div>
@@ -204,7 +204,7 @@ job executions. Do not enable in production.</p>
204
204
  </div>
205
205
 
206
206
  <div id="footer">
207
- Generated on Wed Jun 25 22:57:21 2025 by
207
+ Generated on Wed Jul 2 21:45:28 2025 by
208
208
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
209
209
  0.9.37 (ruby-3.4.4).
210
210
  </div>
@@ -115,7 +115,7 @@
115
115
  </div>
116
116
 
117
117
  <div id="footer">
118
- Generated on Wed Jun 25 22:57:20 2025 by
118
+ Generated on Wed Jul 2 21:45:27 2025 by
119
119
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
120
120
  0.9.37 (ruby-3.4.4).
121
121
  </div>
@@ -115,7 +115,7 @@
115
115
  </div>
116
116
 
117
117
  <div id="footer">
118
- Generated on Wed Jun 25 22:57:19 2025 by
118
+ Generated on Wed Jul 2 21:45:27 2025 by
119
119
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
120
120
  0.9.37 (ruby-3.4.4).
121
121
  </div>
@@ -115,7 +115,7 @@
115
115
  </div>
116
116
 
117
117
  <div id="footer">
118
- Generated on Wed Jun 25 22:57:19 2025 by
118
+ Generated on Wed Jul 2 21:45:26 2025 by
119
119
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
120
120
  0.9.37 (ruby-3.4.4).
121
121
  </div>
@@ -404,7 +404,7 @@ Your subclass of this class is a standalone object that will operate on a form.<
404
404
  </div>
405
405
 
406
406
  <div id="footer">
407
- Generated on Wed Jun 25 22:57:21 2025 by
407
+ Generated on Wed Jul 2 21:45:28 2025 by
408
408
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
409
409
  0.9.37 (ruby-3.4.4).
410
410
  </div>
@@ -118,7 +118,7 @@ data integrity, use your databases constraints and other features.</p>
118
118
  </div>
119
119
 
120
120
  <div id="footer">
121
- Generated on Wed Jun 25 22:57:19 2025 by
121
+ Generated on Wed Jul 2 21:45:26 2025 by
122
122
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
123
123
  0.9.37 (ruby-3.4.4).
124
124
  </div>
@@ -122,7 +122,7 @@ that than it is the front end.</p>
122
122
  </div>
123
123
 
124
124
  <div id="footer">
125
- Generated on Wed Jun 25 22:57:19 2025 by
125
+ Generated on Wed Jul 2 21:45:26 2025 by
126
126
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
127
127
  0.9.37 (ruby-3.4.4).
128
128
  </div>
@@ -132,7 +132,7 @@ such, the CLI has several parts that you can configure:</p>
132
132
 
133
133
  </div><div id="subclasses">
134
134
  <h2>Direct Known Subclasses</h2>
135
- <p class="children"><span class='object_link'><a href="Apps/BuildAssets.html" title="Brut::CLI::Apps::BuildAssets (class)">Brut::CLI::Apps::BuildAssets</a></span>, <span class='object_link'><a href="Apps/DB.html" title="Brut::CLI::Apps::DB (class)">Brut::CLI::Apps::DB</a></span>, <span class='object_link'><a href="Apps/Scaffold.html" title="Brut::CLI::Apps::Scaffold (class)">Brut::CLI::Apps::Scaffold</a></span>, <span class='object_link'><a href="Apps/Test.html" title="Brut::CLI::Apps::Test (class)">Brut::CLI::Apps::Test</a></span></p>
135
+ <p class="children"><span class='object_link'><a href="Apps/BuildAssets.html" title="Brut::CLI::Apps::BuildAssets (class)">Brut::CLI::Apps::BuildAssets</a></span>, <span class='object_link'><a href="Apps/DB.html" title="Brut::CLI::Apps::DB (class)">Brut::CLI::Apps::DB</a></span>, <span class='object_link'><a href="Apps/DeployBase.html" title="Brut::CLI::Apps::DeployBase (class)">Brut::CLI::Apps::DeployBase</a></span>, <span class='object_link'><a href="Apps/Scaffold.html" title="Brut::CLI::Apps::Scaffold (class)">Brut::CLI::Apps::Scaffold</a></span>, <span class='object_link'><a href="Apps/Test.html" title="Brut::CLI::Apps::Test (class)">Brut::CLI::Apps::Test</a></span></p>
136
136
  </div>
137
137
 
138
138
 
@@ -414,7 +414,7 @@ such, the CLI has several parts that you can configure:</p>
414
414
  <li class="public ">
415
415
  <span class="summary_signature">
416
416
 
417
- <a href="#after_bootstrap-instance_method" title="#after_bootstrap (instance method)">#<strong>after_bootstrap</strong> &#x21d2; Object </a>
417
+ <a href="#after_bootstrap-instance_method" title="#after_bootstrap (instance method)">#<strong>after_bootstrap</strong>(app:) &#x21d2; Object </a>
418
418
 
419
419
 
420
420
 
@@ -1353,7 +1353,7 @@ needs to know if it should operate on development, test, or production. When ca
1353
1353
  <div class="method_details first">
1354
1354
  <h3 class="signature first" id="after_bootstrap-instance_method">
1355
1355
 
1356
- #<strong>after_bootstrap</strong> &#x21d2; <tt>Object</tt>
1356
+ #<strong>after_bootstrap</strong>(app:) &#x21d2; <tt>Object</tt>
1357
1357
 
1358
1358
 
1359
1359
 
@@ -1368,7 +1368,26 @@ caused execution to be aborted.</p>
1368
1368
  </div>
1369
1369
  </div>
1370
1370
  <div class="tags">
1371
+ <p class="tag_title">Parameters:</p>
1372
+ <ul class="param">
1373
+
1374
+ <li>
1375
+
1376
+ <span class='name'>app</span>
1377
+
1378
+
1379
+ <span class='type'>(<tt><span class='object_link'><a href="../Framework/App.html" title="Brut::Framework::App (class)">Brut::Framework::App</a></span></tt>)</span>
1380
+
1381
+
1382
+
1383
+ &mdash;
1384
+ <div class='inline'><p>Your Brut app.</p>
1385
+ </div>
1386
+
1387
+ </li>
1371
1388
 
1389
+ </ul>
1390
+
1372
1391
 
1373
1392
  </div><table class="source_code">
1374
1393
  <tr>
@@ -1376,13 +1395,13 @@ caused execution to be aborted.</p>
1376
1395
  <pre class="lines">
1377
1396
 
1378
1397
 
1379
- 182
1380
- 183</pre>
1398
+ 184
1399
+ 185</pre>
1381
1400
  </td>
1382
1401
  <td>
1383
- <pre class="code"><span class="info file"># File 'lib/brut/cli/app.rb', line 182</span>
1402
+ <pre class="code"><span class="info file"># File 'lib/brut/cli/app.rb', line 184</span>
1384
1403
 
1385
- <span class='kw'>def</span> <span class='id identifier rubyid_after_bootstrap'>after_bootstrap</span>
1404
+ <span class='kw'>def</span> <span class='id identifier rubyid_after_bootstrap'>after_bootstrap</span><span class='lparen'>(</span><span class='label'>app:</span><span class='rparen'>)</span>
1386
1405
  <span class='kw'>end</span></pre>
1387
1406
  </td>
1388
1407
  </tr>
@@ -1486,8 +1505,6 @@ caused execution to be aborted.</p>
1486
1505
  <pre class="lines">
1487
1506
 
1488
1507
 
1489
- 189
1490
- 190
1491
1508
  191
1492
1509
  192
1493
1510
  193
@@ -1518,10 +1535,15 @@ caused execution to be aborted.</p>
1518
1535
  218
1519
1536
  219
1520
1537
  220
1521
- 221</pre>
1538
+ 221
1539
+ 222
1540
+ 223
1541
+ 224
1542
+ 225
1543
+ 226</pre>
1522
1544
  </td>
1523
1545
  <td>
1524
- <pre class="code"><span class="info file"># File 'lib/brut/cli/app.rb', line 189</span>
1546
+ <pre class="code"><span class="info file"># File 'lib/brut/cli/app.rb', line 191</span>
1525
1547
 
1526
1548
  <span class='kw'>def</span> <span class='id identifier rubyid_execute!'>execute!</span><span class='lparen'>(</span><span class='id identifier rubyid_command'>command</span><span class='comma'>,</span><span class='label'>project_root:</span><span class='rparen'>)</span>
1527
1549
  <span class='id identifier rubyid_before_execute'>before_execute</span>
@@ -1529,6 +1551,7 @@ caused execution to be aborted.</p>
1529
1551
  <span class='id identifier rubyid_command'>command</span><span class='period'>.</span><span class='id identifier rubyid_set_env_if_needed'>set_env_if_needed</span>
1530
1552
  <span class='id identifier rubyid_load_env'>load_env</span><span class='lparen'>(</span><span class='label'>project_root:</span><span class='rparen'>)</span>
1531
1553
  <span class='id identifier rubyid_command'>command</span><span class='period'>.</span><span class='id identifier rubyid_before_execute'>before_execute</span>
1554
+ <span class='id identifier rubyid_app'>app</span> <span class='op'>=</span> <span class='kw'>nil</span>
1532
1555
  <span class='id identifier rubyid_bootstrap_result'>bootstrap_result</span> <span class='op'>=</span> <span class='kw'>begin</span>
1533
1556
  <span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_project_root'>project_root</span><span class='embexpr_end'>}</span><span class='tstring_content'>/app/bootstrap</span><span class='tstring_end'>&quot;</span></span>
1534
1557
  <span class='id identifier rubyid_bootstrap'>bootstrap</span> <span class='op'>=</span> <span class='const'>Bootstrap</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span>
@@ -1537,6 +1560,7 @@ caused execution to be aborted.</p>
1537
1560
  <span class='kw'>else</span>
1538
1561
  <span class='id identifier rubyid_bootstrap'>bootstrap</span><span class='period'>.</span><span class='id identifier rubyid_bootstrap!'>bootstrap!</span>
1539
1562
  <span class='kw'>end</span>
1563
+ <span class='id identifier rubyid_app'>app</span> <span class='op'>=</span> <span class='id identifier rubyid_bootstrap'>bootstrap</span><span class='period'>.</span><span class='id identifier rubyid_app'>app</span>
1540
1564
  <span class='id identifier rubyid_continue_execution'>continue_execution</span>
1541
1565
  <span class='kw'>rescue</span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_ex'>ex</span>
1542
1566
  <span class='id identifier rubyid_as_execution_result'>as_execution_result</span><span class='lparen'>(</span><span class='id identifier rubyid_command'>command</span><span class='period'>.</span><span class='id identifier rubyid_handle_bootstrap_exception'>handle_bootstrap_exception</span><span class='lparen'>(</span><span class='id identifier rubyid_ex'>ex</span><span class='rparen'>)</span><span class='rparen'>)</span>
@@ -1544,7 +1568,8 @@ caused execution to be aborted.</p>
1544
1568
  <span class='kw'>if</span> <span class='id identifier rubyid_bootstrap_result'>bootstrap_result</span><span class='period'>.</span><span class='id identifier rubyid_stop?'>stop?</span>
1545
1569
  <span class='kw'>return</span> <span class='id identifier rubyid_bootstrap_result'>bootstrap_result</span>
1546
1570
  <span class='kw'>end</span>
1547
- <span class='id identifier rubyid_after_bootstrap'>after_bootstrap</span>
1571
+ <span class='id identifier rubyid_after_bootstrap'>after_bootstrap</span><span class='lparen'>(</span><span class='label'>app:</span><span class='rparen'>)</span>
1572
+ <span class='id identifier rubyid_command'>command</span><span class='period'>.</span><span class='id identifier rubyid_after_bootstrap'>after_bootstrap</span><span class='lparen'>(</span><span class='label'>app:</span><span class='rparen'>)</span>
1548
1573
  <span class='kw'>if</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span><span class='period'>.</span><span class='id identifier rubyid_configure_only?'>configure_only?</span>
1549
1574
  <span class='id identifier rubyid_as_execution_result'>as_execution_result</span><span class='lparen'>(</span><span class='id identifier rubyid_command'>command</span><span class='period'>.</span><span class='id identifier rubyid_execute'>execute</span><span class='rparen'>)</span>
1550
1575
  <span class='kw'>else</span>
@@ -1566,7 +1591,7 @@ caused execution to be aborted.</p>
1566
1591
  </div>
1567
1592
 
1568
1593
  <div id="footer">
1569
- Generated on Wed Jun 25 22:57:20 2025 by
1594
+ Generated on Wed Jul 2 21:45:27 2025 by
1570
1595
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
1571
1596
  0.9.37 (ruby-3.4.4).
1572
1597
  </div>
@@ -481,7 +481,7 @@
481
481
  </div>
482
482
 
483
483
  <div id="footer">
484
- Generated on Wed Jun 25 22:57:20 2025 by
484
+ Generated on Wed Jul 2 21:45:27 2025 by
485
485
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
486
486
  0.9.37 (ruby-3.4.4).
487
487
  </div>
@@ -152,7 +152,7 @@
152
152
 
153
153
 
154
154
  <h3 class="inherited">Methods inherited from <span class='object_link'><a href="../../Command.html" title="Brut::CLI::Command (class)">Command</a></span></h3>
155
- <p class="inherited"><span class='object_link'><a href="../../Command.html#args-class_method" title="Brut::CLI::Command.args (method)">args</a></span>, <span class='object_link'><a href="../../Command.html#args-instance_method" title="Brut::CLI::Command#args (method)">#args</a></span>, <span class='object_link'><a href="../../Command.html#before_execute-instance_method" title="Brut::CLI::Command#before_execute (method)">#before_execute</a></span>, <span class='object_link'><a href="../../Command.html#command_name-class_method" title="Brut::CLI::Command.command_name (method)">command_name</a></span>, <span class='object_link'><a href="../../Command.html#default_env-class_method" title="Brut::CLI::Command.default_env (method)">default_env</a></span>, <span class='object_link'><a href="../../Command.html#delegate_to_commands-instance_method" title="Brut::CLI::Command#delegate_to_commands (method)">#delegate_to_commands</a></span>, <span class='object_link'><a href="../../Command.html#description-class_method" title="Brut::CLI::Command.description (method)">description</a></span>, <span class='object_link'><a href="../../Command.html#detailed_description-class_method" title="Brut::CLI::Command.detailed_description (method)">detailed_description</a></span>, <span class='object_link'><a href="../../Command.html#env_var-class_method" title="Brut::CLI::Command.env_var (method)">env_var</a></span>, <span class='object_link'><a href="../../Command.html#err-instance_method" title="Brut::CLI::Command#err (method)">#err</a></span>, <span class='object_link'><a href="../../Command.html#global_options-instance_method" title="Brut::CLI::Command#global_options (method)">#global_options</a></span>, <span class='object_link'><a href="../../Command.html#handle_bootstrap_exception-instance_method" title="Brut::CLI::Command#handle_bootstrap_exception (method)">#handle_bootstrap_exception</a></span>, <span class='object_link'><a href="../../Command.html#initialize-instance_method" title="Brut::CLI::Command#initialize (method)">#initialize</a></span>, <span class='object_link'><a href="../../Command.html#name_matches%3F-class_method" title="Brut::CLI::Command.name_matches? (method)">name_matches?</a></span>, <span class='object_link'><a href="../../Command.html#option_parser-class_method" title="Brut::CLI::Command.option_parser (method)">option_parser</a></span>, <span class='object_link'><a href="../../Command.html#options-instance_method" title="Brut::CLI::Command#options (method)">#options</a></span>, <span class='object_link'><a href="../../Command.html#opts-class_method" title="Brut::CLI::Command.opts (method)">opts</a></span>, <span class='object_link'><a href="../../Command.html#out-instance_method" title="Brut::CLI::Command#out (method)">#out</a></span>, <span class='object_link'><a href="../../Command.html#requires_project_env-class_method" title="Brut::CLI::Command.requires_project_env (method)">requires_project_env</a></span>, <span class='object_link'><a href="../../Command.html#requires_project_env%3F-class_method" title="Brut::CLI::Command.requires_project_env? (method)">requires_project_env?</a></span>, <span class='object_link'><a href="../../Command.html#system!-instance_method" title="Brut::CLI::Command#system! (method)">#system!</a></span></p>
155
+ <p class="inherited"><span class='object_link'><a href="../../Command.html#after_bootstrap-instance_method" title="Brut::CLI::Command#after_bootstrap (method)">#after_bootstrap</a></span>, <span class='object_link'><a href="../../Command.html#args-class_method" title="Brut::CLI::Command.args (method)">args</a></span>, <span class='object_link'><a href="../../Command.html#args-instance_method" title="Brut::CLI::Command#args (method)">#args</a></span>, <span class='object_link'><a href="../../Command.html#before_execute-instance_method" title="Brut::CLI::Command#before_execute (method)">#before_execute</a></span>, <span class='object_link'><a href="../../Command.html#command_name-class_method" title="Brut::CLI::Command.command_name (method)">command_name</a></span>, <span class='object_link'><a href="../../Command.html#default_env-class_method" title="Brut::CLI::Command.default_env (method)">default_env</a></span>, <span class='object_link'><a href="../../Command.html#delegate_to_commands-instance_method" title="Brut::CLI::Command#delegate_to_commands (method)">#delegate_to_commands</a></span>, <span class='object_link'><a href="../../Command.html#description-class_method" title="Brut::CLI::Command.description (method)">description</a></span>, <span class='object_link'><a href="../../Command.html#detailed_description-class_method" title="Brut::CLI::Command.detailed_description (method)">detailed_description</a></span>, <span class='object_link'><a href="../../Command.html#env_var-class_method" title="Brut::CLI::Command.env_var (method)">env_var</a></span>, <span class='object_link'><a href="../../Command.html#err-instance_method" title="Brut::CLI::Command#err (method)">#err</a></span>, <span class='object_link'><a href="../../Command.html#global_options-instance_method" title="Brut::CLI::Command#global_options (method)">#global_options</a></span>, <span class='object_link'><a href="../../Command.html#handle_bootstrap_exception-instance_method" title="Brut::CLI::Command#handle_bootstrap_exception (method)">#handle_bootstrap_exception</a></span>, <span class='object_link'><a href="../../Command.html#initialize-instance_method" title="Brut::CLI::Command#initialize (method)">#initialize</a></span>, <span class='object_link'><a href="../../Command.html#name_matches%3F-class_method" title="Brut::CLI::Command.name_matches? (method)">name_matches?</a></span>, <span class='object_link'><a href="../../Command.html#option_parser-class_method" title="Brut::CLI::Command.option_parser (method)">option_parser</a></span>, <span class='object_link'><a href="../../Command.html#options-instance_method" title="Brut::CLI::Command#options (method)">#options</a></span>, <span class='object_link'><a href="../../Command.html#opts-class_method" title="Brut::CLI::Command.opts (method)">opts</a></span>, <span class='object_link'><a href="../../Command.html#out-instance_method" title="Brut::CLI::Command#out (method)">#out</a></span>, <span class='object_link'><a href="../../Command.html#requires_project_env-class_method" title="Brut::CLI::Command.requires_project_env (method)">requires_project_env</a></span>, <span class='object_link'><a href="../../Command.html#requires_project_env%3F-class_method" title="Brut::CLI::Command.requires_project_env? (method)">requires_project_env?</a></span>, <span class='object_link'><a href="../../Command.html#system!-instance_method" title="Brut::CLI::Command#system! (method)">#system!</a></span></p>
156
156
 
157
157
 
158
158
 
@@ -254,7 +254,7 @@
254
254
  </div>
255
255
 
256
256
  <div id="footer">
257
- Generated on Wed Jun 25 22:57:20 2025 by
257
+ Generated on Wed Jul 2 21:45:27 2025 by
258
258
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
259
259
  0.9.37 (ruby-3.4.4).
260
260
  </div>