@stacksjs/defaults 0.70.206 → 0.70.208

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 (408) hide show
  1. package/TODO.md +21 -0
  2. package/ai/AGENTS.md +79 -0
  3. package/ai/README.md +45 -0
  4. package/ai/claude/launch.json +12 -0
  5. package/ai/skills/stacks-actions/SKILL.md +128 -0
  6. package/ai/skills/stacks-ai/SKILL.md +276 -0
  7. package/ai/skills/stacks-alias/SKILL.md +94 -0
  8. package/ai/skills/stacks-analytics/SKILL.md +91 -0
  9. package/ai/skills/stacks-api/SKILL.md +738 -0
  10. package/ai/skills/stacks-arrays/SKILL.md +277 -0
  11. package/ai/skills/stacks-auth/SKILL.md +422 -0
  12. package/ai/skills/stacks-auto-imports/SKILL.md +138 -0
  13. package/ai/skills/stacks-brandkit/SKILL.md +811 -0
  14. package/ai/skills/stacks-browse/SKILL.md +127 -0
  15. package/ai/skills/stacks-browse/scripts/browse.ts +492 -0
  16. package/ai/skills/stacks-browser/SKILL.md +145 -0
  17. package/ai/skills/stacks-buddy/SKILL.md +676 -0
  18. package/ai/skills/stacks-build/SKILL.md +163 -0
  19. package/ai/skills/stacks-cache/SKILL.md +125 -0
  20. package/ai/skills/stacks-calendar/SKILL.md +113 -0
  21. package/ai/skills/stacks-chat/SKILL.md +371 -0
  22. package/ai/skills/stacks-cli/SKILL.md +112 -0
  23. package/ai/skills/stacks-cloud/SKILL.md +192 -0
  24. package/ai/skills/stacks-cms/SKILL.md +217 -0
  25. package/ai/skills/stacks-collections/SKILL.md +82 -0
  26. package/ai/skills/stacks-commerce/SKILL.md +114 -0
  27. package/ai/skills/stacks-composables/SKILL.md +161 -0
  28. package/ai/skills/stacks-config/SKILL.md +144 -0
  29. package/ai/skills/stacks-configuration/SKILL.md +154 -0
  30. package/ai/skills/stacks-cron/SKILL.md +123 -0
  31. package/ai/skills/stacks-crosswind/SKILL.md +190 -0
  32. package/ai/skills/stacks-dashboard/SKILL.md +173 -0
  33. package/ai/skills/stacks-database/SKILL.md +286 -0
  34. package/ai/skills/stacks-datetime/SKILL.md +269 -0
  35. package/ai/skills/stacks-dependencies/SKILL.md +111 -0
  36. package/ai/skills/stacks-deploy/SKILL.md +102 -0
  37. package/ai/skills/stacks-design-brutalist/SKILL.md +110 -0
  38. package/ai/skills/stacks-design-minimalist/SKILL.md +115 -0
  39. package/ai/skills/stacks-design-output/SKILL.md +55 -0
  40. package/ai/skills/stacks-design-soft/SKILL.md +156 -0
  41. package/ai/skills/stacks-design-taste/SKILL.md +1012 -0
  42. package/ai/skills/stacks-design-taste-codex/SKILL.md +294 -0
  43. package/ai/skills/stacks-desktop/SKILL.md +78 -0
  44. package/ai/skills/stacks-development/SKILL.md +298 -0
  45. package/ai/skills/stacks-dns/SKILL.md +149 -0
  46. package/ai/skills/stacks-docs/SKILL.md +109 -0
  47. package/ai/skills/stacks-email/SKILL.md +236 -0
  48. package/ai/skills/stacks-enums/SKILL.md +100 -0
  49. package/ai/skills/stacks-env/SKILL.md +181 -0
  50. package/ai/skills/stacks-error-handling/SKILL.md +137 -0
  51. package/ai/skills/stacks-events/SKILL.md +228 -0
  52. package/ai/skills/stacks-faker/SKILL.md +158 -0
  53. package/ai/skills/stacks-git/SKILL.md +158 -0
  54. package/ai/skills/stacks-guard/SKILL.md +98 -0
  55. package/ai/skills/stacks-health/SKILL.md +75 -0
  56. package/ai/skills/stacks-http/SKILL.md +316 -0
  57. package/ai/skills/stacks-i18n/SKILL.md +198 -0
  58. package/ai/skills/stacks-image-to-code/SKILL.md +629 -0
  59. package/ai/skills/stacks-imagegen-mobile/SKILL.md +1474 -0
  60. package/ai/skills/stacks-imagegen-web/SKILL.md +998 -0
  61. package/ai/skills/stacks-investigate/SKILL.md +119 -0
  62. package/ai/skills/stacks-jobs/SKILL.md +136 -0
  63. package/ai/skills/stacks-lint/SKILL.md +184 -0
  64. package/ai/skills/stacks-listeners/SKILL.md +99 -0
  65. package/ai/skills/stacks-logging/SKILL.md +78 -0
  66. package/ai/skills/stacks-mail/SKILL.md +120 -0
  67. package/ai/skills/stacks-middleware/SKILL.md +249 -0
  68. package/ai/skills/stacks-migrations/SKILL.md +105 -0
  69. package/ai/skills/stacks-models/SKILL.md +267 -0
  70. package/ai/skills/stacks-new-feature/SKILL.md +206 -0
  71. package/ai/skills/stacks-notifications/SKILL.md +210 -0
  72. package/ai/skills/stacks-objects/SKILL.md +205 -0
  73. package/ai/skills/stacks-office-hours/SKILL.md +134 -0
  74. package/ai/skills/stacks-orm/SKILL.md +342 -0
  75. package/ai/skills/stacks-path/SKILL.md +118 -0
  76. package/ai/skills/stacks-payments/SKILL.md +373 -0
  77. package/ai/skills/stacks-plan-review/SKILL.md +152 -0
  78. package/ai/skills/stacks-plugins/SKILL.md +149 -0
  79. package/ai/skills/stacks-push/SKILL.md +376 -0
  80. package/ai/skills/stacks-query-builder/SKILL.md +128 -0
  81. package/ai/skills/stacks-queue/SKILL.md +559 -0
  82. package/ai/skills/stacks-realtime/SKILL.md +442 -0
  83. package/ai/skills/stacks-redesign/SKILL.md +182 -0
  84. package/ai/skills/stacks-registry/SKILL.md +58 -0
  85. package/ai/skills/stacks-repl/SKILL.md +80 -0
  86. package/ai/skills/stacks-retro/SKILL.md +122 -0
  87. package/ai/skills/stacks-review/SKILL.md +135 -0
  88. package/ai/skills/stacks-router/SKILL.md +231 -0
  89. package/ai/skills/stacks-routes/SKILL.md +105 -0
  90. package/ai/skills/stacks-scaffolding/SKILL.md +162 -0
  91. package/ai/skills/stacks-scheduler/SKILL.md +363 -0
  92. package/ai/skills/stacks-search-engine/SKILL.md +112 -0
  93. package/ai/skills/stacks-security/SKILL.md +129 -0
  94. package/ai/skills/stacks-security-audit/SKILL.md +128 -0
  95. package/ai/skills/stacks-server/SKILL.md +458 -0
  96. package/ai/skills/stacks-shell/SKILL.md +62 -0
  97. package/ai/skills/stacks-slug/SKILL.md +87 -0
  98. package/ai/skills/stacks-sms/SKILL.md +385 -0
  99. package/ai/skills/stacks-socials/SKILL.md +303 -0
  100. package/ai/skills/stacks-storage/SKILL.md +576 -0
  101. package/ai/skills/stacks-strings/SKILL.md +416 -0
  102. package/ai/skills/stacks-stx/SKILL.md +176 -0
  103. package/ai/skills/stacks-technical-diagrams/LICENSE +22 -0
  104. package/ai/skills/stacks-technical-diagrams/SKILL.md +290 -0
  105. package/ai/skills/stacks-technical-diagrams/agents/openai.yaml +4 -0
  106. package/ai/skills/stacks-technical-diagrams/assets/template.html +1252 -0
  107. package/ai/skills/stacks-technical-diagrams/bin/technical-diagrams.mjs +289 -0
  108. package/ai/skills/stacks-technical-diagrams/bunfig.toml +1 -0
  109. package/ai/skills/stacks-technical-diagrams/examples/agent-run.lifecycle.json +64 -0
  110. package/ai/skills/stacks-technical-diagrams/examples/agent-tool-call.workflow.json +88 -0
  111. package/ai/skills/stacks-technical-diagrams/examples/cache-miss-request.sequence.json +75 -0
  112. package/ai/skills/stacks-technical-diagrams/examples/product-analytics.dataflow.json +70 -0
  113. package/ai/skills/stacks-technical-diagrams/examples/web-app.architecture.json +41 -0
  114. package/ai/skills/stacks-technical-diagrams/renderers/architecture/grid.mjs +62 -0
  115. package/ai/skills/stacks-technical-diagrams/renderers/architecture/render-architecture.mjs +371 -0
  116. package/ai/skills/stacks-technical-diagrams/renderers/dataflow/README.md +82 -0
  117. package/ai/skills/stacks-technical-diagrams/renderers/dataflow/render-dataflow.mjs +295 -0
  118. package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/README.md +91 -0
  119. package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/render-lifecycle.mjs +384 -0
  120. package/ai/skills/stacks-technical-diagrams/renderers/sequence/README.md +84 -0
  121. package/ai/skills/stacks-technical-diagrams/renderers/sequence/render-sequence.mjs +257 -0
  122. package/ai/skills/stacks-technical-diagrams/renderers/shared/cli.mjs +42 -0
  123. package/ai/skills/stacks-technical-diagrams/renderers/shared/generated-validators.mjs +13 -0
  124. package/ai/skills/stacks-technical-diagrams/renderers/shared/geometry.mjs +230 -0
  125. package/ai/skills/stacks-technical-diagrams/renderers/shared/layout-report.mjs +40 -0
  126. package/ai/skills/stacks-technical-diagrams/renderers/shared/utils.mjs +88 -0
  127. package/ai/skills/stacks-technical-diagrams/renderers/shared/validator.mjs +40 -0
  128. package/ai/skills/stacks-technical-diagrams/renderers/workflow/README.md +103 -0
  129. package/ai/skills/stacks-technical-diagrams/renderers/workflow/render-workflow.mjs +481 -0
  130. package/ai/skills/stacks-technical-diagrams/schemas/README.md +68 -0
  131. package/ai/skills/stacks-technical-diagrams/schemas/architecture.schema.json +121 -0
  132. package/ai/skills/stacks-technical-diagrams/schemas/common.schema.json +43 -0
  133. package/ai/skills/stacks-technical-diagrams/schemas/dataflow.schema.json +221 -0
  134. package/ai/skills/stacks-technical-diagrams/schemas/lifecycle.schema.json +241 -0
  135. package/ai/skills/stacks-technical-diagrams/schemas/sequence.schema.json +186 -0
  136. package/ai/skills/stacks-technical-diagrams/schemas/workflow.schema.json +332 -0
  137. package/ai/skills/stacks-technical-diagrams/scripts/check-render-output.mjs +297 -0
  138. package/ai/skills/stacks-technical-diagrams/scripts/render-examples.mjs +28 -0
  139. package/ai/skills/stacks-testing/SKILL.md +129 -0
  140. package/ai/skills/stacks-tunnel/SKILL.md +125 -0
  141. package/ai/skills/stacks-types/SKILL.md +178 -0
  142. package/ai/skills/stacks-ui/SKILL.md +246 -0
  143. package/ai/skills/stacks-utils/SKILL.md +444 -0
  144. package/ai/skills/stacks-validation/SKILL.md +371 -0
  145. package/ai/skills/stacks-whois/SKILL.md +315 -0
  146. package/assets/world-map-data.ts +121 -0
  147. package/bootstrap.ts +114 -0
  148. package/docs/api-examples.md +46 -0
  149. package/docs/index.md +24 -0
  150. package/docs/markdown-examples.md +87 -0
  151. package/functions/analytics.ts +97 -0
  152. package/functions/api.ts +143 -0
  153. package/functions/auth.ts +208 -0
  154. package/functions/billing/payments.ts +149 -0
  155. package/functions/blog.ts +120 -0
  156. package/functions/cms/categorizables.ts +107 -0
  157. package/functions/cms/pages.ts +108 -0
  158. package/functions/cms/posts.ts +100 -0
  159. package/functions/cms/taggables.ts +102 -0
  160. package/functions/commerce/coupons.ts +128 -0
  161. package/functions/commerce/customers.ts +128 -0
  162. package/functions/commerce/gift-cards.ts +119 -0
  163. package/functions/commerce/orders.ts +112 -0
  164. package/functions/commerce/payments.ts +119 -0
  165. package/functions/commerce/products/categories.ts +123 -0
  166. package/functions/commerce/products/manufacturers.ts +123 -0
  167. package/functions/commerce/products/products.ts +123 -0
  168. package/functions/commerce/products/reviews.ts +123 -0
  169. package/functions/commerce/products/units.ts +123 -0
  170. package/functions/commerce/products/variants.ts +123 -0
  171. package/functions/commerce/shippings/delivery-routes.ts +123 -0
  172. package/functions/commerce/shippings/digital-deliveries.ts +119 -0
  173. package/functions/commerce/shippings/drivers.ts +123 -0
  174. package/functions/commerce/shippings/license-keys.ts +123 -0
  175. package/functions/commerce/shippings/shipping-methods.ts +123 -0
  176. package/functions/commerce/shippings/shipping-rates.ts +119 -0
  177. package/functions/commerce/shippings/shipping-zones.ts +119 -0
  178. package/functions/commerce/taxes.ts +119 -0
  179. package/functions/commerce/waitlist/products.ts +123 -0
  180. package/functions/commerce/waitlist/restaurants.ts +123 -0
  181. package/functions/craft.ts +107 -0
  182. package/functions/dashboard.ts +153 -0
  183. package/functions/inbox.ts +95 -0
  184. package/functions/jobs.ts +86 -0
  185. package/functions/monitoring/errors.ts +295 -0
  186. package/functions/queue.ts +111 -0
  187. package/functions/realtime/websockets.ts +96 -0
  188. package/functions/realtime.ts +52 -0
  189. package/functions/releases.ts +49 -0
  190. package/functions/search.ts +126 -0
  191. package/functions/toasts.ts +95 -0
  192. package/functions/uploads.ts +216 -0
  193. package/ide/.gitignore +4 -0
  194. package/ide/cursor/rules/auto-imports.mdc +574 -0
  195. package/ide/cursor/rules/code-style.mdc +12 -0
  196. package/ide/cursor/rules/documentation.mdc +9 -0
  197. package/ide/cursor/rules/error-handling-validation.mdc +11 -0
  198. package/ide/cursor/rules/key-conventions.mdc +11 -0
  199. package/ide/cursor/rules/project-structure.mdc +169 -0
  200. package/ide/cursor/rules/readme.mdc +318 -0
  201. package/ide/cursor/rules/syntax-formatting.mdc +9 -0
  202. package/ide/cursor/rules/testing.mdc +10 -0
  203. package/ide/cursor/rules/typescript.mdc +9 -0
  204. package/ide/cursor/rules/ui-styling.mdc +0 -0
  205. package/ide/dictionary.txt +397 -0
  206. package/ide/jetbrains/.fleet/settings.json +4 -0
  207. package/ide/jetbrains/.idea/.gitignore +5 -0
  208. package/ide/jetbrains/.idea/.name +1 -0
  209. package/ide/jetbrains/.idea/inspectionProfiles/Project_Default.xml +6 -0
  210. package/ide/jetbrains/.idea/jsLinters/eslint.xml +7 -0
  211. package/ide/jetbrains/.idea/modules.xml +8 -0
  212. package/ide/jetbrains/.idea/stacks.iml +22 -0
  213. package/ide/jetbrains/.idea/vcs.xml +6 -0
  214. package/ide/jetbrains/.idea/webResources.xml +14 -0
  215. package/ide/jetbrains/IntelliJ IDEA Global Settings +0 -0
  216. package/ide/jetbrains/installed.txt +4 -0
  217. package/ide/jetbrains/options/github-copilot.xml +5 -0
  218. package/ide/jetbrains/options/nodejs.xml +7 -0
  219. package/ide/jetbrains/options/templates.xml +124 -0
  220. package/ide/jetbrains/templates/JavaScript.xml +6 -0
  221. package/ide/jetbrains/templates/Stacks.xml +8 -0
  222. package/ide/vscode/.vscode/README.md +23 -0
  223. package/ide/vscode/.vscode/extensions.json +5 -0
  224. package/ide/vscode/.vscode/settings.json +176 -0
  225. package/ide/vscode/.vscode/stacks.code-snippets +181 -0
  226. package/ide/vscode/LICENSE.md +21 -0
  227. package/ide/vscode/README.md +36 -0
  228. package/ide/vscode/logo.png +0 -0
  229. package/ide/vscode/package.json +79 -0
  230. package/ide/zed/.zed/settings.json +139 -0
  231. package/lang/README.md +28 -0
  232. package/lang/de.yml +14 -0
  233. package/lang/en.yml +15 -0
  234. package/package.json +19 -3
  235. package/project/bootstrap +161 -0
  236. package/project/buddy +175 -0
  237. package/project/storage/framework/tsconfig.app.json +50 -0
  238. package/project/storage/framework/tsconfig.base.json +58 -0
  239. package/routes/core.ts +78 -0
  240. package/routes/dashboard-api.ts +233 -0
  241. package/routes/dashboard.ts +739 -0
  242. package/routes/email.ts +129 -0
  243. package/stores/[name].stx +16 -0
  244. package/stores/git.ts +71 -0
  245. package/stores/payment.ts +474 -0
  246. package/stores/queue.ts +43 -0
  247. package/stores/user.ts +29 -0
  248. package/stx-components-plugin.ts +25 -0
  249. package/styles/design-tokens.css +597 -0
  250. package/types/dashboard.ts +70 -0
  251. package/types/defaults.ts +438 -0
  252. package/vcs/github/CODE_OF_CONDUCT.md +83 -0
  253. package/vcs/github/CONTRIBUTING.md +187 -0
  254. package/vcs/github/EXPLANATIONS.md +41 -0
  255. package/vcs/github/FUNDING.yml +1 -0
  256. package/vcs/github/ISSUE_TEMPLATE/bug_report.yml +49 -0
  257. package/vcs/github/ISSUE_TEMPLATE/config.yml +10 -0
  258. package/vcs/github/ISSUE_TEMPLATE/feature_request.yml +44 -0
  259. package/vcs/github/SECURITY.md +70 -0
  260. package/vcs/github/renovate.json +5 -0
  261. package/vcs/github/stale.yml +14 -0
  262. package/vcs/github/workflows/README.md +16 -0
  263. package/vcs/github/workflows/ci.yml +114 -0
  264. package/vcs/github/workflows/export-size.yml +25 -0
  265. package/vcs/github/workflows/labeler.yml +13 -0
  266. package/vcs/github/workflows/release.yml +219 -0
  267. package/views/[...all].stx +8 -0
  268. package/views/about.md +3 -0
  269. package/views/auth/login.stx +1 -0
  270. package/views/auth/signup.stx +85 -0
  271. package/views/dashboard/.discovered-models.json +542 -0
  272. package/views/dashboard/AUDIT.md +904 -0
  273. package/views/dashboard/[...all].stx +89 -0
  274. package/views/dashboard/access-tokens/index.stx +177 -0
  275. package/views/dashboard/actions/index.stx +129 -0
  276. package/views/dashboard/analytics/blog/index.stx +356 -0
  277. package/views/dashboard/analytics/browsers/index.stx +263 -0
  278. package/views/dashboard/analytics/commerce/sales/index.stx +329 -0
  279. package/views/dashboard/analytics/commerce/web/index.stx +379 -0
  280. package/views/dashboard/analytics/countries/index.stx +289 -0
  281. package/views/dashboard/analytics/devices/index.stx +305 -0
  282. package/views/dashboard/analytics/events/index.stx +536 -0
  283. package/views/dashboard/analytics/index.stx +88 -0
  284. package/views/dashboard/analytics/marketing/index.stx +315 -0
  285. package/views/dashboard/analytics/pages/index.stx +271 -0
  286. package/views/dashboard/analytics/referrers/index.stx +319 -0
  287. package/views/dashboard/analytics/web/index.stx +356 -0
  288. package/views/dashboard/buddy/index.stx +198 -0
  289. package/views/dashboard/ci/index.stx +462 -0
  290. package/views/dashboard/cloud/index.stx +452 -0
  291. package/views/dashboard/commands/index.stx +295 -0
  292. package/views/dashboard/commerce/categories/index.stx +406 -0
  293. package/views/dashboard/commerce/coupons/index.stx +485 -0
  294. package/views/dashboard/commerce/customers/index.stx +410 -0
  295. package/views/dashboard/commerce/dashboard/index.stx +287 -0
  296. package/views/dashboard/commerce/delivery/delivery-routes.stx +305 -0
  297. package/views/dashboard/commerce/delivery/digital-delivery.stx +332 -0
  298. package/views/dashboard/commerce/delivery/drivers.stx +397 -0
  299. package/views/dashboard/commerce/delivery/index.stx +18 -0
  300. package/views/dashboard/commerce/delivery/license-keys.stx +380 -0
  301. package/views/dashboard/commerce/delivery/shipping-methods.stx +346 -0
  302. package/views/dashboard/commerce/delivery/shipping-rates.stx +338 -0
  303. package/views/dashboard/commerce/delivery/shipping-zones.stx +302 -0
  304. package/views/dashboard/commerce/delivery/tabs.ts +25 -0
  305. package/views/dashboard/commerce/gift-cards/index.stx +561 -0
  306. package/views/dashboard/commerce/manufacturers/index.stx +308 -0
  307. package/views/dashboard/commerce/orders/index.stx +247 -0
  308. package/views/dashboard/commerce/payments/index.stx +535 -0
  309. package/views/dashboard/commerce/pos/index.stx +653 -0
  310. package/views/dashboard/commerce/printers/devices/index.stx +273 -0
  311. package/views/dashboard/commerce/printers/receipts/index.stx +308 -0
  312. package/views/dashboard/commerce/products/detail.stx +563 -0
  313. package/views/dashboard/commerce/products/index.stx +370 -0
  314. package/views/dashboard/commerce/reviews/index.stx +656 -0
  315. package/views/dashboard/commerce/reviews/index.ts +0 -0
  316. package/views/dashboard/commerce/taxes/index.stx +377 -0
  317. package/views/dashboard/commerce/units/index.stx +317 -0
  318. package/views/dashboard/commerce/variants/index.stx +319 -0
  319. package/views/dashboard/commerce/waitlist/products.stx +942 -0
  320. package/views/dashboard/commerce/waitlist/restaurant.stx +1024 -0
  321. package/views/dashboard/components/index.stx +330 -0
  322. package/views/dashboard/composables/index.ts +19 -0
  323. package/views/dashboard/composables/useChart.ts +77 -0
  324. package/views/dashboard/composables/useNavigation.ts +99 -0
  325. package/views/dashboard/composables/useRole.ts +58 -0
  326. package/views/dashboard/composables/useTheme.ts +74 -0
  327. package/views/dashboard/content/authors/index.stx +171 -0
  328. package/views/dashboard/content/blog/index.stx +493 -0
  329. package/views/dashboard/content/categories/index.stx +169 -0
  330. package/views/dashboard/content/comments/index.stx +189 -0
  331. package/views/dashboard/content/dashboard.stx +383 -0
  332. package/views/dashboard/content/files/index.stx +706 -0
  333. package/views/dashboard/content/pages/index.stx +174 -0
  334. package/views/dashboard/content/posts/index.stx +269 -0
  335. package/views/dashboard/content/seo/index.stx +240 -0
  336. package/views/dashboard/content/tags/index.stx +167 -0
  337. package/views/dashboard/data/activity/index.stx +261 -0
  338. package/views/dashboard/data/dashboard/index.stx +116 -0
  339. package/views/dashboard/data/subscribers.stx +270 -0
  340. package/views/dashboard/data/teams.stx +275 -0
  341. package/views/dashboard/data/users.stx +279 -0
  342. package/views/dashboard/dependencies/index.stx +178 -0
  343. package/views/dashboard/deployments/[id].stx +234 -0
  344. package/views/dashboard/deployments/index.stx +9 -0
  345. package/views/dashboard/dns/index.stx +163 -0
  346. package/views/dashboard/environment/index.stx +283 -0
  347. package/views/dashboard/errors/index.stx +274 -0
  348. package/views/dashboard/forgot-password.stx +57 -0
  349. package/views/dashboard/functions/index.stx +159 -0
  350. package/views/dashboard/health/index.stx +248 -0
  351. package/views/dashboard/inbox/activity.stx +350 -0
  352. package/views/dashboard/inbox/index.stx +452 -0
  353. package/views/dashboard/inbox/settings.stx +290 -0
  354. package/views/dashboard/index.stx +252 -0
  355. package/views/dashboard/insights/index.stx +529 -0
  356. package/views/dashboard/jobs/[id].stx +430 -0
  357. package/views/dashboard/jobs/history.stx +222 -0
  358. package/views/dashboard/jobs/index.stx +214 -0
  359. package/views/dashboard/kanban/[id].stx +899 -0
  360. package/views/dashboard/kanban/index.stx +260 -0
  361. package/views/dashboard/layouts/default.stx +565 -0
  362. package/views/dashboard/layouts/guest.stx +10 -0
  363. package/views/dashboard/login.stx +48 -0
  364. package/views/dashboard/logs/index.stx +540 -0
  365. package/views/dashboard/mailboxes/index.stx +149 -0
  366. package/views/dashboard/management/permissions/index.stx +490 -0
  367. package/views/dashboard/marketing/campaigns/index.stx +604 -0
  368. package/views/dashboard/marketing/lists/index.stx +514 -0
  369. package/views/dashboard/marketing/reviews/index.stx +475 -0
  370. package/views/dashboard/marketing/social-posts/index.stx +560 -0
  371. package/views/dashboard/models/[model].stx +195 -0
  372. package/views/dashboard/models/index.stx +159 -0
  373. package/views/dashboard/monitoring/errors/index.stx +415 -0
  374. package/views/dashboard/notifications/dashboard.stx +383 -0
  375. package/views/dashboard/notifications/email.stx +336 -0
  376. package/views/dashboard/notifications/history.stx +373 -0
  377. package/views/dashboard/notifications/sms.stx +332 -0
  378. package/views/dashboard/packages/index.stx +195 -0
  379. package/views/dashboard/queries/[id].stx +381 -0
  380. package/views/dashboard/queries/history.stx +227 -0
  381. package/views/dashboard/queries/index.stx +335 -0
  382. package/views/dashboard/queries/slow.stx +318 -0
  383. package/views/dashboard/queue/index.stx +427 -0
  384. package/views/dashboard/realtime/index.stx +429 -0
  385. package/views/dashboard/register.stx +46 -0
  386. package/views/dashboard/releases/index.stx +389 -0
  387. package/views/dashboard/requests/index.stx +462 -0
  388. package/views/dashboard/serverless/index.stx +475 -0
  389. package/views/dashboard/servers/[id].stx +299 -0
  390. package/views/dashboard/servers/index.stx +483 -0
  391. package/views/dashboard/settings/billing.stx +50 -0
  392. package/views/dashboard/settings/index.stx +256 -0
  393. package/views/dashboard/settings/mail.stx +252 -0
  394. package/views/dashboard/stores/auth.ts +123 -0
  395. package/views/dashboard/stores/ci.ts +342 -0
  396. package/views/dashboard/stores/index.ts +129 -0
  397. package/views/dashboard/stores/kanban.ts +723 -0
  398. package/views/dashboard/stores/rbac.ts +350 -0
  399. package/views/dashboard/stx.config.ts +34 -0
  400. package/views/dashboard/teams/[id].stx +170 -0
  401. package/views/forum/category.stx +92 -0
  402. package/views/forum/index.stx +209 -0
  403. package/views/forum/new-topic.stx +113 -0
  404. package/views/forum/profile.stx +1 -0
  405. package/views/forum/topic.stx +143 -0
  406. package/views/hello-world/[name].stx +47 -0
  407. package/views/index.stx +21 -0
  408. package/views/system-tray/index.stx +147 -0
@@ -0,0 +1,267 @@
1
+ ---
2
+ name: stacks-models
3
+ description: Use when working with data models in Stacks — the defineModel() API, model attributes with validation and factories, relationships (hasOne/hasMany/belongsTo/belongsToMany), traits (useAuth, useUuid, useTimestamps, useSearch, useApi, billable, taggable, categorizable, commentable, likeable, observe), computed properties (get/set), model generation, and the 50+ built-in framework models. Covers model definitions and storage/framework/defaults/app/Models/.
4
+ license: MIT
5
+ compatibility: Bun >= 1.3.0, TypeScript, SQLite >= 3.47.2
6
+ allowed-tools: Read Edit Write Bash Grep Glob
7
+ ---
8
+
9
+ # Stacks Models
10
+
11
+ ## Key Paths
12
+ - Your models: `app/Models/` (create it; it does not exist in a fresh project)
13
+ - Built-in models: `storage/framework/defaults/app/Models/` (62 files, grouped
14
+ into `commerce/`, `Content/`, `realtime/` and a flat top level)
15
+ - `ModelOptions` / `Attribute` types: `storage/framework/core/types/src/model.ts`
16
+ - Attribute presets: `storage/framework/types/attributes.ts`
17
+
18
+ To customize a built-in model, create the same filename under `app/Models/` -
19
+ `app/Models/User.ts` wins over the default. `buddy publish:model User` copies the
20
+ default across as a starting point.
21
+
22
+ ## Writing a model
23
+
24
+ Everything - schema, validation, factory, relationships, behavior - is declared
25
+ in one `defineModel()` call. Migrations are derived from this; you do not write
26
+ the SQL.
27
+
28
+ ```ts
29
+ // app/Models/Product.ts
30
+ import { defineModel } from '@stacksjs/orm'
31
+ import { schema } from '@stacksjs/validation'
32
+
33
+ export default defineModel({
34
+ name: 'Product', // defaults to the file name
35
+ table: 'products', // defaults to lowercase plural of `name`
36
+ primaryKey: 'id', // default
37
+ autoIncrement: true, // default
38
+
39
+ traits: {
40
+ useUuid: true,
41
+ useTimestamps: true,
42
+ useApi: { uri: 'products', routes: ['index', 'store', 'show', 'update', 'destroy'] },
43
+ useSearch: { searchable: ['name'], filterable: ['status'] },
44
+ observe: true,
45
+ },
46
+
47
+ belongsTo: ['Category'],
48
+ hasMany: ['Review'],
49
+
50
+ attributes: {
51
+ name: {
52
+ required: true,
53
+ fillable: true,
54
+ order: 1,
55
+ validation: {
56
+ rule: schema.string().min(3).max(100),
57
+ message: { max: 'Name must have a maximum of 100 characters' },
58
+ },
59
+ factory: faker => faker.commerce.productName(),
60
+ },
61
+ status: {
62
+ required: true,
63
+ fillable: true,
64
+ default: 'draft',
65
+ validation: { rule: schema.enum(['draft', 'published', 'archived']) },
66
+ factory: faker => faker.helpers.arrayElement(['draft', 'published', 'archived']),
67
+ },
68
+ },
69
+ } as const)
70
+ ```
71
+
72
+ `as const` is what the built-in models use - it narrows literal types so the
73
+ generated model types stay precise.
74
+
75
+ ### Attribute fields
76
+
77
+ `validation.rule` is the only required key on an attribute.
78
+
79
+ | Field | Effect |
80
+ |---|---|
81
+ | `required` | Value required; emits a `NOT NULL` column |
82
+ | `nullable` | Explicit nullability override |
83
+ | `default` | Column default (`string \| number \| boolean \| Date`) |
84
+ | `unique` | Unique constraint |
85
+ | `type` | Force the column type instead of inferring from the rule |
86
+ | `order` | Column order in the table and in dashboard forms |
87
+ | `fillable` | Allow mass assignment |
88
+ | `guarded` | Block mass assignment |
89
+ | `hidden` | Exclude from JSON serialization (passwords, tokens) |
90
+ | `foreignKey` | Disable, infer, or configure the FK constraint |
91
+ | `factory` | `(faker) => value`, used by seeders and tests |
92
+ | `validation` | `{ rule, message? }` - `rule` from `schema`, `message` keyed by rule name |
93
+
94
+ ### Traits
95
+
96
+ | Trait | What it adds |
97
+ |---|---|
98
+ | `useUuid` | UUID column alongside the primary key |
99
+ | `useTimestamps` (alias `timestampable`) | `created_at` / `updated_at`. On by default |
100
+ | `useSoftDeletes` (alias `softDeletable`) | `deleted_at` plus soft-delete query scopes |
101
+ | `useAuth` (alias `authenticatable`) | Auth columns; `{ usePasskey: true }` adds passkeys |
102
+ | `useApi` | Generates REST actions and routes: `{ uri, routes }` |
103
+ | `useSearch` (alias `searchable`) | Search-engine indexing: `{ displayable, searchable, sortable, filterable }` |
104
+ | `useSocials` | OAuth identities, e.g. `['github']` |
105
+ | `useActivityLog` | Writes an `Activity` row per change |
106
+ | `observe` | Emits `{model}:created` / `:updated` / `:deleted` events |
107
+ | `billable` | Stripe methods (`checkout()`, `activeSubscription()`, ...) |
108
+ | `taggable` / `categorizable` / `commentable` / `likeable` | Pivot tables and their relation methods |
109
+
110
+ Also at the top level: `indexes: [{ name, columns, unique?, where? }]` for
111
+ composite and partial-unique indexes, and `dashboard: { highlight: true }` to
112
+ feature the model in the admin UI.
113
+
114
+ ### Relationships
115
+
116
+ `hasOne`, `hasMany`, `belongsTo`, `belongsToMany`, `hasOneThrough`,
117
+ `hasManyThrough`, `morphOne`, `morphMany`, `morphTo`, `morphToMany`,
118
+ `morphedByMany`. Each takes an array of model names, or an object form when you
119
+ need to name the foreign key.
120
+
121
+ ### Computed properties and scopes
122
+
123
+ ```ts
124
+ get: {
125
+ fullName: (model) => `${model.firstName} ${model.lastName}`,
126
+ },
127
+ set: {
128
+ password: (value) => makeHash(value),
129
+ },
130
+ scopes: {
131
+ published: (query) => query.where('status', 'published'),
132
+ },
133
+ ```
134
+
135
+ ## Workflow
136
+
137
+ ```sh
138
+ buddy make:model Product # scaffold app/Models/Product.ts
139
+ buddy generate:migrations # diff models against the schema, emit SQL
140
+ # review the generated file in database/migrations/
141
+ buddy migrate # apply it
142
+ buddy migrate:fresh --seed # dev only: drop, re-migrate, seed
143
+ ```
144
+
145
+ Models resolve at runtime through `createModel()` from `bun-query-builder` -
146
+ there is no build step between editing a model and querying it. Only migrations
147
+ need generating.
148
+
149
+ ## Seeding
150
+
151
+ Seed data is declared on the model, through the `useSeeder` trait plus the
152
+ per-attribute `factory` functions:
153
+
154
+ ```ts
155
+ traits: {
156
+ useSeeder: {
157
+ count: 20,
158
+ // Optional: pin specific rows over the generated ones. Keys use the
159
+ // model's camelCase attribute names.
160
+ fixtures: [
161
+ { name: 'Flagship Widget', status: 'published' },
162
+ ],
163
+ },
164
+ },
165
+ ```
166
+
167
+ `buddy seed` walks every model carrying the trait and fills its table from the
168
+ attribute factories. Nothing else is needed - no seeder files, no registration.
169
+
170
+ ```bash
171
+ buddy seed # every model with a useSeeder trait
172
+ buddy seed --fresh # truncate each table first
173
+ buddy seed --only Product,Review # just these models
174
+ buddy seed --except User # everything but these
175
+ buddy seed --include-defaults # framework built-ins too
176
+ ```
177
+
178
+ A model with no `useSeeder` trait is never seeded. Auth and OAuth models are
179
+ skipped on a non-fresh database so re-seeding cannot invalidate live sessions -
180
+ pass `--allow-protected` to override.
181
+
182
+ ## All 62 built-in models by category
183
+
184
+ ### Users & Auth
185
+ - **User** — name, email, password | traits: useAuth(passkey), useUuid, useTimestamps, useSocials(github) | hasOne: Subscriber, Driver, Author | hasMany: PersonalAccessToken, Customer
186
+ - **Author** — name, email | belongsTo: User | hasMany: Post
187
+ - **Customer** — name, email, phone, totalSpent, lastOrder, status, avatar | belongsTo: User | hasMany: Order, GiftCard, Review, Payment
188
+ - **Driver** — name, phone, vehicleNumber, license, status | belongsTo: User | hasMany: DeliveryRoute
189
+ - **Subscriber** — email, status, source | belongsTo: User | hasMany: SubscriberEmail
190
+
191
+ ### Content
192
+ - **Post** — title, content, poster, excerpt, views, publishedAt, status, isFeatured | belongsTo: Author | traits: categorizable, taggable, commentable | seeder: 20
193
+ - **Page** — similar to Post with taggable, categorizable
194
+ - **Comment** — author info, approval, content fields
195
+ - **Tag** — name(unique), slug(unique), description, postCount, color | seeder: 15
196
+ - **Category** — name, description, slug, imageUrl, isActive, parentCategoryId, displayOrder | hasMany: Product | seeder: 10
197
+
198
+ ### Commerce (20+ models)
199
+ - **Product** — name(max100), description, price(min1), imageUrl, isAvailable, inventoryCount, preparationTime, allergens(JSON), nutritionalInfo(JSON) | belongsTo: Category, Manufacturer | hasMany: Review, ProductUnit, ProductVariant, LicenseKey, WaitlistProduct, Coupon | seeder: 10, dashboard: highlighted
200
+ - **ProductVariant** — SKU, options, pricing
201
+ - **ProductUnit** — unit-specific pricing
202
+ - **Cart** — status(active|abandoned|converted|expired), totalItems, subtotal, taxAmount, discountAmount, total, expiresAt, currency(USD), notes | hasMany: CartItem | belongsTo: Customer, Coupon
203
+ - **CartItem** — quantity(min1), unitPrice, totalPrice, taxRate, taxAmount, discountPercentage, productName, productSku | belongsTo: Cart
204
+ - **Order** — status, totalAmount, taxAmount, discountAmount, deliveryFee, tipAmount, orderType(DINE_IN|TAKEOUT|DELIVERY), deliveryAddress, specialInstructions | hasMany: OrderItem, Payment | belongsTo: Customer, Coupon | observe: true | seeder: 20
205
+ - **OrderItem** — quantity(min1), price(min0), specialInstructions | belongsTo: Order, Product
206
+ - **Coupon** — code(unique), discountType(fixed_amount|percentage), discountValue, minOrderAmount, usageLimit, usageCount, startDate, endDate | seeder: 15
207
+ - **GiftCard** — code(unique), initialBalance, currentBalance, currency, status, recipientEmail, isDigital, isReloadable, expiryDate | seeder: 20
208
+ - **Manufacturer** — manufacturer info
209
+ - **Review** — rating(1-5), title, content(max2000), isVerifiedPurchase, isApproved, isFeatured, helpfulVotes, unhelpfulVotes | belongsTo: Product, Customer | seeder: 50
210
+
211
+ ### Shipping & Delivery
212
+ - **ShippingMethod**, **ShippingRate** (weightFrom, weightTo, rate), **ShippingZone**
213
+ - **DeliveryRoute** — driver, vehicle, stops, totalDistance | belongsTo: Driver
214
+ - **DigitalDelivery** — name, downloadLimit, expiryDays, automaticDelivery
215
+ - **LicenseKey** — key(XXXX-XXXX-XXXX-XXXX-XXXX), template, expiryDate, status
216
+
217
+ ### Payments & Financial
218
+ - **Payment** — amount, method(creditCard|debitCard|paypal|...), status(pending|completed|failed|refunded), currency, transactionId(unique) | belongsTo: Order, Customer | seeder: 50
219
+ - **PaymentMethod**, **PaymentProduct**, **PaymentTransaction**
220
+ - **Subscription** — type, providerId, providerStatus, unitPrice
221
+ - **Transaction** — standard transaction tracking
222
+ - **TaxRate** — name, rate(0-100), type(VAT|GST|Sales Tax|Customs Duty), country, region, isDefault
223
+
224
+ ### Engagement & Marketing
225
+ - **Notification** — type, channel, recipient, subject, body, status(pending|sent|delivered|failed|read) | belongsTo: User | seeder: 30
226
+ - **Campaign** — name, type(email|sms|push|social|multi-channel), status, audienceSize, openRate, clickRate, budget | seeder: 10
227
+ - **Activity** — type, description, subjectType, subjectId, causer, properties(JSON), ipAddress | belongsTo: User | seeder: 50
228
+ - **EmailList**, **SocialPost**, **LoyaltyPoint** (walletId, points, source, expiryDate), **LoyaltyReward**
229
+
230
+ ### System
231
+ - **Job** — queue, payload, attempts, available_at, reserved_at | seeder: 15
232
+ - **FailedJob** — failed background jobs
233
+ - **Error** — type, message, stack, status, additionalInfo | seeder: 10
234
+ - **Log** — application logs
235
+ - **Request** — method, path, statusCode, durationMs, ipAddress, memoryUsage, userAgent, errorMessage | seeder: 50
236
+ - **Websocket** — connection tracking
237
+ - **PrintDevice** — name, location, terminal, lastPing, printCount, isActive
238
+ - **WaitlistProduct**, **WaitlistRestaurant** — waitlist tracking
239
+ - **Receipt** — receipt records
240
+
241
+ ## CLI Commands
242
+ - `buddy make:model [name]` — scaffold a model in `app/Models/`
243
+ - `buddy publish:model [name]` — copy a built-in model into `app/Models/` to override it
244
+ - `buddy generate:migrations` — diff models against the schema and emit SQL
245
+ - `buddy migrate` / `buddy migrate:fresh --seed` — apply migrations
246
+ - `buddy make:migration [name]` — hand-write a migration instead
247
+ - `buddy make:factory [name]` — standalone factory
248
+ - `buddy seed` — seed every model carrying a `useSeeder` trait
249
+
250
+ ## Gotchas
251
+ - **No code generation step for models.** `defineModel()` calls `createModel()`
252
+ from bun-query-builder at runtime, so a model is queryable the moment you save
253
+ it. Only migrations are generated.
254
+ - **Migrations come from models.** Change the model, run `buddy generate:migrations`,
255
+ review the SQL, then `buddy migrate`. Editing a generated migration by hand
256
+ will be overwritten by the next diff.
257
+ - **`commentable`, not `commentables`.** `define-model` only checks the singular
258
+ key. The plural spelling used to type check while leaving the trait inert.
259
+ - **Seeding is model-declared.** `useSeeder` sets the count and fixtures; the
260
+ per-attribute `factory` functions produce the values. There are no seeder
261
+ files to write or register.
262
+ - **`hidden` is serialization, `guarded` is mass assignment.** They are different
263
+ protections; a password wants both `hidden` and no `fillable`.
264
+ - **`validation.rule` is mandatory** on every attribute - it drives both request
265
+ validation and the inferred column type.
266
+ - Dashboard-highlighted models (`dashboard: { highlight: true }`) appear
267
+ prominently in the admin UI.
@@ -0,0 +1,206 @@
1
+ ---
2
+ name: stacks-new-feature
3
+ description: Use when adding a new feature end-to-end in a Stacks application — the complete workflow from model definition through migration, action, route, test, and deployment. Covers the recommended order of operations for building features.
4
+ license: MIT
5
+ compatibility: Bun >= 1.3.0, TypeScript
6
+ allowed-tools: Read Edit Write Bash Grep Glob
7
+ ---
8
+
9
+ # Adding a New Feature to Stacks
10
+
11
+ Step-by-step guide for building features end-to-end.
12
+
13
+ ## Workflow Overview
14
+
15
+ ```
16
+ 1. Model → 2. Migration → 3. Action → 4. Route → 5. Test → 6. Lint → 7. Deploy
17
+ ```
18
+
19
+ ## Step 1: Define the Model
20
+
21
+ ```typescript
22
+ // Create or edit in storage/framework/defaults/app/Models/
23
+ import { defineModel } from '@stacksjs/orm'
24
+ import { schema } from '@stacksjs/validation'
25
+
26
+ export default defineModel({
27
+ name: 'Article',
28
+ table: 'articles',
29
+ primaryKey: 'id',
30
+ autoIncrement: true,
31
+
32
+ traits: {
33
+ useTimestamps: true,
34
+ useSearch: {
35
+ searchable: ['title', 'content'],
36
+ sortable: ['title', 'created_at'],
37
+ filterable: ['status']
38
+ },
39
+ useApi: {
40
+ uri: 'articles',
41
+ routes: ['index', 'store', 'show', 'update', 'destroy']
42
+ },
43
+ useSeeder: { count: 10 },
44
+ observe: true
45
+ },
46
+
47
+ belongsTo: ['User'],
48
+
49
+ attributes: {
50
+ title: {
51
+ fillable: true,
52
+ required: true,
53
+ validation: { rule: schema.string().maxLength(200) },
54
+ factory: (faker) => faker.lorem.sentence()
55
+ },
56
+ content: {
57
+ fillable: true,
58
+ required: true,
59
+ validation: { rule: schema.string() },
60
+ factory: (faker) => faker.lorem.paragraphs(3)
61
+ },
62
+ status: {
63
+ fillable: true,
64
+ default: 'draft',
65
+ validation: { rule: schema.enum(['draft', 'published', 'archived']) },
66
+ factory: () => 'draft'
67
+ }
68
+ },
69
+
70
+ get: {
71
+ excerpt: (attrs) => attrs.content?.substring(0, 150) + '...'
72
+ }
73
+ } as const)
74
+ ```
75
+
76
+ ## Step 2: Generate & Run Migration
77
+
78
+ ```bash
79
+ buddy generate:migrations # generate migration SQL from model diffs
80
+ buddy migrate # apply migration
81
+ buddy seed # seed with factory data
82
+ ```
83
+
84
+ ## Step 3: Create Actions
85
+
86
+ ```typescript
87
+ // app/Actions/CreateArticle.ts
88
+ export default {
89
+ name: 'CreateArticle',
90
+ description: 'Create a new article',
91
+
92
+ async handle(request: any) {
93
+ const title = request.get('title')
94
+ const content = request.get('content')
95
+ const user = await request.user()
96
+
97
+ const article = await Article.create({
98
+ title,
99
+ content,
100
+ user_id: user.id,
101
+ status: 'draft'
102
+ })
103
+
104
+ return { success: true, data: article }
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## Step 4: Define Routes
110
+
111
+ ```typescript
112
+ // routes/api.ts (add to existing)
113
+ route.group({ prefix: '/articles', middleware: ['auth'] }, () => {
114
+ route.get('/', 'Actions/ListArticles')
115
+ route.post('/', 'Actions/CreateArticle')
116
+ route.get('/{id}', 'Actions/ShowArticle')
117
+ route.put('/{id}', 'Actions/UpdateArticle')
118
+ route.delete('/{id}', 'Actions/DeleteArticle')
119
+ })
120
+ ```
121
+
122
+ Or rely on auto-generated routes from `useApi` trait — they're created automatically.
123
+
124
+ ## Step 5: Add Event Listeners (Optional)
125
+
126
+ ```typescript
127
+ // app/Events.ts — add to existing
128
+ {
129
+ 'article:created': ['NotifySubscribers'],
130
+ 'article:published': ['SendNewsletter', 'IndexInSearchEngine']
131
+ }
132
+ ```
133
+
134
+ ## Step 6: Write Tests
135
+
136
+ ```typescript
137
+ // tests/feature/articles.test.ts
138
+ import { describe, test, expect, beforeAll } from 'bun:test'
139
+ import { setupDatabase, refreshDatabase } from '@stacksjs/testing'
140
+
141
+ describe('Articles', () => {
142
+ beforeAll(async () => {
143
+ await setupDatabase()
144
+ })
145
+
146
+ test('can create an article', async () => {
147
+ const article = await Article.create({
148
+ title: 'Test Article',
149
+ content: 'Test content',
150
+ status: 'draft'
151
+ })
152
+ expect(article.title).toBe('Test Article')
153
+ })
154
+
155
+ test('can list articles', async () => {
156
+ const articles = await Article.all()
157
+ expect(articles.length).toBeGreaterThan(0)
158
+ })
159
+ })
160
+ ```
161
+
162
+ ## Step 7: Lint & Deploy
163
+
164
+ ```bash
165
+ bunx --bun pickier . --fix # lint and auto-fix
166
+ buddy test # run tests
167
+ buddy deploy # deploy to cloud
168
+ ```
169
+
170
+ ## Common Patterns
171
+
172
+ ### Adding a Dashboard View
173
+ Models with `useApi` + `dashboard: { highlight: true }` auto-appear in the admin dashboard.
174
+
175
+ ### Adding Email Notifications
176
+ ```typescript
177
+ // app/Mail/ArticlePublished.ts
178
+ export async function sendArticlePublished({ to, article }) {
179
+ const { html, text } = await template('article-published', {
180
+ variables: { title: article.title, url: `${config.app.url}/articles/${article.id}` }
181
+ })
182
+ await mail.send({ to, subject: `New: ${article.title}`, html, text })
183
+ }
184
+ ```
185
+
186
+ ### Adding Background Processing
187
+ ```typescript
188
+ // app/Jobs/IndexArticle.ts
189
+ export default new Job({
190
+ name: 'IndexArticle',
191
+ queue: 'search',
192
+ tries: 3,
193
+ async handle(payload: { articleId: number }) {
194
+ const article = await Article.find(payload.articleId)
195
+ await search.addDocuments('articles', [article])
196
+ }
197
+ })
198
+ ```
199
+
200
+ ## Gotchas
201
+ - Models work directly via the dynamic ORM — no generation step needed before migrations
202
+ - The `useApi` trait auto-generates both routes AND dashboard views
203
+ - Model events (observe: true) emit `article:created`, `article:updated`, `article:deleted`
204
+ - Factories in model attributes are used by `buddy seed`
205
+ - Always lint after code generation: `bunx --bun pickier . --fix`
206
+ - Use conventional commits: `feat: add article management`
@@ -0,0 +1,210 @@
1
+ ---
2
+ name: stacks-notifications
3
+ description: Use when implementing notifications in Stacks — multi-channel notifications (email, SMS, push, chat, database), the database notification driver with read/unread tracking, notification factories (useEmail, useSMS, useChat, useDatabase), or notification configuration. Covers @stacksjs/notifications and config/notification.ts.
4
+ license: MIT
5
+ compatibility: Bun >= 1.3.0, TypeScript
6
+ allowed-tools: Read Edit Write Bash Grep Glob
7
+ ---
8
+
9
+ # Stacks Notifications
10
+
11
+ Multi-channel notification system with 5 channel types: email, SMS, chat, push, and database.
12
+
13
+ ## Key Paths
14
+ - Core package: `storage/framework/core/notifications/src/`
15
+ - Main entry: `storage/framework/core/notifications/src/index.ts`
16
+ - Drivers: `storage/framework/core/notifications/src/drivers/`
17
+ - Database driver: `storage/framework/core/notifications/src/drivers/database.ts`
18
+ - Configuration: `config/notification.ts`
19
+ - Notification model: `storage/framework/defaults/app/Models/Notification.ts`
20
+
21
+ ## Package Exports
22
+
23
+ ```typescript
24
+ import {
25
+ useChat,
26
+ useEmail,
27
+ useSMS,
28
+ useDatabase,
29
+ useNotification,
30
+ notification,
31
+ DatabaseNotificationDriver,
32
+ } from '@stacksjs/notifications'
33
+
34
+ // Types
35
+ import type { CreateNotificationOptions, DatabaseNotification } from '@stacksjs/notifications'
36
+ ```
37
+
38
+ ## Channel Factories
39
+
40
+ Each factory returns the underlying driver module for that channel.
41
+
42
+ ```typescript
43
+ // Email -- defaults to 'mailtrap', returns @stacksjs/email driver
44
+ const emailDriver = useEmail('ses')
45
+ const emailDriver = useEmail('sendgrid')
46
+ const emailDriver = useEmail('mailgun')
47
+ const emailDriver = useEmail('mailtrap')
48
+ const emailDriver = useEmail('smtp')
49
+
50
+ // SMS -- defaults to 'twilio', returns @stacksjs/sms driver
51
+ const smsDriver = useSMS('twilio')
52
+ const smsDriver = useSMS('vonage')
53
+
54
+ // Chat -- defaults to 'slack', returns @stacksjs/chat driver
55
+ const chatDriver = useChat('slack')
56
+ const chatDriver = useChat('discord')
57
+ const chatDriver = useChat('teams')
58
+
59
+ // Database -- returns DatabaseNotificationDriver object
60
+ const dbDriver = useDatabase()
61
+
62
+ // Auto-detect by type -- dispatches to the correct factory
63
+ const driver = useNotification('email', 'ses')
64
+ const driver = useNotification('sms', 'twilio')
65
+ const driver = useNotification('chat', 'slack')
66
+ const driver = useNotification('database')
67
+
68
+ // Default (uses config.default, falls back to 'email' + 'mailtrap')
69
+ const driver = notification()
70
+ ```
71
+
72
+ `useNotification()` reads `config/notification.ts` for the default type. If no default is set, it throws `'No default notification type set in config/notification.ts'`.
73
+
74
+ The channel drivers are re-exports from their respective packages:
75
+ - `email` driver: `@stacksjs/email`
76
+ - `sms` driver: `@stacksjs/sms`
77
+ - `chat` driver: `@stacksjs/chat`
78
+ - `push` driver: `@stacksjs/push`
79
+
80
+ ## Database Notification Driver
81
+
82
+ The `DatabaseNotificationDriver` provides CRUD operations for notifications stored in the `notifications` database table using Kysely query builder.
83
+
84
+ ### Send a Notification
85
+
86
+ ```typescript
87
+ const db = useDatabase()
88
+
89
+ const notification = await db.send({
90
+ userId: 1,
91
+ type: 'order.shipped',
92
+ data: { orderId: 42, trackingNumber: 'ABC123' },
93
+ })
94
+ // Returns the created DatabaseNotification with auto-generated id, timestamps
95
+ ```
96
+
97
+ `send()` inserts a row into the `notifications` table with:
98
+ - `user_id` from `options.userId`
99
+ - `type` from `options.type`
100
+ - `data` -- JSON.stringify'd from `options.data`
101
+ - `read_at` set to `null`
102
+ - `created_at` and `updated_at` set to current ISO timestamp
103
+
104
+ ### Query Notifications
105
+
106
+ ```typescript
107
+ // All notifications for a user, ordered by created_at desc
108
+ const all = await db.getUserNotifications(userId)
109
+
110
+ // Only unread (where read_at is null), ordered by created_at desc
111
+ const unread = await db.getUnreadNotifications(userId)
112
+
113
+ // Count of unread notifications
114
+ const count = await db.unreadCount(userId)
115
+ ```
116
+
117
+ ### Mark as Read
118
+
119
+ ```typescript
120
+ // Mark a single notification as read (sets read_at to current timestamp)
121
+ await db.markAsRead(notificationId)
122
+
123
+ // Mark all unread notifications for a user as read
124
+ await db.markAllAsRead(userId)
125
+ ```
126
+
127
+ `markAllAsRead()` only updates rows where `read_at` is null.
128
+
129
+ ### Delete Notifications
130
+
131
+ ```typescript
132
+ // Delete a single notification by ID
133
+ await db.deleteNotification(notificationId)
134
+
135
+ // Delete all notifications for a user
136
+ await db.deleteAllNotifications(userId)
137
+ ```
138
+
139
+ ### DatabaseNotification Interface
140
+
141
+ ```typescript
142
+ interface DatabaseNotification {
143
+ id: number
144
+ user_id: number
145
+ type: string // e.g., 'order.shipped', 'payment.received'
146
+ data: string // JSON stringified -- parse with JSON.parse() when reading
147
+ read_at: string | null // ISO timestamp or null if unread
148
+ created_at: string // ISO timestamp
149
+ updated_at: string | null // ISO timestamp
150
+ }
151
+ ```
152
+
153
+ ### CreateNotificationOptions Interface
154
+
155
+ ```typescript
156
+ interface CreateNotificationOptions {
157
+ userId: number
158
+ type: string
159
+ data: Record<string, any>
160
+ }
161
+ ```
162
+
163
+ ## Notification Model Fields
164
+
165
+ The Notification model (at `storage/framework/defaults/app/Models/Notification.ts`) defines:
166
+ - `type` -- notification type: email, sms, push, slack, webhook
167
+ - `channel` -- delivery channel
168
+ - `recipient` -- target email, phone, or user
169
+ - `subject` -- notification subject line
170
+ - `body` -- notification body content
171
+ - `status` -- pending, sent, delivered, failed, read
172
+ - `readAt`, `sentAt`, `metadata`
173
+
174
+ Note: The Notification model uses 30 seeded records by default.
175
+
176
+ ## CLI Commands
177
+ - `buddy make:notification [name]` -- scaffold a new notification
178
+
179
+ ## config/notification.ts
180
+
181
+ ```typescript
182
+ import type { NotificationConfig } from '@stacksjs/types'
183
+
184
+ export default {
185
+ default: 'email',
186
+ } satisfies NotificationConfig
187
+ ```
188
+
189
+ The `default` field controls which channel type `useNotification()` and `notification()` use when no type is specified. Valid values: `'email'`, `'sms'`, `'chat'`, `'database'`.
190
+
191
+ ## Architecture
192
+
193
+ The notifications package is a thin aggregation layer. Each channel delegates to its own dedicated package:
194
+
195
+ - **Email channel** (`useEmail`) -- re-exports `@stacksjs/email` (configured via `config/email.ts`)
196
+ - **SMS channel** (`useSMS`) -- re-exports `@stacksjs/sms` (configured via `config/sms.ts`)
197
+ - **Chat channel** (`useChat`) -- re-exports `@stacksjs/chat` (configured via `config/services.ts`)
198
+ - **Push channel** -- re-exports `@stacksjs/push`
199
+ - **Database channel** (`useDatabase`) -- built-in driver using `@stacksjs/database`
200
+
201
+ The driver modules (`drivers/email.ts`, `drivers/sms.ts`, etc.) are single-line re-exports: `export * as email from '@stacksjs/email'`, `export * as sms from '@stacksjs/sms'`, etc.
202
+
203
+ ## Gotchas
204
+ - The `data` field in database notifications is stored as a JSON string -- always `JSON.parse()` when reading
205
+ - `read_at` is `null` for unread notifications -- use this to filter unread
206
+ - The database driver uses Kysely's query builder with `as any` type casts on table/column names since the notifications table is dynamically referenced
207
+ - Channel-specific configuration (SMTP credentials, Twilio keys, Slack tokens) lives in each channel's own config file, not in `config/notification.ts`
208
+ - `useNotification()` throws if `config.default` is not set in `config/notification.ts`
209
+ - The `notification()` function (without arguments) is a shorthand for `useNotification()` with defaults
210
+ - The `nexmo` driver is a legacy alias for `vonage` in the SMS drivers index