@stacksjs/defaults 0.70.207 โ†’ 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,261 @@
1
+ @extends('layouts/default')
2
+
3
+ @section('content')
4
+ @title('Dashboard - Activity Log')
5
+ <div class="p-6 space-y-6">
6
+ <div class="flex items-center justify-between">
7
+ <PageHeader title="Activity Log" description="Audit trail of recent activity" />
8
+ <div class="flex gap-2 items-center">
9
+ <button @click="toggleAutoRefresh()" class="{{ autoRefreshButtonClass }}">
10
+ <div class="mr-2 h-4 w-4 i-hugeicons-refresh"></div>
11
+ {{ autoRefreshLabel }}
12
+ </button>
13
+ </div>
14
+ </div>
15
+
16
+ <div class="flex flex-col gap-4 sm:flex-row sm:items-center">
17
+ <div class="relative max-w-sm">
18
+ <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
19
+ <div class="h-5 w-5 text-gray-400 i-hugeicons-search-01"></div>
20
+ </div>
21
+ <input x-model="searchTerm" type="text" class="block pl-10 pr-3 py-1.5 w-full text-gray-900 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600" placeholder="Search activity..." />
22
+ </div>
23
+ <select x-model="logNameFilter" class="block pl-3 pr-10 py-1.5 text-gray-900 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600">
24
+ <option value="all">All Channels</option>
25
+ <template :for="ln in logNames">
26
+ <option :value="ln.id">{{ ln.name }}</option>
27
+ </template>
28
+ </select>
29
+ <select x-model="eventFilter" class="block pl-3 pr-10 py-1.5 text-gray-900 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600">
30
+ <template :for="ev in eventTypes">
31
+ <option :value="ev">{{ ev === 'all' ? 'All Events' : ev.charAt(0).toUpperCase() + ev.slice(1) }}</option>
32
+ </template>
33
+ </select>
34
+ </div>
35
+
36
+ <div class="overflow-x-auto border border-gray-200 rounded-lg dark:border-neutral-700 shadow">
37
+ <table class="min-w-full divide-gray-200 divide-y dark:divide-neutral-700">
38
+ <thead class="bg-gray-50 dark:bg-neutral-700/50">
39
+ <tr>
40
+ <th class="px-4 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-white">When</th>
41
+ <th class="px-4 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-white">Causer</th>
42
+ <th class="px-4 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-white">Channel</th>
43
+ <th class="px-4 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-white">Event</th>
44
+ <th class="px-4 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-white">Description</th>
45
+ <th class="relative px-4 py-3.5"><span class="sr-only">Actions</span></th>
46
+ </tr>
47
+ </thead>
48
+ <tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
49
+ <template :for="log in paginatedLogs">
50
+ <tr class="hover:bg-gray-50 dark:hover:bg-neutral-700">
51
+ <td class="px-4 py-3 whitespace-nowrap"><div class="text-gray-500 text-xs dark:text-neutral-400">{{ formatDate(log.created_at) }}</div></td>
52
+ <td class="px-4 py-3 whitespace-nowrap">
53
+ <div class="flex gap-2 items-center">
54
+ <img :show="log.causer?.avatar" :src="log.causer?.avatar" alt="" class="h-6 w-6 rounded-full" />
55
+ <div class="font-medium text-gray-900 text-sm dark:text-white">{{ log.causer?.name ?? 'System' }}</div>
56
+ </div>
57
+ </td>
58
+ <td class="px-4 py-3 whitespace-nowrap"><span class="{{ logNameBadgeClass(log.log_name) }}">{{ log.log_name }}</span></td>
59
+ <td class="px-4 py-3 whitespace-nowrap"><span class="{{ eventBadgeClass(log.event) }}">{{ log.event }}</span></td>
60
+ <td class="px-4 py-3"><div class="max-w-md text-gray-700 text-sm dark:text-neutral-300">{{ log.description }}</div></td>
61
+ <td class="px-4 py-3 font-medium text-right text-sm whitespace-nowrap">
62
+ <button @click="openLog(log)" class="text-blue-600 hover:text-blue-500">View</button>
63
+ </td>
64
+ </tr>
65
+ </template>
66
+ <tr :show="paginatedLogs().length === 0">
67
+ <td colspan="6" class="px-4 py-8 text-center text-gray-500 text-sm dark:text-neutral-400">No activity found.</td>
68
+ </tr>
69
+ </tbody>
70
+ </table>
71
+ </div>
72
+
73
+ <div :show="totalPages() > 1" class="flex items-center justify-between">
74
+ <p class="text-gray-700 text-sm dark:text-neutral-300">Page {{ currentPage }} of {{ totalPages }}</p>
75
+ <nav class="inline-flex -space-x-px rounded-md shadow-sm">
76
+ <button @click="prevPage()" :disabled="currentPage() === 1" class="inline-flex relative items-center px-2 py-2 text-gray-400 dark:text-neutral-500 hover:bg-gray-50 dark:hover:bg-neutral-700 ring-1 ring-gray-300 ring-inset rounded-l-md dark:ring-neutral-600 disabled:opacity-50">
77
+ <div class="h-5 w-5 i-hugeicons-arrow-left-01"></div>
78
+ </button>
79
+ <button @click="nextPage()" :disabled="currentPage() === totalPages()" class="inline-flex relative items-center px-2 py-2 text-gray-400 dark:text-neutral-500 hover:bg-gray-50 dark:hover:bg-neutral-700 ring-1 ring-gray-300 ring-inset rounded-r-md dark:ring-neutral-600 disabled:opacity-50">
80
+ <div class="h-5 w-5 i-hugeicons-arrow-right-01"></div>
81
+ </button>
82
+ </nav>
83
+ </div>
84
+
85
+ <div :show="selectedLog() !== null" class="relative z-10">
86
+ <div class="fixed inset-0 bg-gray-500 bg-opacity-75 dark:bg-neutral-900 dark:bg-opacity-75"></div>
87
+ <div class="fixed inset-0 overflow-y-auto z-10">
88
+ <div class="flex items-end justify-center sm:items-center p-4 min-h-full">
89
+ <div class="overflow-hidden relative pb-4 pt-5 px-4 sm:p-6 sm:max-w-2xl sm:w-full bg-white dark:bg-neutral-800 rounded-lg shadow-xl">
90
+ <h3 class="font-semibold leading-6 text-base text-gray-900 dark:text-white">Activity Detail</h3>
91
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">{{ selectedLog()?.description }}</p>
92
+ <dl class="grid gap-3 grid-cols-2 mt-4 text-sm">
93
+ <div>
94
+ <dt class="font-medium text-gray-500 dark:text-neutral-400">When</dt>
95
+ <dd class="mt-1 text-gray-900 dark:text-white">{{ formatDate(selectedLog()?.created_at ?? '') }}</dd>
96
+ </div>
97
+ <div>
98
+ <dt class="font-medium text-gray-500 dark:text-neutral-400">Channel</dt>
99
+ <dd class="mt-1 text-gray-900 dark:text-white">{{ selectedLog()?.log_name }}</dd>
100
+ </div>
101
+ <div>
102
+ <dt class="font-medium text-gray-500 dark:text-neutral-400">Event</dt>
103
+ <dd class="mt-1 text-gray-900 dark:text-white">{{ selectedLog()?.event }}</dd>
104
+ </div>
105
+ <div>
106
+ <dt class="font-medium text-gray-500 dark:text-neutral-400">Subject</dt>
107
+ <dd class="mt-1 text-gray-900 dark:text-white">{{ selectedLog()?.subject_type }} #{{ selectedLog()?.subject_id }}</dd>
108
+ </div>
109
+ </dl>
110
+ <pre class="overflow-auto mt-4 p-3 max-h-64 font-mono text-gray-800 text-xs dark:text-neutral-200 bg-gray-50 dark:bg-neutral-900 rounded">{{ selectedLogJSON }}</pre>
111
+ <div class="flex justify-end mt-5">
112
+ <button @click="closeLog()" class="inline-flex justify-center px-3 py-2 font-semibold text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-700 hover:bg-gray-50 dark:hover:bg-neutral-600 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-600 shadow-sm">Close</button>
113
+ </div>
114
+ </div>
115
+ </div>
116
+ </div>
117
+ </div>
118
+ </div>
119
+
120
+ <script client>
121
+ // Filter options โ€” moved out of the former `<script server>` block
122
+ // (stacksjs/stacks#1838).
123
+ const logNames = [
124
+ { id: 'default', name: 'Default' },
125
+ { id: 'auth', name: 'Authentication' },
126
+ { id: 'users', name: 'Users' },
127
+ { id: 'posts', name: 'Posts' },
128
+ { id: 'comments', name: 'Comments' },
129
+ { id: 'media', name: 'Media' },
130
+ { id: 'deployment', name: 'Deployment' },
131
+ { id: 'server', name: 'Server' },
132
+ { id: 'commerce', name: 'Commerce' },
133
+ { id: 'blog', name: 'Blog' },
134
+ ]
135
+
136
+ const eventTypes = ['all', 'created', 'updated', 'deleted', 'restored']
137
+
138
+ interface ActivityLog {
139
+ id: string
140
+ log_name: string
141
+ description: string
142
+ subject_type: string
143
+ subject_id: string
144
+ event: string
145
+ causer?: { name: string, avatar?: string }
146
+ properties?: Record<string, unknown>
147
+ created_at: string
148
+ }
149
+
150
+ const sampleLogs: ActivityLog[] = [
151
+ { id: '1', log_name: 'auth', description: 'User logged in', subject_type: 'User', subject_id: '1', event: 'created', causer: { name: 'Chris Breuer', avatar: 'https://i.pravatar.cc/150?u=chris' }, created_at: new Date(Date.now() - 1000 * 60 * 5).toISOString() },
152
+ { id: '2', log_name: 'posts', description: 'Created post "10 Tips for Better Code"', subject_type: 'Post', subject_id: '12', event: 'created', causer: { name: 'Jane Smith', avatar: 'https://i.pravatar.cc/150?u=jane' }, created_at: new Date(Date.now() - 1000 * 60 * 30).toISOString() },
153
+ { id: '3', log_name: 'deployment', description: 'Deployed v1.4.2 to production', subject_type: 'Deployment', subject_id: '88', event: 'created', causer: { name: 'System' }, created_at: new Date(Date.now() - 1000 * 60 * 60 * 2).toISOString() },
154
+ { id: '4', log_name: 'comments', description: 'Approved comment from Sarah Williams', subject_type: 'Comment', subject_id: '40', event: 'updated', causer: { name: 'Chris Breuer', avatar: 'https://i.pravatar.cc/150?u=chris' }, created_at: new Date(Date.now() - 1000 * 60 * 60 * 6).toISOString() },
155
+ { id: '5', log_name: 'users', description: 'Updated profile settings', subject_type: 'User', subject_id: '2', event: 'updated', causer: { name: 'John Doe', avatar: 'https://i.pravatar.cc/150?u=john' }, created_at: new Date(Date.now() - 1000 * 60 * 60 * 12).toISOString() },
156
+ { id: '6', log_name: 'media', description: 'Uploaded 4 images to /Images', subject_type: 'Media', subject_id: '102', event: 'created', causer: { name: 'Jane Smith', avatar: 'https://i.pravatar.cc/150?u=jane' }, created_at: new Date(Date.now() - 1000 * 60 * 60 * 18).toISOString() },
157
+ { id: '7', log_name: 'commerce', description: 'Order #1024 placed', subject_type: 'Order', subject_id: '1024', event: 'created', causer: { name: 'John Doe', avatar: 'https://i.pravatar.cc/150?u=john' }, created_at: new Date(Date.now() - 1000 * 60 * 60 * 26).toISOString() },
158
+ { id: '8', log_name: 'auth', description: 'User logged out', subject_type: 'User', subject_id: '2', event: 'deleted', causer: { name: 'John Doe', avatar: 'https://i.pravatar.cc/150?u=john' }, created_at: new Date(Date.now() - 1000 * 60 * 60 * 36).toISOString() },
159
+ { id: '9', log_name: 'server', description: 'Restarted node-1', subject_type: 'Server', subject_id: 'node-1', event: 'updated', causer: { name: 'System' }, created_at: new Date(Date.now() - 1000 * 60 * 60 * 48).toISOString() },
160
+ { id: '10', log_name: 'blog', description: 'Published post "STX Tips"', subject_type: 'Post', subject_id: '88', event: 'updated', causer: { name: 'Jane Smith', avatar: 'https://i.pravatar.cc/150?u=jane' }, created_at: new Date(Date.now() - 1000 * 60 * 60 * 72).toISOString() },
161
+ ]
162
+
163
+ const logs = state<ActivityLog[]>(sampleLogs)
164
+ const searchTerm = state('')
165
+ const logNameFilter = state<'all' | string>('all')
166
+ const eventFilter = state<'all' | string>('all')
167
+ const currentPage = state(1)
168
+ const itemsPerPage = state(10)
169
+ const autoRefresh = state(true)
170
+ const selectedLog = state<ActivityLog | null>(null)
171
+
172
+ const filteredLogs = derived(() => {
173
+ let list = [...logs()]
174
+ if (logNameFilter() !== 'all')
175
+ list = list.filter(l => l.log_name === logNameFilter())
176
+ if (eventFilter() !== 'all')
177
+ list = list.filter(l => l.event === eventFilter())
178
+ const q = searchTerm().toLowerCase()
179
+ if (q) {
180
+ list = list.filter(l =>
181
+ l.description.toLowerCase().includes(q)
182
+ || l.subject_type.toLowerCase().includes(q)
183
+ || (l.causer?.name ?? '').toLowerCase().includes(q),
184
+ )
185
+ }
186
+ return list.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
187
+ })
188
+
189
+ const totalPages = derived(() => Math.max(1, Math.ceil(filteredLogs().length / itemsPerPage())))
190
+ const paginatedLogs = derived(() => {
191
+ const start = (currentPage() - 1) * itemsPerPage()
192
+ return filteredLogs().slice(start, start + itemsPerPage())
193
+ })
194
+
195
+ const autoRefreshLabel = derived(() => autoRefresh() ? 'Auto Refresh: On' : 'Auto Refresh: Off')
196
+ const autoRefreshButtonClass = derived(() => autoRefresh()
197
+ ? 'inline-flex items-center px-3 py-1.5 font-semibold text-sm text-white bg-green-600 hover:bg-green-500 rounded-md shadow-sm'
198
+ : 'inline-flex items-center px-3 py-1.5 font-semibold text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-700 hover:bg-gray-50 dark:hover:bg-neutral-600 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-600 shadow-sm')
199
+
200
+ const selectedLogJSON = derived(() => {
201
+ const log = selectedLog()
202
+ return log ? JSON.stringify(log, null, 2) : ''
203
+ })
204
+
205
+ function formatDate(s: string) {
206
+ if (!s)
207
+ return ''
208
+ return new Date(s).toLocaleString()
209
+ }
210
+
211
+ function logNameBadgeClass(name: string) {
212
+ const base = 'inline-flex items-center px-2 py-0.5 font-medium text-xs rounded-full'
213
+ const map: Record<string, string> = {
214
+ auth: `${base} bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-200`,
215
+ users: `${base} bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200`,
216
+ posts: `${base} bg-pink-100 text-pink-800 dark:bg-pink-900 dark:text-pink-200`,
217
+ comments: `${base} bg-rose-100 text-rose-800 dark:bg-rose-900 dark:text-rose-200`,
218
+ media: `${base} bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-200`,
219
+ deployment: `${base} bg-emerald-100 text-emerald-800 dark:bg-emerald-900 dark:text-emerald-200`,
220
+ server: `${base} bg-cyan-100 text-cyan-800 dark:bg-cyan-900 dark:text-cyan-200`,
221
+ commerce: `${base} bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200`,
222
+ blog: `${base} bg-violet-100 text-violet-800 dark:bg-violet-900 dark:text-violet-200`,
223
+ }
224
+ return map[name] ?? `${base} bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200`
225
+ }
226
+
227
+ function eventBadgeClass(ev: string) {
228
+ const base = 'inline-flex items-center px-2 py-0.5 font-medium text-xs rounded'
229
+ switch (ev) {
230
+ case 'created': return `${base} bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200`
231
+ case 'updated': return `${base} bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200`
232
+ case 'deleted': return `${base} bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200`
233
+ case 'restored': return `${base} bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200`
234
+ default: return `${base} bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200`
235
+ }
236
+ }
237
+
238
+ function toggleAutoRefresh() {
239
+ autoRefresh.set(!autoRefresh())
240
+ }
241
+
242
+ function openLog(log: ActivityLog) {
243
+ selectedLog.set(log)
244
+ }
245
+
246
+ function closeLog() {
247
+ selectedLog.set(null)
248
+ }
249
+
250
+ function nextPage() {
251
+ if (currentPage() < totalPages())
252
+ currentPage.set(currentPage() + 1)
253
+ }
254
+
255
+ function prevPage() {
256
+ if (currentPage() > 1)
257
+ currentPage.set(currentPage() - 1)
258
+ }
259
+ </script>
260
+
261
+ @endsection
@@ -0,0 +1,116 @@
1
+ @extends('layouts/default')
2
+
3
+ @section('content')
4
+ @title('Dashboard - Data Models')
5
+ <div class="p-6 space-y-6">
6
+ <div class="flex items-center justify-between">
7
+ <PageHeader title="Data Models" description="Browse all models and their relationships" />
8
+ </div>
9
+
10
+ <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
11
+ <div class="relative max-w-sm">
12
+ <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
13
+ <div class="h-5 w-5 text-gray-400 i-hugeicons-search-01"></div>
14
+ </div>
15
+ <input x-model="searchQuery" type="text" class="block pl-10 pr-3 py-1.5 w-full text-gray-900 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600" placeholder="Search models..." />
16
+ </div>
17
+ <select x-model="selectedCategory" class="block pl-3 pr-10 py-1.5 text-gray-900 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600">
18
+ <template :for="cat in categories">
19
+ <option :value="cat">{{ cat }}</option>
20
+ </template>
21
+ </select>
22
+ </div>
23
+
24
+ <div class="grid gap-5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
25
+ <template :for="model in filteredModels">
26
+ <div class="overflow-hidden p-6 bg-white dark:bg-neutral-800 rounded-lg shadow">
27
+ <div class="flex gap-3 items-center">
28
+ <span class="text-3xl">{{ model.emoji }}</span>
29
+ <div>
30
+ <h3 class="font-semibold text-gray-900 dark:text-white">{{ model.name }}</h3>
31
+ <span class="text-gray-500 text-xs dark:text-neutral-400">{{ model.category }}</span>
32
+ </div>
33
+ </div>
34
+ <div class="mt-4">
35
+ <h4 class="font-medium text-gray-700 text-xs tracking-wider uppercase dark:text-neutral-300">Properties</h4>
36
+ <ul class="mt-2 space-y-1">
37
+ <template :for="prop in model.properties">
38
+ <li class="flex items-center justify-between font-mono text-xs">
39
+ <span class="text-gray-700 dark:text-neutral-300">{{ prop.name }}</span>
40
+ <span class="text-gray-500 dark:text-neutral-400">{{ prop.type }}</span>
41
+ </li>
42
+ </template>
43
+ </ul>
44
+ </div>
45
+ <div class="mt-4">
46
+ <h4 class="font-medium text-gray-700 text-xs tracking-wider uppercase dark:text-neutral-300">Relationships</h4>
47
+ <ul class="mt-2 space-y-1">
48
+ <template :for="rel in model.relationships">
49
+ <li class="flex items-center justify-between text-xs">
50
+ <span class="text-gray-500 dark:text-neutral-400">{{ rel.type }}</span>
51
+ <span class="font-medium text-blue-600 dark:text-blue-400">{{ rel.model }}</span>
52
+ </li>
53
+ </template>
54
+ </ul>
55
+ </div>
56
+ <a :href="modelRoute(model.id)" class="block mt-4 px-4 py-2 w-full font-semibold text-center text-sm text-white bg-blue-600 hover:bg-blue-500 rounded-md shadow-sm">View Details</a>
57
+ </div>
58
+ </template>
59
+ <div :show="filteredModels().length === 0" class="col-span-full px-4 py-12 text-center text-gray-500 text-sm dark:text-neutral-400">No models match your filter.</div>
60
+ </div>
61
+ </div>
62
+
63
+ <script client>
64
+ interface ModelNode {
65
+ id: string
66
+ name: string
67
+ emoji: string
68
+ category: string
69
+ properties: Array<{ name: string, type: string, nullable: boolean }>
70
+ relationships: Array<{ type: string, model: string }>
71
+ color: string
72
+ }
73
+
74
+ // Category filter options + model relationship graph โ€” moved out of the
75
+ // former `<script server>` block (stacksjs/stacks#1838).
76
+ const categories = ['All', 'Authentication', 'Content', 'Communication', 'Commerce', 'Other']
77
+
78
+ const initialModels: ModelNode[] = [
79
+ { id: 'user', name: 'User', emoji: '๐Ÿ‘ค', category: 'Authentication', color: '#2563EB', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'name', type: 'string', nullable: false }, { name: 'email', type: 'string', nullable: false }, { name: 'password', type: 'string', nullable: false }, { name: 'created_at', type: 'timestamp', nullable: true }], relationships: [{ type: 'hasOne', model: 'Subscriber' }, { type: 'hasMany', model: 'Deployment' }, { type: 'hasMany', model: 'Post' }, { type: 'belongsToMany', model: 'Team' }] },
80
+ { id: 'team', name: 'Team', emoji: '๐Ÿ‘ฅ', category: 'Authentication', color: '#2563EB', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'name', type: 'string', nullable: false }, { name: 'owner_id', type: 'bigInteger', nullable: false }], relationships: [{ type: 'belongsToMany', model: 'User' }, { type: 'hasMany', model: 'AccessToken' }] },
81
+ { id: 'post', name: 'Post', emoji: '๐Ÿ“', category: 'Content', color: '#DB2777', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'title', type: 'string', nullable: false }, { name: 'content', type: 'text', nullable: false }, { name: 'user_id', type: 'bigInteger', nullable: false }], relationships: [{ type: 'belongsTo', model: 'User' }] },
82
+ { id: 'subscriber', name: 'Subscriber', emoji: '๐Ÿ“ซ', category: 'Communication', color: '#0D9488', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'email', type: 'string', nullable: false }, { name: 'status', type: 'string', nullable: false }], relationships: [{ type: 'hasMany', model: 'SubscriberEmail' }, { type: 'belongsTo', model: 'User' }] },
83
+ { id: 'subscriberEmail', name: 'SubscriberEmail', emoji: 'โœ‰๏ธ', category: 'Communication', color: '#0D9488', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'email', type: 'string', nullable: false }, { name: 'subscriber_id', type: 'bigInteger', nullable: false }], relationships: [{ type: 'belongsTo', model: 'Subscriber' }] },
84
+ { id: 'accessToken', name: 'AccessToken', emoji: '๐Ÿ”‘', category: 'Authentication', color: '#2563EB', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'token', type: 'string', nullable: false }, { name: 'user_id', type: 'bigInteger', nullable: false }], relationships: [{ type: 'belongsTo', model: 'User' }, { type: 'belongsTo', model: 'Team' }] },
85
+ { id: 'deployment', name: 'Deployment', emoji: '๐Ÿš€', category: 'Other', color: '#4B5563', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'project_id', type: 'bigInteger', nullable: false }, { name: 'user_id', type: 'bigInteger', nullable: false }], relationships: [{ type: 'belongsTo', model: 'Project' }, { type: 'belongsTo', model: 'User' }] },
86
+ { id: 'project', name: 'Project', emoji: '๐Ÿ“', category: 'Other', color: '#4B5563', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'name', type: 'string', nullable: false }], relationships: [{ type: 'hasMany', model: 'Deployment' }, { type: 'hasMany', model: 'Release' }] },
87
+ { id: 'release', name: 'Release', emoji: '๐Ÿท๏ธ', category: 'Other', color: '#4B5563', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'project_id', type: 'bigInteger', nullable: false }, { name: 'version', type: 'string', nullable: false }], relationships: [{ type: 'belongsTo', model: 'Project' }] },
88
+ { id: 'order', name: 'Order', emoji: '๐Ÿ›’', category: 'Commerce', color: '#7E22CE', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'user_id', type: 'bigInteger', nullable: false }, { name: 'total', type: 'decimal', nullable: false }], relationships: [{ type: 'belongsTo', model: 'User' }, { type: 'hasMany', model: 'OrderItem' }] },
89
+ { id: 'orderItem', name: 'OrderItem', emoji: '๐Ÿงพ', category: 'Commerce', color: '#7E22CE', properties: [{ name: 'id', type: 'bigInteger', nullable: false }, { name: 'order_id', type: 'bigInteger', nullable: false }, { name: 'product_id', type: 'bigInteger', nullable: false }], relationships: [{ type: 'belongsTo', model: 'Order' }] },
90
+ ]
91
+
92
+ const searchQuery = state('')
93
+ const selectedCategory = state('All')
94
+
95
+ const filteredModels = derived(() => {
96
+ const q = searchQuery().toLowerCase()
97
+ return initialModels.filter((m) => {
98
+ const matchesSearch = q === '' || m.name.toLowerCase().includes(q) || m.properties.some(p => p.name.toLowerCase().includes(q))
99
+ const matchesCategory = selectedCategory() === 'All' || m.category === selectedCategory()
100
+ return matchesSearch && matchesCategory
101
+ })
102
+ })
103
+
104
+ function modelRoute(id: string) {
105
+ const map: Record<string, string> = {
106
+ user: '/models/users', team: '/models/teams', post: '/models/posts',
107
+ subscriber: '/models/subscribers', subscriberEmail: '/models/subscriber-emails',
108
+ accessToken: '/models/access-tokens', deployment: '/models/deployments',
109
+ project: '/models/projects', release: '/models/releases',
110
+ order: '/models/orders', orderItem: '/models/order-items',
111
+ }
112
+ return map[id] || '/models'
113
+ }
114
+ </script>
115
+
116
+ @endsection