devstack 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1450) hide show
  1. package/README.md +253 -0
  2. package/bin/audit-template-deps.ts +267 -0
  3. package/bin/cli.ts +5 -0
  4. package/bin/validate-tanstack-scaffold.ts +67 -0
  5. package/package.json +85 -0
  6. package/src/builders/index.ts +1 -0
  7. package/src/builders/separated.ts +1 -0
  8. package/src/builders/shared.ts +608 -0
  9. package/src/builders/tanstack-start.ts +2683 -0
  10. package/src/builders/types.ts +10 -0
  11. package/src/cli.ts +106 -0
  12. package/src/generator.ts +2946 -0
  13. package/src/index.ts +23 -0
  14. package/src/modules/auth.ts +33 -0
  15. package/src/modules/email.ts +38 -0
  16. package/src/modules/index.ts +30 -0
  17. package/src/modules/inngest.ts +58 -0
  18. package/src/modules/observability.ts +30 -0
  19. package/src/modules/organizations.ts +23 -0
  20. package/src/modules/redis.ts +35 -0
  21. package/src/modules/storage.ts +39 -0
  22. package/src/modules/storybook.ts +33 -0
  23. package/src/modules/stripe.ts +39 -0
  24. package/src/modules/types.ts +368 -0
  25. package/src/utils/files.ts +198 -0
  26. package/src/utils/packages.ts +59 -0
  27. package/src/utils/template-dependency-audit.ts +218 -0
  28. package/src/utils/template.ts +31 -0
  29. package/templates/base/backend/drizzle.config.ts +12 -0
  30. package/templates/base/backend/src/app.ts +65 -0
  31. package/templates/base/backend/src/db/index.ts +10 -0
  32. package/templates/base/backend/src/db/schema/index.ts +2 -0
  33. package/templates/base/backend/src/db/schema/items.ts +18 -0
  34. package/templates/base/backend/src/env.ts +78 -0
  35. package/templates/base/backend/src/index.ts +23 -0
  36. package/templates/base/backend/src/lib/errors.ts +205 -0
  37. package/templates/base/backend/src/lib/id.ts +5 -0
  38. package/templates/base/backend/src/lib/lazy.ts +14 -0
  39. package/templates/base/backend/src/lib/logger.ts +168 -0
  40. package/templates/base/backend/src/lib/openapi-schemas.ts +123 -0
  41. package/templates/base/backend/src/lib/openapi.ts +113 -0
  42. package/templates/base/backend/src/lib/pagination.ts +75 -0
  43. package/templates/base/backend/src/lib/response.ts +23 -0
  44. package/templates/base/backend/src/modules/items/index.ts +1 -0
  45. package/templates/base/backend/src/modules/items/model.ts +26 -0
  46. package/templates/base/backend/src/modules/items/repository.ts +30 -0
  47. package/templates/base/backend/src/modules/items/route.ts +93 -0
  48. package/templates/base/backend/src/modules/items/usecases.ts +67 -0
  49. package/templates/base/backend/src/plugins/error.ts +40 -0
  50. package/templates/base/backend/src/plugins/index.ts +7 -0
  51. package/templates/base/backend/src/plugins/logging.ts +20 -0
  52. package/templates/base/backend/src/plugins/metrics.ts +155 -0
  53. package/templates/base/backend/src/plugins/openapi.ts +17 -0
  54. package/templates/base/backend/src/plugins/request-id.ts +35 -0
  55. package/templates/base/backend/src/routes/health.ts +72 -0
  56. package/templates/base/backend/src/test-setup.ts +36 -0
  57. package/templates/base/backend/src/test-utils/db.ts +212 -0
  58. package/templates/base/backend/src/test-utils/factories.ts +16 -0
  59. package/templates/base/backend/src/test-utils/index.ts +3 -0
  60. package/templates/base/backend/src/test-utils/request.ts +72 -0
  61. package/templates/base/backend/src/types/index.ts +1 -0
  62. package/templates/base/backend/tsconfig.json +21 -0
  63. package/templates/base/backend/vitest.config.ts +26 -0
  64. package/templates/base/claude/skills/agent-browser/SKILL.md +629 -0
  65. package/templates/base/claude/skills/agent-browser/references/authentication.md +306 -0
  66. package/templates/base/claude/skills/agent-browser/references/commands.md +264 -0
  67. package/templates/base/claude/skills/agent-browser/references/profiling.md +120 -0
  68. package/templates/base/claude/skills/agent-browser/references/proxy-support.md +194 -0
  69. package/templates/base/claude/skills/agent-browser/references/session-management.md +194 -0
  70. package/templates/base/claude/skills/agent-browser/references/snapshot-refs.md +196 -0
  71. package/templates/base/claude/skills/agent-browser/references/video-recording.md +173 -0
  72. package/templates/base/claude/skills/agent-browser/templates/authenticated-session.sh +105 -0
  73. package/templates/base/claude/skills/agent-browser/templates/capture-workflow.sh +69 -0
  74. package/templates/base/claude/skills/agent-browser/templates/form-automation.sh +62 -0
  75. package/templates/base/claude/skills/alpine-js/SKILL.md +107 -0
  76. package/templates/base/claude/skills/better-auth-best-practices/SKILL.md +183 -0
  77. package/templates/base/claude/skills/es-toolkit/SKILL.md +281 -0
  78. package/templates/base/claude/skills/es-toolkit/references/api-catalog.md +234 -0
  79. package/templates/base/claude/skills/es-toolkit/references/lodash-migration.md +131 -0
  80. package/templates/base/claude/skills/hono/SKILL.md +90 -0
  81. package/templates/base/claude/skills/organization-best-practices/SKILL.md +478 -0
  82. package/templates/base/claude/skills/stripe-best-practices/SKILL.md +30 -0
  83. package/templates/base/claude/skills/stripe-integration/SKILL.md +492 -0
  84. package/templates/base/claude/skills/stripe-subscriptions/SKILL.md +54 -0
  85. package/templates/base/claude/skills/stripe-webhooks/SKILL.md +163 -0
  86. package/templates/base/claude/skills/stripe-webhooks/examples/express/.env.example +5 -0
  87. package/templates/base/claude/skills/stripe-webhooks/examples/express/README.md +64 -0
  88. package/templates/base/claude/skills/stripe-webhooks/examples/express/package.json +19 -0
  89. package/templates/base/claude/skills/stripe-webhooks/examples/express/src/index.js +75 -0
  90. package/templates/base/claude/skills/stripe-webhooks/examples/express/test/webhook.test.js +129 -0
  91. package/templates/base/claude/skills/stripe-webhooks/examples/fastapi/.env.example +5 -0
  92. package/templates/base/claude/skills/stripe-webhooks/examples/fastapi/README.md +69 -0
  93. package/templates/base/claude/skills/stripe-webhooks/examples/fastapi/main.py +75 -0
  94. package/templates/base/claude/skills/stripe-webhooks/examples/fastapi/requirements.txt +6 -0
  95. package/templates/base/claude/skills/stripe-webhooks/examples/fastapi/test_webhook.py +121 -0
  96. package/templates/base/claude/skills/stripe-webhooks/examples/nextjs/.env.example +5 -0
  97. package/templates/base/claude/skills/stripe-webhooks/examples/nextjs/README.md +62 -0
  98. package/templates/base/claude/skills/stripe-webhooks/examples/nextjs/app/webhooks/stripe/route.ts +63 -0
  99. package/templates/base/claude/skills/stripe-webhooks/examples/nextjs/package.json +23 -0
  100. package/templates/base/claude/skills/stripe-webhooks/examples/nextjs/test/webhook.test.ts +139 -0
  101. package/templates/base/claude/skills/stripe-webhooks/examples/nextjs/vitest.config.ts +8 -0
  102. package/templates/base/claude/skills/stripe-webhooks/references/overview.md +62 -0
  103. package/templates/base/claude/skills/stripe-webhooks/references/setup.md +99 -0
  104. package/templates/base/claude/skills/stripe-webhooks/references/verification.md +154 -0
  105. package/templates/base/claude/skills/svelte-code-writer/SKILL.md +66 -0
  106. package/templates/base/claude/skills/zod/AGENTS.md +97 -0
  107. package/templates/base/claude/skills/zod/README.md +79 -0
  108. package/templates/base/claude/skills/zod/SKILL.md +128 -0
  109. package/templates/base/claude/skills/zod/references/compose-intersection.md +143 -0
  110. package/templates/base/claude/skills/zod/references/compose-lazy-recursive.md +138 -0
  111. package/templates/base/claude/skills/zod/references/compose-pipe.md +114 -0
  112. package/templates/base/claude/skills/zod/references/compose-preprocess.md +131 -0
  113. package/templates/base/claude/skills/zod/references/compose-shared-schemas.md +142 -0
  114. package/templates/base/claude/skills/zod/references/error-avoid-throwing-in-refine.md +134 -0
  115. package/templates/base/claude/skills/zod/references/error-custom-messages.md +127 -0
  116. package/templates/base/claude/skills/zod/references/error-i18n.md +140 -0
  117. package/templates/base/claude/skills/zod/references/error-path-for-nested.md +135 -0
  118. package/templates/base/claude/skills/zod/references/error-use-flatten.md +135 -0
  119. package/templates/base/claude/skills/zod/references/object-discriminated-unions.md +136 -0
  120. package/templates/base/claude/skills/zod/references/object-extend-for-composition.md +146 -0
  121. package/templates/base/claude/skills/zod/references/object-optional-vs-nullable.md +120 -0
  122. package/templates/base/claude/skills/zod/references/object-partial-for-updates.md +124 -0
  123. package/templates/base/claude/skills/zod/references/object-pick-omit.md +147 -0
  124. package/templates/base/claude/skills/zod/references/object-strict-vs-strip.md +122 -0
  125. package/templates/base/claude/skills/zod/references/parse-async-for-async-refinements.md +127 -0
  126. package/templates/base/claude/skills/zod/references/parse-avoid-double-validation.md +130 -0
  127. package/templates/base/claude/skills/zod/references/parse-handle-all-issues.md +126 -0
  128. package/templates/base/claude/skills/zod/references/parse-never-trust-json.md +116 -0
  129. package/templates/base/claude/skills/zod/references/parse-use-safeparse.md +103 -0
  130. package/templates/base/claude/skills/zod/references/parse-validate-early.md +125 -0
  131. package/templates/base/claude/skills/zod/references/perf-arrays.md +154 -0
  132. package/templates/base/claude/skills/zod/references/perf-avoid-dynamic-creation.md +142 -0
  133. package/templates/base/claude/skills/zod/references/perf-cache-schemas.md +143 -0
  134. package/templates/base/claude/skills/zod/references/perf-lazy-loading.md +136 -0
  135. package/templates/base/claude/skills/zod/references/perf-zod-mini.md +118 -0
  136. package/templates/base/claude/skills/zod/references/refine-add-path.md +149 -0
  137. package/templates/base/claude/skills/zod/references/refine-catch.md +138 -0
  138. package/templates/base/claude/skills/zod/references/refine-defaults.md +132 -0
  139. package/templates/base/claude/skills/zod/references/refine-transform-coerce.md +103 -0
  140. package/templates/base/claude/skills/zod/references/refine-vs-superrefine.md +159 -0
  141. package/templates/base/claude/skills/zod/references/schema-avoid-optional-abuse.md +94 -0
  142. package/templates/base/claude/skills/zod/references/schema-coercion-for-form-data.md +89 -0
  143. package/templates/base/claude/skills/zod/references/schema-string-validations.md +87 -0
  144. package/templates/base/claude/skills/zod/references/schema-use-enums.md +106 -0
  145. package/templates/base/claude/skills/zod/references/schema-use-primitives-correctly.md +63 -0
  146. package/templates/base/claude/skills/zod/references/schema-use-unknown-not-any.md +86 -0
  147. package/templates/base/claude/skills/zod/references/type-branded-types.md +106 -0
  148. package/templates/base/claude/skills/zod/references/type-enable-strict-mode.md +132 -0
  149. package/templates/base/claude/skills/zod/references/type-export-schemas-and-types.md +117 -0
  150. package/templates/base/claude/skills/zod/references/type-input-vs-output.md +116 -0
  151. package/templates/base/claude/skills/zod/references/type-use-z-infer.md +113 -0
  152. package/templates/base/frontend/components.json +25 -0
  153. package/templates/base/frontend/index.html +17 -0
  154. package/templates/base/frontend/src/App.test.tsx +13 -0
  155. package/templates/base/frontend/src/App.tsx +11 -0
  156. package/templates/base/frontend/src/components/app-sidebar.tsx +89 -0
  157. package/templates/base/frontend/src/components/app-topbar.tsx +28 -0
  158. package/templates/base/frontend/src/components/nav-secondary.tsx +38 -0
  159. package/templates/base/frontend/src/components/nav-user.tsx +93 -0
  160. package/templates/base/frontend/src/components/theme-toggle.tsx +29 -0
  161. package/templates/base/frontend/src/components/ui/accordion.tsx +72 -0
  162. package/templates/base/frontend/src/components/ui/alert-dialog.tsx +160 -0
  163. package/templates/base/frontend/src/components/ui/alert.tsx +69 -0
  164. package/templates/base/frontend/src/components/ui/aspect-ratio.tsx +22 -0
  165. package/templates/base/frontend/src/components/ui/avatar.tsx +91 -0
  166. package/templates/base/frontend/src/components/ui/badge.tsx +50 -0
  167. package/templates/base/frontend/src/components/ui/banner.tsx +34 -0
  168. package/templates/base/frontend/src/components/ui/breadcrumb.tsx +103 -0
  169. package/templates/base/frontend/src/components/ui/button-group.tsx +78 -0
  170. package/templates/base/frontend/src/components/ui/button.tsx +61 -0
  171. package/templates/base/frontend/src/components/ui/calendar.tsx +185 -0
  172. package/templates/base/frontend/src/components/ui/card.tsx +92 -0
  173. package/templates/base/frontend/src/components/ui/carousel.tsx +229 -0
  174. package/templates/base/frontend/src/components/ui/chart.tsx +323 -0
  175. package/templates/base/frontend/src/components/ui/checkbox.tsx +28 -0
  176. package/templates/base/frontend/src/components/ui/collapsible.tsx +15 -0
  177. package/templates/base/frontend/src/components/ui/combobox.tsx +273 -0
  178. package/templates/base/frontend/src/components/ui/command.tsx +179 -0
  179. package/templates/base/frontend/src/components/ui/context-menu.tsx +245 -0
  180. package/templates/base/frontend/src/components/ui/dialog.tsx +138 -0
  181. package/templates/base/frontend/src/components/ui/direction.tsx +1 -0
  182. package/templates/base/frontend/src/components/ui/drawer.tsx +118 -0
  183. package/templates/base/frontend/src/components/ui/dropdown-menu.tsx +258 -0
  184. package/templates/base/frontend/src/components/ui/empty.tsx +94 -0
  185. package/templates/base/frontend/src/components/ui/field.tsx +224 -0
  186. package/templates/base/frontend/src/components/ui/hover-card.tsx +44 -0
  187. package/templates/base/frontend/src/components/ui/input-group.tsx +146 -0
  188. package/templates/base/frontend/src/components/ui/input-otp.tsx +86 -0
  189. package/templates/base/frontend/src/components/ui/input.tsx +20 -0
  190. package/templates/base/frontend/src/components/ui/item.tsx +188 -0
  191. package/templates/base/frontend/src/components/ui/kbd.tsx +26 -0
  192. package/templates/base/frontend/src/components/ui/label.tsx +20 -0
  193. package/templates/base/frontend/src/components/ui/menubar.tsx +265 -0
  194. package/templates/base/frontend/src/components/ui/native-select.tsx +43 -0
  195. package/templates/base/frontend/src/components/ui/navigation-menu.tsx +161 -0
  196. package/templates/base/frontend/src/components/ui/pagination.tsx +118 -0
  197. package/templates/base/frontend/src/components/ui/popover.tsx +77 -0
  198. package/templates/base/frontend/src/components/ui/progress.tsx +64 -0
  199. package/templates/base/frontend/src/components/ui/radio-group.tsx +38 -0
  200. package/templates/base/frontend/src/components/ui/resizable.tsx +40 -0
  201. package/templates/base/frontend/src/components/ui/scroll-area.tsx +50 -0
  202. package/templates/base/frontend/src/components/ui/select.tsx +188 -0
  203. package/templates/base/frontend/src/components/ui/separator.tsx +19 -0
  204. package/templates/base/frontend/src/components/ui/sheet.tsx +123 -0
  205. package/templates/base/frontend/src/components/ui/sidebar.tsx +694 -0
  206. package/templates/base/frontend/src/components/ui/skeleton.tsx +13 -0
  207. package/templates/base/frontend/src/components/ui/slider.tsx +52 -0
  208. package/templates/base/frontend/src/components/ui/sonner.tsx +43 -0
  209. package/templates/base/frontend/src/components/ui/spinner.tsx +15 -0
  210. package/templates/base/frontend/src/components/ui/surface.tsx +15 -0
  211. package/templates/base/frontend/src/components/ui/switch.tsx +30 -0
  212. package/templates/base/frontend/src/components/ui/table.tsx +98 -0
  213. package/templates/base/frontend/src/components/ui/tabs.tsx +75 -0
  214. package/templates/base/frontend/src/components/ui/textarea.tsx +18 -0
  215. package/templates/base/frontend/src/components/ui/toggle-group.tsx +87 -0
  216. package/templates/base/frontend/src/components/ui/toggle.tsx +42 -0
  217. package/templates/base/frontend/src/components/ui/tooltip.tsx +54 -0
  218. package/templates/base/frontend/src/hooks/use-mobile.ts +19 -0
  219. package/templates/base/frontend/src/integrations/tanstack-query/devtools.tsx +6 -0
  220. package/templates/base/frontend/src/integrations/tanstack-query/root-provider.tsx +18 -0
  221. package/templates/base/frontend/src/lib/utils.ts +6 -0
  222. package/templates/base/frontend/src/main.tsx +39 -0
  223. package/templates/base/frontend/src/routeTree.gen.ts +102 -0
  224. package/templates/base/frontend/src/routes/__root.tsx +16 -0
  225. package/templates/base/frontend/src/routes/_app/index.tsx +122 -0
  226. package/templates/base/frontend/src/routes/_app/settings.tsx +137 -0
  227. package/templates/base/frontend/src/routes/_app.tsx +19 -0
  228. package/templates/base/frontend/src/stores/use-theme-store.ts +92 -0
  229. package/templates/base/frontend/src/styles.css +146 -0
  230. package/templates/base/frontend/src/test-setup.ts +24 -0
  231. package/templates/base/frontend/tsconfig.json +27 -0
  232. package/templates/base/frontend/vite.config.ts +30 -0
  233. package/templates/base/frontend/vitest.config.ts +20 -0
  234. package/templates/base/root/.editorconfig +35 -0
  235. package/templates/base/root/.github/actions/setup-bun/action.yml +48 -0
  236. package/templates/base/root/.github/workflows/ci.yaml +66 -0
  237. package/templates/base/root/.husky/commit-msg +4 -0
  238. package/templates/base/root/.husky/pre-commit +4 -0
  239. package/templates/base/root/.nvmrc +2 -0
  240. package/templates/base/root/.oxfmtrc.json +33 -0
  241. package/templates/base/root/.oxlintrc.json +179 -0
  242. package/templates/base/root/CLAUDE.md +40 -0
  243. package/templates/base/root/Makefile +57 -0
  244. package/templates/base/root/commitlint.config.ts +3 -0
  245. package/templates/base/root/docker/postgres/init-test-db.sh +12 -0
  246. package/templates/base/root/lint-plugins/react-component-complexity.mjs +282 -0
  247. package/templates/base/root/lint-plugins/react-hooks-separation-codemod.mjs +1078 -0
  248. package/templates/base/root/lint-plugins/react-hooks-separation.mjs +243 -0
  249. package/templates/base/root/lint-plugins/test-file-location.mjs +104 -0
  250. package/templates/base/root/tsconfig.base.json +15 -0
  251. package/templates/base/root/tsconfig.json +16 -0
  252. package/templates/modules/auth/packages/backend/src/db/schema/auth.ts +145 -0
  253. package/templates/modules/auth/packages/backend/src/lib/auth/auth-context.ts +28 -0
  254. package/templates/modules/auth/packages/backend/src/lib/auth/auth.ts +97 -0
  255. package/templates/modules/auth/packages/backend/src/plugins/auth.ts +82 -0
  256. package/templates/modules/auth/src/db/schema/auth.ts +87 -0
  257. package/templates/modules/auth/src/lib/auth/auth-context.ts +23 -0
  258. package/templates/modules/auth/src/lib/auth/auth.ts +53 -0
  259. package/templates/modules/auth/src/lib/auth/index.ts +2 -0
  260. package/templates/modules/auth/src/plugins/auth.ts +52 -0
  261. package/templates/modules/email/packages/backend/src/lib/emails/send.tsx +58 -0
  262. package/templates/modules/email/packages/backend/src/lib/emails/templates/base.tsx +26 -0
  263. package/templates/modules/email/src/lib/emails/index.ts +1 -0
  264. package/templates/modules/email/src/lib/emails/send.ts +63 -0
  265. package/templates/modules/email/src/lib/emails/templates/layout.tsx +34 -0
  266. package/templates/modules/email/src/lib/integrations/resend.ts +10 -0
  267. package/templates/modules/inngest/packages/backend/src/jobs/example.ts +12 -0
  268. package/templates/modules/inngest/packages/backend/src/jobs/index.ts +3 -0
  269. package/templates/modules/inngest/packages/backend/src/lib/inngest.ts +39 -0
  270. package/templates/modules/inngest/src/jobs/example.ts +12 -0
  271. package/templates/modules/inngest/src/jobs/index.ts +3 -0
  272. package/templates/modules/inngest/src/lib/inngest.ts +28 -0
  273. package/templates/modules/observability/packages/backend/src/lib/sentry.ts +25 -0
  274. package/templates/modules/observability/packages/backend/src/lib/tracing.ts +125 -0
  275. package/templates/modules/observability/src/lib/sentry.ts +20 -0
  276. package/templates/modules/observability/src/lib/tracing.ts +77 -0
  277. package/templates/modules/organizations/packages/backend/src/lib/auth/org-context.ts +33 -0
  278. package/templates/modules/organizations/packages/backend/src/lib/auth/permissions.ts +43 -0
  279. package/templates/modules/organizations/src/db/schema/auth.ts +147 -0
  280. package/templates/modules/organizations/src/lib/auth/auth.ts +90 -0
  281. package/templates/modules/organizations/src/lib/auth/org-context.ts +33 -0
  282. package/templates/modules/organizations/src/lib/auth/permissions.ts +47 -0
  283. package/templates/modules/organizations/src/plugins/auth.ts +68 -0
  284. package/templates/modules/redis/packages/backend/src/lib/redis.ts +65 -0
  285. package/templates/modules/redis/packages/backend/src/plugins/rate-limiter.ts +51 -0
  286. package/templates/modules/redis/src/lib/redis.ts +30 -0
  287. package/templates/modules/redis/src/plugins/rate-limiter.ts +60 -0
  288. package/templates/modules/storage/packages/backend/src/lib/storage/client.ts +64 -0
  289. package/templates/modules/storage/packages/backend/src/lib/storage/index.ts +2 -0
  290. package/templates/modules/storage/packages/backend/src/lib/storage/init.ts +30 -0
  291. package/templates/modules/storage/src/lib/storage/client.ts +42 -0
  292. package/templates/modules/storage/src/lib/storage/index.ts +1 -0
  293. package/templates/modules/storybook/packages/frontend/.storybook/main.ts +17 -0
  294. package/templates/modules/storybook/packages/frontend/.storybook/preview.tsx +17 -0
  295. package/templates/modules/storybook/packages/frontend/src/components/ui/button.stories.tsx +17 -0
  296. package/templates/modules/stripe/packages/backend/src/db/schema/billing.ts +102 -0
  297. package/templates/modules/stripe/packages/backend/src/lib/billing.ts +31 -0
  298. package/templates/modules/stripe/packages/backend/src/lib/integrations/stripe.ts +52 -0
  299. package/templates/modules/stripe/packages/backend/src/modules/billing/index.ts +1 -0
  300. package/templates/modules/stripe/packages/backend/src/modules/billing/model.ts +45 -0
  301. package/templates/modules/stripe/packages/backend/src/modules/billing/repository.ts +87 -0
  302. package/templates/modules/stripe/packages/backend/src/modules/billing/route.ts +42 -0
  303. package/templates/modules/stripe/packages/backend/src/modules/billing/usecases.ts +97 -0
  304. package/templates/modules/stripe/packages/backend/src/routes/webhooks.ts +25 -0
  305. package/templates/modules/stripe/src/db/schema/billing.ts +90 -0
  306. package/templates/modules/stripe/src/lib/billing.ts +33 -0
  307. package/templates/modules/stripe/src/lib/integrations/stripe.ts +46 -0
  308. package/templates/modules/stripe/src/modules/billing/index.ts +1 -0
  309. package/templates/modules/stripe/src/modules/billing/model.ts +55 -0
  310. package/templates/modules/stripe/src/modules/billing/repository.ts +48 -0
  311. package/templates/modules/stripe/src/modules/billing/route.ts +97 -0
  312. package/templates/modules/stripe/src/modules/billing/usecases.ts +92 -0
  313. package/templates/modules/stripe/src/routes/webhooks.ts +57 -0
  314. package/vendor/skills/README.md +244 -0
  315. package/vendor/skills/skills/a11y-testing/SKILL.md +169 -0
  316. package/vendor/skills/skills/a11y-testing/checklists/a11y-testing-checklist.md +298 -0
  317. package/vendor/skills/skills/a11y-testing/examples/a11y-testing-examples.md +615 -0
  318. package/vendor/skills/skills/a11y-testing/references/a11y-testing-tools.md +383 -0
  319. package/vendor/skills/skills/a11y-testing/templates/a11y-test-template.ts +470 -0
  320. package/vendor/skills/skills/adversarial-review/SKILL.md +140 -0
  321. package/vendor/skills/skills/adversarial-review/references/reviewer-lenses.md +38 -0
  322. package/vendor/skills/skills/agent-browser/SKILL.md +151 -0
  323. package/vendor/skills/skills/agent-identifier/SKILL.md +438 -0
  324. package/vendor/skills/skills/agent-identifier/examples/agent-creation-prompt.md +250 -0
  325. package/vendor/skills/skills/agent-identifier/examples/complete-agent-examples.md +458 -0
  326. package/vendor/skills/skills/agent-identifier/references/agent-creation-system-prompt.md +216 -0
  327. package/vendor/skills/skills/agent-identifier/references/system-prompt-design.md +464 -0
  328. package/vendor/skills/skills/agent-identifier/references/triggering-examples.md +508 -0
  329. package/vendor/skills/skills/agent-identifier/scripts/validate-agent.sh +217 -0
  330. package/vendor/skills/skills/agent-md-refactor/README.md +234 -0
  331. package/vendor/skills/skills/agent-md-refactor/SKILL.md +309 -0
  332. package/vendor/skills/skills/ai-pdf-builder/README.md +40 -0
  333. package/vendor/skills/skills/ai-pdf-builder/SKILL.md +210 -0
  334. package/vendor/skills/skills/ai-pdf-builder/_meta.json +22 -0
  335. package/vendor/skills/skills/ai-sdk/SKILL.md +53 -0
  336. package/vendor/skills/skills/ai-sdk/references/ai-gateway.md +41 -0
  337. package/vendor/skills/skills/ai-sdk/references/common-errors.md +167 -0
  338. package/vendor/skills/skills/alex-hormozi-pitch/SKILL.md +69 -0
  339. package/vendor/skills/skills/alex-hormozi-pitch/metadata.json +14 -0
  340. package/vendor/skills/skills/app-renderer-systems/SKILL.md +177 -0
  341. package/vendor/skills/skills/app-renderer-systems/references/directory-layout.md +120 -0
  342. package/vendor/skills/skills/app-renderer-systems/references/patterns.md +509 -0
  343. package/vendor/skills/skills/architectural-analysis/SKILL.md +720 -0
  344. package/vendor/skills/skills/argocd-expert/SKILL.md +767 -0
  345. package/vendor/skills/skills/bencium-innovative-ux-designer/ACCESSIBILITY.md +112 -0
  346. package/vendor/skills/skills/bencium-innovative-ux-designer/DESIGN-SYSTEM-TEMPLATE.md +631 -0
  347. package/vendor/skills/skills/bencium-innovative-ux-designer/MOTION-SPEC.md +74 -0
  348. package/vendor/skills/skills/bencium-innovative-ux-designer/RESPONSIVE-DESIGN.md +95 -0
  349. package/vendor/skills/skills/bencium-innovative-ux-designer/SKILL.md +772 -0
  350. package/vendor/skills/skills/better-auth-best-practices/SKILL.md +174 -0
  351. package/vendor/skills/skills/brainstorming/SKILL.md +101 -0
  352. package/vendor/skills/skills/brand-storytelling/SKILL.md +86 -0
  353. package/vendor/skills/skills/brand-storytelling/references/guest-insights.md +722 -0
  354. package/vendor/skills/skills/building-components/SKILL.md +37 -0
  355. package/vendor/skills/skills/building-components/references/accessibility.mdx +794 -0
  356. package/vendor/skills/skills/building-components/references/as-child.mdx +318 -0
  357. package/vendor/skills/skills/building-components/references/composition.mdx +229 -0
  358. package/vendor/skills/skills/building-components/references/data-attributes.mdx +409 -0
  359. package/vendor/skills/skills/building-components/references/definitions.mdx +256 -0
  360. package/vendor/skills/skills/building-components/references/design-tokens.mdx +57 -0
  361. package/vendor/skills/skills/building-components/references/docs.mdx +153 -0
  362. package/vendor/skills/skills/building-components/references/marketplaces.mdx +144 -0
  363. package/vendor/skills/skills/building-components/references/npm.mdx +166 -0
  364. package/vendor/skills/skills/building-components/references/polymorphism.mdx +576 -0
  365. package/vendor/skills/skills/building-components/references/principles.mdx +61 -0
  366. package/vendor/skills/skills/building-components/references/registry.mdx +169 -0
  367. package/vendor/skills/skills/building-components/references/state.mdx +95 -0
  368. package/vendor/skills/skills/building-components/references/styling.mdx +271 -0
  369. package/vendor/skills/skills/building-components/references/types.mdx +189 -0
  370. package/vendor/skills/skills/centrifugo/SKILL.md +362 -0
  371. package/vendor/skills/skills/centrifugo/references/authentication.md +187 -0
  372. package/vendor/skills/skills/centrifugo/references/channels.md +172 -0
  373. package/vendor/skills/skills/centrifugo/references/client-sdk.md +242 -0
  374. package/vendor/skills/skills/centrifugo/references/configuration.md +201 -0
  375. package/vendor/skills/skills/centrifugo/references/engines.md +203 -0
  376. package/vendor/skills/skills/centrifugo/references/proxy.md +301 -0
  377. package/vendor/skills/skills/centrifugo/references/server-api.md +209 -0
  378. package/vendor/skills/skills/cloudflare/SKILL.md +238 -0
  379. package/vendor/skills/skills/cloudflare/references/agents-sdk/README.md +95 -0
  380. package/vendor/skills/skills/cloudflare/references/agents-sdk/api.md +195 -0
  381. package/vendor/skills/skills/cloudflare/references/agents-sdk/configuration.md +178 -0
  382. package/vendor/skills/skills/cloudflare/references/agents-sdk/gotchas.md +173 -0
  383. package/vendor/skills/skills/cloudflare/references/agents-sdk/patterns.md +215 -0
  384. package/vendor/skills/skills/cloudflare/references/ai-gateway/README.md +176 -0
  385. package/vendor/skills/skills/cloudflare/references/ai-gateway/configuration.md +117 -0
  386. package/vendor/skills/skills/cloudflare/references/ai-gateway/dynamic-routing.md +88 -0
  387. package/vendor/skills/skills/cloudflare/references/ai-gateway/features.md +96 -0
  388. package/vendor/skills/skills/cloudflare/references/ai-gateway/sdk-integration.md +110 -0
  389. package/vendor/skills/skills/cloudflare/references/ai-gateway/troubleshooting.md +90 -0
  390. package/vendor/skills/skills/cloudflare/references/ai-search/README.md +145 -0
  391. package/vendor/skills/skills/cloudflare/references/ai-search/api.md +87 -0
  392. package/vendor/skills/skills/cloudflare/references/ai-search/configuration.md +91 -0
  393. package/vendor/skills/skills/cloudflare/references/ai-search/gotchas.md +92 -0
  394. package/vendor/skills/skills/cloudflare/references/ai-search/patterns.md +87 -0
  395. package/vendor/skills/skills/cloudflare/references/analytics-engine/README.md +96 -0
  396. package/vendor/skills/skills/cloudflare/references/analytics-engine/api.md +112 -0
  397. package/vendor/skills/skills/cloudflare/references/analytics-engine/configuration.md +107 -0
  398. package/vendor/skills/skills/cloudflare/references/analytics-engine/gotchas.md +87 -0
  399. package/vendor/skills/skills/cloudflare/references/analytics-engine/patterns.md +83 -0
  400. package/vendor/skills/skills/cloudflare/references/api/README.md +66 -0
  401. package/vendor/skills/skills/cloudflare/references/api/api.md +205 -0
  402. package/vendor/skills/skills/cloudflare/references/api/configuration.md +158 -0
  403. package/vendor/skills/skills/cloudflare/references/api/gotchas.md +231 -0
  404. package/vendor/skills/skills/cloudflare/references/api/patterns.md +208 -0
  405. package/vendor/skills/skills/cloudflare/references/api-shield/README.md +44 -0
  406. package/vendor/skills/skills/cloudflare/references/api-shield/api.md +153 -0
  407. package/vendor/skills/skills/cloudflare/references/api-shield/configuration.md +210 -0
  408. package/vendor/skills/skills/cloudflare/references/api-shield/gotchas.md +132 -0
  409. package/vendor/skills/skills/cloudflare/references/api-shield/patterns.md +185 -0
  410. package/vendor/skills/skills/cloudflare/references/argo-smart-routing/README.md +96 -0
  411. package/vendor/skills/skills/cloudflare/references/argo-smart-routing/api.md +253 -0
  412. package/vendor/skills/skills/cloudflare/references/argo-smart-routing/configuration.md +205 -0
  413. package/vendor/skills/skills/cloudflare/references/argo-smart-routing/gotchas.md +115 -0
  414. package/vendor/skills/skills/cloudflare/references/argo-smart-routing/patterns.md +107 -0
  415. package/vendor/skills/skills/cloudflare/references/bindings/README.md +127 -0
  416. package/vendor/skills/skills/cloudflare/references/bindings/api.md +214 -0
  417. package/vendor/skills/skills/cloudflare/references/bindings/configuration.md +200 -0
  418. package/vendor/skills/skills/cloudflare/references/bindings/gotchas.md +210 -0
  419. package/vendor/skills/skills/cloudflare/references/bindings/patterns.md +205 -0
  420. package/vendor/skills/skills/cloudflare/references/bot-management/README.md +95 -0
  421. package/vendor/skills/skills/cloudflare/references/bot-management/api.md +175 -0
  422. package/vendor/skills/skills/cloudflare/references/bot-management/configuration.md +175 -0
  423. package/vendor/skills/skills/cloudflare/references/bot-management/gotchas.md +116 -0
  424. package/vendor/skills/skills/cloudflare/references/bot-management/patterns.md +181 -0
  425. package/vendor/skills/skills/cloudflare/references/browser-rendering/README.md +84 -0
  426. package/vendor/skills/skills/cloudflare/references/browser-rendering/api.md +108 -0
  427. package/vendor/skills/skills/cloudflare/references/browser-rendering/configuration.md +78 -0
  428. package/vendor/skills/skills/cloudflare/references/browser-rendering/gotchas.md +91 -0
  429. package/vendor/skills/skills/cloudflare/references/browser-rendering/patterns.md +94 -0
  430. package/vendor/skills/skills/cloudflare/references/c3/README.md +111 -0
  431. package/vendor/skills/skills/cloudflare/references/c3/api.md +71 -0
  432. package/vendor/skills/skills/cloudflare/references/c3/configuration.md +85 -0
  433. package/vendor/skills/skills/cloudflare/references/c3/gotchas.md +97 -0
  434. package/vendor/skills/skills/cloudflare/references/c3/patterns.md +84 -0
  435. package/vendor/skills/skills/cloudflare/references/cache-reserve/README.md +150 -0
  436. package/vendor/skills/skills/cloudflare/references/cache-reserve/api.md +184 -0
  437. package/vendor/skills/skills/cloudflare/references/cache-reserve/configuration.md +170 -0
  438. package/vendor/skills/skills/cloudflare/references/cache-reserve/gotchas.md +136 -0
  439. package/vendor/skills/skills/cloudflare/references/cache-reserve/patterns.md +197 -0
  440. package/vendor/skills/skills/cloudflare/references/containers/README.md +87 -0
  441. package/vendor/skills/skills/cloudflare/references/containers/api.md +197 -0
  442. package/vendor/skills/skills/cloudflare/references/containers/configuration.md +191 -0
  443. package/vendor/skills/skills/cloudflare/references/containers/gotchas.md +182 -0
  444. package/vendor/skills/skills/cloudflare/references/containers/patterns.md +204 -0
  445. package/vendor/skills/skills/cloudflare/references/cron-triggers/README.md +101 -0
  446. package/vendor/skills/skills/cloudflare/references/cron-triggers/api.md +224 -0
  447. package/vendor/skills/skills/cloudflare/references/cron-triggers/configuration.md +190 -0
  448. package/vendor/skills/skills/cloudflare/references/cron-triggers/gotchas.md +207 -0
  449. package/vendor/skills/skills/cloudflare/references/cron-triggers/patterns.md +277 -0
  450. package/vendor/skills/skills/cloudflare/references/d1/README.md +137 -0
  451. package/vendor/skills/skills/cloudflare/references/d1/api.md +213 -0
  452. package/vendor/skills/skills/cloudflare/references/d1/configuration.md +198 -0
  453. package/vendor/skills/skills/cloudflare/references/d1/gotchas.md +98 -0
  454. package/vendor/skills/skills/cloudflare/references/d1/patterns.md +242 -0
  455. package/vendor/skills/skills/cloudflare/references/ddos/README.md +42 -0
  456. package/vendor/skills/skills/cloudflare/references/ddos/api.md +158 -0
  457. package/vendor/skills/skills/cloudflare/references/ddos/configuration.md +94 -0
  458. package/vendor/skills/skills/cloudflare/references/ddos/gotchas.md +114 -0
  459. package/vendor/skills/skills/cloudflare/references/ddos/patterns.md +222 -0
  460. package/vendor/skills/skills/cloudflare/references/do-storage/README.md +79 -0
  461. package/vendor/skills/skills/cloudflare/references/do-storage/api.md +107 -0
  462. package/vendor/skills/skills/cloudflare/references/do-storage/configuration.md +114 -0
  463. package/vendor/skills/skills/cloudflare/references/do-storage/gotchas.md +153 -0
  464. package/vendor/skills/skills/cloudflare/references/do-storage/patterns.md +210 -0
  465. package/vendor/skills/skills/cloudflare/references/do-storage/testing.md +186 -0
  466. package/vendor/skills/skills/cloudflare/references/durable-objects/README.md +194 -0
  467. package/vendor/skills/skills/cloudflare/references/durable-objects/api.md +205 -0
  468. package/vendor/skills/skills/cloudflare/references/durable-objects/configuration.md +160 -0
  469. package/vendor/skills/skills/cloudflare/references/durable-objects/gotchas.md +200 -0
  470. package/vendor/skills/skills/cloudflare/references/durable-objects/patterns.md +205 -0
  471. package/vendor/skills/skills/cloudflare/references/email-routing/README.md +89 -0
  472. package/vendor/skills/skills/cloudflare/references/email-routing/api.md +192 -0
  473. package/vendor/skills/skills/cloudflare/references/email-routing/configuration.md +187 -0
  474. package/vendor/skills/skills/cloudflare/references/email-routing/gotchas.md +203 -0
  475. package/vendor/skills/skills/cloudflare/references/email-routing/patterns.md +241 -0
  476. package/vendor/skills/skills/cloudflare/references/email-workers/README.md +153 -0
  477. package/vendor/skills/skills/cloudflare/references/email-workers/api.md +227 -0
  478. package/vendor/skills/skills/cloudflare/references/email-workers/configuration.md +115 -0
  479. package/vendor/skills/skills/cloudflare/references/email-workers/gotchas.md +133 -0
  480. package/vendor/skills/skills/cloudflare/references/email-workers/patterns.md +108 -0
  481. package/vendor/skills/skills/cloudflare/references/graphql-api/README.md +147 -0
  482. package/vendor/skills/skills/cloudflare/references/graphql-api/api.md +175 -0
  483. package/vendor/skills/skills/cloudflare/references/graphql-api/configuration.md +151 -0
  484. package/vendor/skills/skills/cloudflare/references/graphql-api/gotchas.md +111 -0
  485. package/vendor/skills/skills/cloudflare/references/graphql-api/patterns.md +276 -0
  486. package/vendor/skills/skills/cloudflare/references/hyperdrive/README.md +84 -0
  487. package/vendor/skills/skills/cloudflare/references/hyperdrive/api.md +149 -0
  488. package/vendor/skills/skills/cloudflare/references/hyperdrive/configuration.md +166 -0
  489. package/vendor/skills/skills/cloudflare/references/hyperdrive/gotchas.md +77 -0
  490. package/vendor/skills/skills/cloudflare/references/hyperdrive/patterns.md +203 -0
  491. package/vendor/skills/skills/cloudflare/references/images/README.md +65 -0
  492. package/vendor/skills/skills/cloudflare/references/images/api.md +101 -0
  493. package/vendor/skills/skills/cloudflare/references/images/configuration.md +206 -0
  494. package/vendor/skills/skills/cloudflare/references/images/gotchas.md +106 -0
  495. package/vendor/skills/skills/cloudflare/references/images/patterns.md +126 -0
  496. package/vendor/skills/skills/cloudflare/references/kv/README.md +90 -0
  497. package/vendor/skills/skills/cloudflare/references/kv/api.md +163 -0
  498. package/vendor/skills/skills/cloudflare/references/kv/configuration.md +148 -0
  499. package/vendor/skills/skills/cloudflare/references/kv/gotchas.md +133 -0
  500. package/vendor/skills/skills/cloudflare/references/kv/patterns.md +195 -0
  501. package/vendor/skills/skills/cloudflare/references/miniflare/README.md +113 -0
  502. package/vendor/skills/skills/cloudflare/references/miniflare/api.md +204 -0
  503. package/vendor/skills/skills/cloudflare/references/miniflare/configuration.md +174 -0
  504. package/vendor/skills/skills/cloudflare/references/miniflare/gotchas.md +179 -0
  505. package/vendor/skills/skills/cloudflare/references/miniflare/patterns.md +187 -0
  506. package/vendor/skills/skills/cloudflare/references/network-interconnect/README.md +104 -0
  507. package/vendor/skills/skills/cloudflare/references/network-interconnect/api.md +220 -0
  508. package/vendor/skills/skills/cloudflare/references/network-interconnect/configuration.md +123 -0
  509. package/vendor/skills/skills/cloudflare/references/network-interconnect/gotchas.md +175 -0
  510. package/vendor/skills/skills/cloudflare/references/network-interconnect/patterns.md +174 -0
  511. package/vendor/skills/skills/cloudflare/references/observability/README.md +93 -0
  512. package/vendor/skills/skills/cloudflare/references/observability/api.md +168 -0
  513. package/vendor/skills/skills/cloudflare/references/observability/configuration.md +178 -0
  514. package/vendor/skills/skills/cloudflare/references/observability/gotchas.md +125 -0
  515. package/vendor/skills/skills/cloudflare/references/observability/patterns.md +105 -0
  516. package/vendor/skills/skills/cloudflare/references/pages/README.md +92 -0
  517. package/vendor/skills/skills/cloudflare/references/pages/api.md +205 -0
  518. package/vendor/skills/skills/cloudflare/references/pages/configuration.md +216 -0
  519. package/vendor/skills/skills/cloudflare/references/pages/gotchas.md +218 -0
  520. package/vendor/skills/skills/cloudflare/references/pages/patterns.md +215 -0
  521. package/vendor/skills/skills/cloudflare/references/pages-functions/README.md +104 -0
  522. package/vendor/skills/skills/cloudflare/references/pages-functions/api.md +159 -0
  523. package/vendor/skills/skills/cloudflare/references/pages-functions/configuration.md +130 -0
  524. package/vendor/skills/skills/cloudflare/references/pages-functions/gotchas.md +102 -0
  525. package/vendor/skills/skills/cloudflare/references/pages-functions/patterns.md +148 -0
  526. package/vendor/skills/skills/cloudflare/references/pipelines/README.md +109 -0
  527. package/vendor/skills/skills/cloudflare/references/pipelines/api.md +214 -0
  528. package/vendor/skills/skills/cloudflare/references/pipelines/configuration.md +98 -0
  529. package/vendor/skills/skills/cloudflare/references/pipelines/gotchas.md +84 -0
  530. package/vendor/skills/skills/cloudflare/references/pipelines/patterns.md +87 -0
  531. package/vendor/skills/skills/cloudflare/references/pulumi/README.md +113 -0
  532. package/vendor/skills/skills/cloudflare/references/pulumi/api.md +230 -0
  533. package/vendor/skills/skills/cloudflare/references/pulumi/configuration.md +213 -0
  534. package/vendor/skills/skills/cloudflare/references/pulumi/gotchas.md +205 -0
  535. package/vendor/skills/skills/cloudflare/references/pulumi/patterns.md +260 -0
  536. package/vendor/skills/skills/cloudflare/references/queues/README.md +99 -0
  537. package/vendor/skills/skills/cloudflare/references/queues/api.md +211 -0
  538. package/vendor/skills/skills/cloudflare/references/queues/configuration.md +151 -0
  539. package/vendor/skills/skills/cloudflare/references/queues/gotchas.md +210 -0
  540. package/vendor/skills/skills/cloudflare/references/queues/patterns.md +220 -0
  541. package/vendor/skills/skills/cloudflare/references/r2/README.md +97 -0
  542. package/vendor/skills/skills/cloudflare/references/r2/api.md +235 -0
  543. package/vendor/skills/skills/cloudflare/references/r2/configuration.md +176 -0
  544. package/vendor/skills/skills/cloudflare/references/r2/gotchas.md +190 -0
  545. package/vendor/skills/skills/cloudflare/references/r2/patterns.md +203 -0
  546. package/vendor/skills/skills/cloudflare/references/r2-data-catalog/README.md +157 -0
  547. package/vendor/skills/skills/cloudflare/references/r2-data-catalog/api.md +199 -0
  548. package/vendor/skills/skills/cloudflare/references/r2-data-catalog/configuration.md +205 -0
  549. package/vendor/skills/skills/cloudflare/references/r2-data-catalog/gotchas.md +170 -0
  550. package/vendor/skills/skills/cloudflare/references/r2-data-catalog/patterns.md +191 -0
  551. package/vendor/skills/skills/cloudflare/references/r2-sql/README.md +138 -0
  552. package/vendor/skills/skills/cloudflare/references/r2-sql/SKILL.md.backup +512 -0
  553. package/vendor/skills/skills/cloudflare/references/r2-sql/api.md +159 -0
  554. package/vendor/skills/skills/cloudflare/references/r2-sql/configuration.md +152 -0
  555. package/vendor/skills/skills/cloudflare/references/r2-sql/gotchas.md +228 -0
  556. package/vendor/skills/skills/cloudflare/references/r2-sql/patterns.md +230 -0
  557. package/vendor/skills/skills/cloudflare/references/realtime-sfu/README.md +66 -0
  558. package/vendor/skills/skills/cloudflare/references/realtime-sfu/api.md +164 -0
  559. package/vendor/skills/skills/cloudflare/references/realtime-sfu/configuration.md +141 -0
  560. package/vendor/skills/skills/cloudflare/references/realtime-sfu/gotchas.md +138 -0
  561. package/vendor/skills/skills/cloudflare/references/realtime-sfu/patterns.md +187 -0
  562. package/vendor/skills/skills/cloudflare/references/realtimekit/README.md +118 -0
  563. package/vendor/skills/skills/cloudflare/references/realtimekit/api.md +237 -0
  564. package/vendor/skills/skills/cloudflare/references/realtimekit/configuration.md +226 -0
  565. package/vendor/skills/skills/cloudflare/references/realtimekit/gotchas.md +206 -0
  566. package/vendor/skills/skills/cloudflare/references/realtimekit/patterns.md +240 -0
  567. package/vendor/skills/skills/cloudflare/references/sandbox/README.md +104 -0
  568. package/vendor/skills/skills/cloudflare/references/sandbox/api.md +200 -0
  569. package/vendor/skills/skills/cloudflare/references/sandbox/configuration.md +154 -0
  570. package/vendor/skills/skills/cloudflare/references/sandbox/gotchas.md +201 -0
  571. package/vendor/skills/skills/cloudflare/references/sandbox/patterns.md +195 -0
  572. package/vendor/skills/skills/cloudflare/references/secrets-store/README.md +77 -0
  573. package/vendor/skills/skills/cloudflare/references/secrets-store/api.md +199 -0
  574. package/vendor/skills/skills/cloudflare/references/secrets-store/configuration.md +187 -0
  575. package/vendor/skills/skills/cloudflare/references/secrets-store/gotchas.md +97 -0
  576. package/vendor/skills/skills/cloudflare/references/secrets-store/patterns.md +218 -0
  577. package/vendor/skills/skills/cloudflare/references/smart-placement/README.md +143 -0
  578. package/vendor/skills/skills/cloudflare/references/smart-placement/api.md +192 -0
  579. package/vendor/skills/skills/cloudflare/references/smart-placement/configuration.md +202 -0
  580. package/vendor/skills/skills/cloudflare/references/smart-placement/gotchas.md +180 -0
  581. package/vendor/skills/skills/cloudflare/references/smart-placement/patterns.md +194 -0
  582. package/vendor/skills/skills/cloudflare/references/snippets/README.md +74 -0
  583. package/vendor/skills/skills/cloudflare/references/snippets/api.md +214 -0
  584. package/vendor/skills/skills/cloudflare/references/snippets/configuration.md +239 -0
  585. package/vendor/skills/skills/cloudflare/references/snippets/gotchas.md +104 -0
  586. package/vendor/skills/skills/cloudflare/references/snippets/patterns.md +135 -0
  587. package/vendor/skills/skills/cloudflare/references/spectrum/README.md +52 -0
  588. package/vendor/skills/skills/cloudflare/references/spectrum/api.md +184 -0
  589. package/vendor/skills/skills/cloudflare/references/spectrum/configuration.md +203 -0
  590. package/vendor/skills/skills/cloudflare/references/spectrum/gotchas.md +155 -0
  591. package/vendor/skills/skills/cloudflare/references/spectrum/patterns.md +206 -0
  592. package/vendor/skills/skills/cloudflare/references/static-assets/README.md +65 -0
  593. package/vendor/skills/skills/cloudflare/references/static-assets/api.md +201 -0
  594. package/vendor/skills/skills/cloudflare/references/static-assets/configuration.md +186 -0
  595. package/vendor/skills/skills/cloudflare/references/static-assets/gotchas.md +164 -0
  596. package/vendor/skills/skills/cloudflare/references/static-assets/patterns.md +189 -0
  597. package/vendor/skills/skills/cloudflare/references/stream/README.md +123 -0
  598. package/vendor/skills/skills/cloudflare/references/stream/api-live.md +202 -0
  599. package/vendor/skills/skills/cloudflare/references/stream/api.md +206 -0
  600. package/vendor/skills/skills/cloudflare/references/stream/configuration.md +151 -0
  601. package/vendor/skills/skills/cloudflare/references/stream/gotchas.md +139 -0
  602. package/vendor/skills/skills/cloudflare/references/stream/patterns.md +217 -0
  603. package/vendor/skills/skills/cloudflare/references/tail-workers/README.md +92 -0
  604. package/vendor/skills/skills/cloudflare/references/tail-workers/api.md +203 -0
  605. package/vendor/skills/skills/cloudflare/references/tail-workers/configuration.md +178 -0
  606. package/vendor/skills/skills/cloudflare/references/tail-workers/gotchas.md +206 -0
  607. package/vendor/skills/skills/cloudflare/references/tail-workers/patterns.md +190 -0
  608. package/vendor/skills/skills/cloudflare/references/terraform/README.md +100 -0
  609. package/vendor/skills/skills/cloudflare/references/terraform/api.md +178 -0
  610. package/vendor/skills/skills/cloudflare/references/terraform/configuration.md +197 -0
  611. package/vendor/skills/skills/cloudflare/references/terraform/gotchas.md +150 -0
  612. package/vendor/skills/skills/cloudflare/references/terraform/patterns.md +174 -0
  613. package/vendor/skills/skills/cloudflare/references/tunnel/README.md +137 -0
  614. package/vendor/skills/skills/cloudflare/references/tunnel/api.md +205 -0
  615. package/vendor/skills/skills/cloudflare/references/tunnel/configuration.md +163 -0
  616. package/vendor/skills/skills/cloudflare/references/tunnel/gotchas.md +159 -0
  617. package/vendor/skills/skills/cloudflare/references/tunnel/networking.md +174 -0
  618. package/vendor/skills/skills/cloudflare/references/tunnel/patterns.md +199 -0
  619. package/vendor/skills/skills/cloudflare/references/turn/README.md +86 -0
  620. package/vendor/skills/skills/cloudflare/references/turn/api.md +236 -0
  621. package/vendor/skills/skills/cloudflare/references/turn/configuration.md +181 -0
  622. package/vendor/skills/skills/cloudflare/references/turn/gotchas.md +236 -0
  623. package/vendor/skills/skills/cloudflare/references/turn/patterns.md +228 -0
  624. package/vendor/skills/skills/cloudflare/references/turnstile/README.md +102 -0
  625. package/vendor/skills/skills/cloudflare/references/turnstile/api.md +253 -0
  626. package/vendor/skills/skills/cloudflare/references/turnstile/configuration.md +243 -0
  627. package/vendor/skills/skills/cloudflare/references/turnstile/gotchas.md +253 -0
  628. package/vendor/skills/skills/cloudflare/references/turnstile/patterns.md +195 -0
  629. package/vendor/skills/skills/cloudflare/references/vectorize/README.md +133 -0
  630. package/vendor/skills/skills/cloudflare/references/vectorize/api.md +89 -0
  631. package/vendor/skills/skills/cloudflare/references/vectorize/configuration.md +91 -0
  632. package/vendor/skills/skills/cloudflare/references/vectorize/gotchas.md +83 -0
  633. package/vendor/skills/skills/cloudflare/references/vectorize/patterns.md +92 -0
  634. package/vendor/skills/skills/cloudflare/references/waf/README.md +125 -0
  635. package/vendor/skills/skills/cloudflare/references/waf/api.md +203 -0
  636. package/vendor/skills/skills/cloudflare/references/waf/configuration.md +215 -0
  637. package/vendor/skills/skills/cloudflare/references/waf/gotchas.md +208 -0
  638. package/vendor/skills/skills/cloudflare/references/waf/patterns.md +236 -0
  639. package/vendor/skills/skills/cloudflare/references/web-analytics/README.md +149 -0
  640. package/vendor/skills/skills/cloudflare/references/web-analytics/configuration.md +81 -0
  641. package/vendor/skills/skills/cloudflare/references/web-analytics/gotchas.md +86 -0
  642. package/vendor/skills/skills/cloudflare/references/web-analytics/integration.md +63 -0
  643. package/vendor/skills/skills/cloudflare/references/web-analytics/patterns.md +98 -0
  644. package/vendor/skills/skills/cloudflare/references/workerd/README.md +85 -0
  645. package/vendor/skills/skills/cloudflare/references/workerd/api.md +219 -0
  646. package/vendor/skills/skills/cloudflare/references/workerd/configuration.md +200 -0
  647. package/vendor/skills/skills/cloudflare/references/workerd/gotchas.md +151 -0
  648. package/vendor/skills/skills/cloudflare/references/workerd/patterns.md +205 -0
  649. package/vendor/skills/skills/cloudflare/references/workers/README.md +110 -0
  650. package/vendor/skills/skills/cloudflare/references/workers/api.md +197 -0
  651. package/vendor/skills/skills/cloudflare/references/workers/configuration.md +184 -0
  652. package/vendor/skills/skills/cloudflare/references/workers/frameworks.md +200 -0
  653. package/vendor/skills/skills/cloudflare/references/workers/gotchas.md +145 -0
  654. package/vendor/skills/skills/cloudflare/references/workers/patterns.md +220 -0
  655. package/vendor/skills/skills/cloudflare/references/workers-ai/README.md +206 -0
  656. package/vendor/skills/skills/cloudflare/references/workers-ai/api.md +115 -0
  657. package/vendor/skills/skills/cloudflare/references/workers-ai/configuration.md +98 -0
  658. package/vendor/skills/skills/cloudflare/references/workers-ai/gotchas.md +130 -0
  659. package/vendor/skills/skills/cloudflare/references/workers-ai/patterns.md +122 -0
  660. package/vendor/skills/skills/cloudflare/references/workers-for-platforms/README.md +95 -0
  661. package/vendor/skills/skills/cloudflare/references/workers-for-platforms/api.md +212 -0
  662. package/vendor/skills/skills/cloudflare/references/workers-for-platforms/configuration.md +178 -0
  663. package/vendor/skills/skills/cloudflare/references/workers-for-platforms/gotchas.md +134 -0
  664. package/vendor/skills/skills/cloudflare/references/workers-for-platforms/patterns.md +210 -0
  665. package/vendor/skills/skills/cloudflare/references/workers-playground/README.md +131 -0
  666. package/vendor/skills/skills/cloudflare/references/workers-playground/api.md +101 -0
  667. package/vendor/skills/skills/cloudflare/references/workers-playground/configuration.md +169 -0
  668. package/vendor/skills/skills/cloudflare/references/workers-playground/gotchas.md +88 -0
  669. package/vendor/skills/skills/cloudflare/references/workers-playground/patterns.md +134 -0
  670. package/vendor/skills/skills/cloudflare/references/workers-vpc/README.md +130 -0
  671. package/vendor/skills/skills/cloudflare/references/workers-vpc/api.md +196 -0
  672. package/vendor/skills/skills/cloudflare/references/workers-vpc/configuration.md +151 -0
  673. package/vendor/skills/skills/cloudflare/references/workers-vpc/gotchas.md +171 -0
  674. package/vendor/skills/skills/cloudflare/references/workers-vpc/patterns.md +235 -0
  675. package/vendor/skills/skills/cloudflare/references/workflows/README.md +72 -0
  676. package/vendor/skills/skills/cloudflare/references/workflows/api.md +240 -0
  677. package/vendor/skills/skills/cloudflare/references/workflows/configuration.md +160 -0
  678. package/vendor/skills/skills/cloudflare/references/workflows/gotchas.md +97 -0
  679. package/vendor/skills/skills/cloudflare/references/workflows/patterns.md +245 -0
  680. package/vendor/skills/skills/cloudflare/references/wrangler/README.md +143 -0
  681. package/vendor/skills/skills/cloudflare/references/wrangler/api.md +188 -0
  682. package/vendor/skills/skills/cloudflare/references/wrangler/configuration.md +198 -0
  683. package/vendor/skills/skills/cloudflare/references/wrangler/gotchas.md +212 -0
  684. package/vendor/skills/skills/cloudflare/references/wrangler/patterns.md +211 -0
  685. package/vendor/skills/skills/cloudflare/references/zaraz/IMPLEMENTATION_SUMMARY.md +131 -0
  686. package/vendor/skills/skills/cloudflare/references/zaraz/README.md +114 -0
  687. package/vendor/skills/skills/cloudflare/references/zaraz/api.md +118 -0
  688. package/vendor/skills/skills/cloudflare/references/zaraz/configuration.md +94 -0
  689. package/vendor/skills/skills/cloudflare/references/zaraz/gotchas.md +88 -0
  690. package/vendor/skills/skills/cloudflare/references/zaraz/patterns.md +77 -0
  691. package/vendor/skills/skills/content-research-writer/SKILL.md +595 -0
  692. package/vendor/skills/skills/copywriting/SKILL.md +287 -0
  693. package/vendor/skills/skills/copywriting/references/copy-frameworks.md +385 -0
  694. package/vendor/skills/skills/copywriting/references/natural-transitions.md +255 -0
  695. package/vendor/skills/skills/crafting-effective-readmes/README.md +180 -0
  696. package/vendor/skills/skills/crafting-effective-readmes/SKILL.md +82 -0
  697. package/vendor/skills/skills/crafting-effective-readmes/references/art-of-readme.md +518 -0
  698. package/vendor/skills/skills/crafting-effective-readmes/references/make-a-readme.md +119 -0
  699. package/vendor/skills/skills/crafting-effective-readmes/references/standard-readme-example-maximal.md +70 -0
  700. package/vendor/skills/skills/crafting-effective-readmes/references/standard-readme-example-minimal.md +23 -0
  701. package/vendor/skills/skills/crafting-effective-readmes/references/standard-readme-spec.md +290 -0
  702. package/vendor/skills/skills/crafting-effective-readmes/section-checklist.md +17 -0
  703. package/vendor/skills/skills/crafting-effective-readmes/style-guide.md +13 -0
  704. package/vendor/skills/skills/crafting-effective-readmes/templates/internal.md +106 -0
  705. package/vendor/skills/skills/crafting-effective-readmes/templates/oss.md +77 -0
  706. package/vendor/skills/skills/crafting-effective-readmes/templates/personal.md +51 -0
  707. package/vendor/skills/skills/crafting-effective-readmes/templates/xdg-config.md +71 -0
  708. package/vendor/skills/skills/crafting-effective-readmes/using-references.md +37 -0
  709. package/vendor/skills/skills/creating-spec/SKILL.md +343 -0
  710. package/vendor/skills/skills/deep-research/SKILL.md +96 -0
  711. package/vendor/skills/skills/design-spec-extraction/SKILL.md +1402 -0
  712. package/vendor/skills/skills/design-spec-extraction/references/design-tokens-schema.json +1145 -0
  713. package/vendor/skills/skills/design-spec-extraction/references/extraction-patterns.md +1044 -0
  714. package/vendor/skills/skills/develop-ai-functions-example/SKILL.md +225 -0
  715. package/vendor/skills/skills/devops-engineer/SKILL.md +147 -0
  716. package/vendor/skills/skills/devops-engineer/references/deployment-strategies.md +245 -0
  717. package/vendor/skills/skills/devops-engineer/references/docker-patterns.md +113 -0
  718. package/vendor/skills/skills/devops-engineer/references/github-actions.md +142 -0
  719. package/vendor/skills/skills/devops-engineer/references/incident-response.md +345 -0
  720. package/vendor/skills/skills/devops-engineer/references/kubernetes.md +154 -0
  721. package/vendor/skills/skills/devops-engineer/references/platform-engineering.md +417 -0
  722. package/vendor/skills/skills/devops-engineer/references/release-automation.md +527 -0
  723. package/vendor/skills/skills/devops-engineer/references/terraform-iac.md +141 -0
  724. package/vendor/skills/skills/dispatching-parallel-agents/SKILL.md +191 -0
  725. package/vendor/skills/skills/drizzle-orm/SKILL.md +116 -0
  726. package/vendor/skills/skills/drizzle-orm/references/patterns.md +750 -0
  727. package/vendor/skills/skills/drizzle-safe-migrations/SKILL.md +68 -0
  728. package/vendor/skills/skills/drizzle-safe-migrations/agents/openai.yaml +4 -0
  729. package/vendor/skills/skills/drizzle-safe-migrations/references/production-playbook.md +47 -0
  730. package/vendor/skills/skills/effect-ts/SKILL.md +232 -0
  731. package/vendor/skills/skills/effect-ts/references/api-platform-observability.md +194 -0
  732. package/vendor/skills/skills/effect-ts/references/batching-and-caching.md +208 -0
  733. package/vendor/skills/skills/effect-ts/references/class-patterns.md +711 -0
  734. package/vendor/skills/skills/effect-ts/references/concurrency-and-resources.md +199 -0
  735. package/vendor/skills/skills/effect-ts/references/construction-and-style.md +138 -0
  736. package/vendor/skills/skills/effect-ts/references/control-flow-and-runtime.md +216 -0
  737. package/vendor/skills/skills/effect-ts/references/core-patterns.md +48 -0
  738. package/vendor/skills/skills/effect-ts/references/data-and-testing.md +200 -0
  739. package/vendor/skills/skills/effect-ts/references/data-types.md +705 -0
  740. package/vendor/skills/skills/effect-ts/references/error-handling-patterns.md +498 -0
  741. package/vendor/skills/skills/effect-ts/references/foundations.md +171 -0
  742. package/vendor/skills/skills/effect-ts/references/library-development-patterns.md +441 -0
  743. package/vendor/skills/skills/effect-ts/references/pattern-matching.md +363 -0
  744. package/vendor/skills/skills/effect-ts/references/quality-tooling-and-resources.md +240 -0
  745. package/vendor/skills/skills/effect-ts/references/schema-errors-config.md +486 -0
  746. package/vendor/skills/skills/effect-ts/references/schema-transforms-and-filters.md +293 -0
  747. package/vendor/skills/skills/effect-ts/references/sink.md +282 -0
  748. package/vendor/skills/skills/effect-ts/references/streams-deep-dive.md +649 -0
  749. package/vendor/skills/skills/effect-ts/references/testing-patterns.md +566 -0
  750. package/vendor/skills/skills/electron-builder/SKILL.md +447 -0
  751. package/vendor/skills/skills/electron-builder/references/auto-update.md +250 -0
  752. package/vendor/skills/skills/electron-builder/references/code-signing.md +213 -0
  753. package/vendor/skills/skills/electron-builder/references/configuration.md +229 -0
  754. package/vendor/skills/skills/electron-builder/references/hooks-and-programmatic.md +337 -0
  755. package/vendor/skills/skills/electron-builder/references/platform-targets.md +324 -0
  756. package/vendor/skills/skills/electron-builder/references/publishing.md +263 -0
  757. package/vendor/skills/skills/electron-dev/SKILL.md +195 -0
  758. package/vendor/skills/skills/electron-dev/references/patterns.md +825 -0
  759. package/vendor/skills/skills/electron-release/SKILL.md +216 -0
  760. package/vendor/skills/skills/electron-release/references/patterns.md +464 -0
  761. package/vendor/skills/skills/elysia/SKILL.md +155 -0
  762. package/vendor/skills/skills/elysia/references/patterns.md +569 -0
  763. package/vendor/skills/skills/es-toolkit/SKILL.md +45 -0
  764. package/vendor/skills/skills/es-toolkit/references/patterns.md +136 -0
  765. package/vendor/skills/skills/evolution-api/SKILL.md +312 -0
  766. package/vendor/skills/skills/evolution-api/references/api-endpoints.md +174 -0
  767. package/vendor/skills/skills/evolution-api/references/environment-variables.md +156 -0
  768. package/vendor/skills/skills/evolution-api/references/events.md +101 -0
  769. package/vendor/skills/skills/exa-web-search-free/.clawhub/origin.json +7 -0
  770. package/vendor/skills/skills/exa-web-search-free/SKILL.md +96 -0
  771. package/vendor/skills/skills/exa-web-search-free/references/examples.md +156 -0
  772. package/vendor/skills/skills/executing-plans/SKILL.md +87 -0
  773. package/vendor/skills/skills/find-rules/SKILL.md +184 -0
  774. package/vendor/skills/skills/find-skills/SKILL.md +133 -0
  775. package/vendor/skills/skills/firecrawl/SKILL.md +126 -0
  776. package/vendor/skills/skills/firecrawl/rules/install.md +63 -0
  777. package/vendor/skills/skills/firecrawl/rules/security.md +26 -0
  778. package/vendor/skills/skills/fix-coderabbit-review/SKILL.md +116 -0
  779. package/vendor/skills/skills/fix-coderabbit-review/agents/openai.yaml +3 -0
  780. package/vendor/skills/skills/fix-coderabbit-review/scripts/pr-review.ts +1182 -0
  781. package/vendor/skills/skills/fix-coderabbit-review/scripts/resolve_pr_issues.sh +228 -0
  782. package/vendor/skills/skills/fixing-motion-performance/SKILL.md +128 -0
  783. package/vendor/skills/skills/frontend-design/SKILL.md +45 -0
  784. package/vendor/skills/skills/fundraising/README.md +14 -0
  785. package/vendor/skills/skills/fundraising/SKILL.md +136 -0
  786. package/vendor/skills/skills/fundraising/references/CHECKLISTS.md +49 -0
  787. package/vendor/skills/skills/fundraising/references/EXAMPLES.md +10 -0
  788. package/vendor/skills/skills/fundraising/references/INTAKE.md +38 -0
  789. package/vendor/skills/skills/fundraising/references/RUBRIC.md +39 -0
  790. package/vendor/skills/skills/fundraising/references/SOURCE_SUMMARY.md +23 -0
  791. package/vendor/skills/skills/fundraising/references/TEMPLATES.md +201 -0
  792. package/vendor/skills/skills/fundraising/references/WORKFLOW.md +84 -0
  793. package/vendor/skills/skills/fundraising/skillpack.json +13 -0
  794. package/vendor/skills/skills/game-changing-features/README.md +230 -0
  795. package/vendor/skills/skills/game-changing-features/SKILL.md +287 -0
  796. package/vendor/skills/skills/git-rebase/SKILL.md +422 -0
  797. package/vendor/skills/skills/git-rebase/references/automation.md +25 -0
  798. package/vendor/skills/skills/git-rebase/references/resolution-patterns.md +76 -0
  799. package/vendor/skills/skills/git-rebase/references/scripts-tools.md +49 -0
  800. package/vendor/skills/skills/git-rebase/references/strategies.md +367 -0
  801. package/vendor/skills/skills/git-rebase/references/troubleshooting.md +70 -0
  802. package/vendor/skills/skills/git-rebase/scripts/analyze-conflicts.sh +107 -0
  803. package/vendor/skills/skills/git-rebase/scripts/pre-rebase-backup.sh +94 -0
  804. package/vendor/skills/skills/git-rebase/scripts/validate-merge.sh +106 -0
  805. package/vendor/skills/skills/google-ads/SKILL.md +197 -0
  806. package/vendor/skills/skills/google-ads/_meta.json +22 -0
  807. package/vendor/skills/skills/google-ads/references/api-setup.md +337 -0
  808. package/vendor/skills/skills/google-ads/references/browser-workflows.md +294 -0
  809. package/vendor/skills/skills/helm-chart-scaffolding/SKILL.md +566 -0
  810. package/vendor/skills/skills/helm-chart-scaffolding/assets/Chart.yaml.template +42 -0
  811. package/vendor/skills/skills/helm-chart-scaffolding/assets/values.yaml.template +185 -0
  812. package/vendor/skills/skills/helm-chart-scaffolding/references/chart-structure.md +509 -0
  813. package/vendor/skills/skills/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
  814. package/vendor/skills/skills/hetzner-server/SKILL.md +278 -0
  815. package/vendor/skills/skills/hono/SKILL.md +90 -0
  816. package/vendor/skills/skills/hormozi-ad-factory/SKILL.md +153 -0
  817. package/vendor/skills/skills/hormozi-ad-factory/assets/output-template.md +132 -0
  818. package/vendor/skills/skills/hormozi-ad-factory/references/cta-templates.md +84 -0
  819. package/vendor/skills/skills/hormozi-ad-factory/references/hook-formulas.md +137 -0
  820. package/vendor/skills/skills/hormozi-ad-factory/references/meat-formats.md +133 -0
  821. package/vendor/skills/skills/humanizer/README.md +122 -0
  822. package/vendor/skills/skills/humanizer/SKILL.md +493 -0
  823. package/vendor/skills/skills/inngest/SKILL.md +62 -0
  824. package/vendor/skills/skills/interface-design/SKILL.md +402 -0
  825. package/vendor/skills/skills/interface-design/references/critique.md +67 -0
  826. package/vendor/skills/skills/interface-design/references/example.md +87 -0
  827. package/vendor/skills/skills/interface-design/references/principles.md +235 -0
  828. package/vendor/skills/skills/interface-design/references/validation.md +51 -0
  829. package/vendor/skills/skills/k8s-security-policies/SKILL.md +352 -0
  830. package/vendor/skills/skills/k8s-security-policies/assets/network-policy-template.yaml +176 -0
  831. package/vendor/skills/skills/k8s-security-policies/references/rbac-patterns.md +199 -0
  832. package/vendor/skills/skills/kubernetes-specialist/SKILL.md +244 -0
  833. package/vendor/skills/skills/kubernetes-specialist/references/configuration.md +452 -0
  834. package/vendor/skills/skills/kubernetes-specialist/references/cost-optimization.md +458 -0
  835. package/vendor/skills/skills/kubernetes-specialist/references/custom-operators.md +563 -0
  836. package/vendor/skills/skills/kubernetes-specialist/references/gitops.md +531 -0
  837. package/vendor/skills/skills/kubernetes-specialist/references/helm-charts.md +912 -0
  838. package/vendor/skills/skills/kubernetes-specialist/references/multi-cluster.md +507 -0
  839. package/vendor/skills/skills/kubernetes-specialist/references/networking.md +447 -0
  840. package/vendor/skills/skills/kubernetes-specialist/references/service-mesh.md +459 -0
  841. package/vendor/skills/skills/kubernetes-specialist/references/storage.md +535 -0
  842. package/vendor/skills/skills/kubernetes-specialist/references/troubleshooting.md +416 -0
  843. package/vendor/skills/skills/kubernetes-specialist/references/workloads.md +377 -0
  844. package/vendor/skills/skills/landing-page-design/SKILL.md +243 -0
  845. package/vendor/skills/skills/lesson-learned/README.md +65 -0
  846. package/vendor/skills/skills/lesson-learned/SKILL.md +107 -0
  847. package/vendor/skills/skills/lesson-learned/references/anti-patterns.md +55 -0
  848. package/vendor/skills/skills/lesson-learned/references/se-principles.md +109 -0
  849. package/vendor/skills/skills/mastra/SKILL.md +173 -0
  850. package/vendor/skills/skills/mastra/references/common-errors.md +535 -0
  851. package/vendor/skills/skills/mastra/references/create-mastra.md +220 -0
  852. package/vendor/skills/skills/mastra/references/embedded-docs.md +99 -0
  853. package/vendor/skills/skills/mastra/references/migration-guide.md +180 -0
  854. package/vendor/skills/skills/mastra/references/remote-docs.md +193 -0
  855. package/vendor/skills/skills/mermaid-diagrams/README.md +246 -0
  856. package/vendor/skills/skills/mermaid-diagrams/SKILL.md +228 -0
  857. package/vendor/skills/skills/mermaid-diagrams/references/advanced-features.md +567 -0
  858. package/vendor/skills/skills/mermaid-diagrams/references/architecture-diagrams.md +192 -0
  859. package/vendor/skills/skills/mermaid-diagrams/references/c4-diagrams.md +416 -0
  860. package/vendor/skills/skills/mermaid-diagrams/references/class-diagrams.md +376 -0
  861. package/vendor/skills/skills/mermaid-diagrams/references/erd-diagrams.md +519 -0
  862. package/vendor/skills/skills/mermaid-diagrams/references/flowcharts.md +478 -0
  863. package/vendor/skills/skills/mermaid-diagrams/references/sequence-diagrams.md +406 -0
  864. package/vendor/skills/skills/motion/.claude-plugin/plugin.json +12 -0
  865. package/vendor/skills/skills/motion/SKILL.md +874 -0
  866. package/vendor/skills/skills/motion/references/common-patterns.md +247 -0
  867. package/vendor/skills/skills/motion/references/motion-vs-auto-animate.md +714 -0
  868. package/vendor/skills/skills/motion/references/nextjs-integration.md +694 -0
  869. package/vendor/skills/skills/motion/references/performance-optimization.md +898 -0
  870. package/vendor/skills/skills/motion/rules/motion.md +91 -0
  871. package/vendor/skills/skills/motion/scripts/init-motion.sh +241 -0
  872. package/vendor/skills/skills/motion/scripts/optimize-bundle.sh +215 -0
  873. package/vendor/skills/skills/motion/templates/layout-transitions.tsx +608 -0
  874. package/vendor/skills/skills/motion/templates/motion-nextjs-client.tsx +490 -0
  875. package/vendor/skills/skills/motion/templates/motion-vite-basic.tsx +366 -0
  876. package/vendor/skills/skills/motion/templates/scroll-parallax.tsx +506 -0
  877. package/vendor/skills/skills/motion/templates/ui-components.tsx +723 -0
  878. package/vendor/skills/skills/motion-react/SKILL.md +376 -0
  879. package/vendor/skills/skills/motion-react/references/animation-api.md +231 -0
  880. package/vendor/skills/skills/motion-react/references/gestures-and-drag.md +179 -0
  881. package/vendor/skills/skills/motion-react/references/hooks-and-motion-values.md +333 -0
  882. package/vendor/skills/skills/motion-react/references/layout-animations.md +208 -0
  883. package/vendor/skills/skills/motion-react/references/scroll-animations.md +229 -0
  884. package/vendor/skills/skills/motion-react/references/transitions-api.md +162 -0
  885. package/vendor/skills/skills/nano-banana-pro/SKILL.md +58 -0
  886. package/vendor/skills/skills/nano-banana-pro/scripts/generate_image.py +184 -0
  887. package/vendor/skills/skills/nano-banana-prompting/SKILL.md +149 -0
  888. package/vendor/skills/skills/nano-banana-prompting/references/guide.md +403 -0
  889. package/vendor/skills/skills/next-best-practices/SKILL.md +171 -0
  890. package/vendor/skills/skills/next-best-practices/async-patterns.md +84 -0
  891. package/vendor/skills/skills/next-best-practices/bundling.md +182 -0
  892. package/vendor/skills/skills/next-best-practices/data-patterns.md +300 -0
  893. package/vendor/skills/skills/next-best-practices/debug-tricks.md +122 -0
  894. package/vendor/skills/skills/next-best-practices/directives.md +74 -0
  895. package/vendor/skills/skills/next-best-practices/error-handling.md +228 -0
  896. package/vendor/skills/skills/next-best-practices/file-conventions.md +141 -0
  897. package/vendor/skills/skills/next-best-practices/font.md +246 -0
  898. package/vendor/skills/skills/next-best-practices/functions.md +108 -0
  899. package/vendor/skills/skills/next-best-practices/hydration-error.md +86 -0
  900. package/vendor/skills/skills/next-best-practices/image.md +173 -0
  901. package/vendor/skills/skills/next-best-practices/metadata.md +292 -0
  902. package/vendor/skills/skills/next-best-practices/parallel-routes.md +286 -0
  903. package/vendor/skills/skills/next-best-practices/route-handlers.md +143 -0
  904. package/vendor/skills/skills/next-best-practices/rsc-boundaries.md +160 -0
  905. package/vendor/skills/skills/next-best-practices/runtime-selection.md +40 -0
  906. package/vendor/skills/skills/next-best-practices/scripts.md +137 -0
  907. package/vendor/skills/skills/next-best-practices/self-hosting.md +375 -0
  908. package/vendor/skills/skills/next-best-practices/suspense-boundaries.md +67 -0
  909. package/vendor/skills/skills/no-workarounds/SKILL.md +447 -0
  910. package/vendor/skills/skills/no-workarounds/references/philosophical-foundations.md +111 -0
  911. package/vendor/skills/skills/no-workarounds/references/workaround-catalog.md +565 -0
  912. package/vendor/skills/skills/organization-best-practices/SKILL.md +478 -0
  913. package/vendor/skills/skills/outside-to-issue/SKILL.md +105 -0
  914. package/vendor/skills/skills/pal/SKILL.md +184 -0
  915. package/vendor/skills/skills/pal/references/analyze.md +77 -0
  916. package/vendor/skills/skills/pal/references/debug.md +78 -0
  917. package/vendor/skills/skills/pal/references/planner.md +101 -0
  918. package/vendor/skills/skills/pal/references/refactor.md +88 -0
  919. package/vendor/skills/skills/pal/references/review.md +61 -0
  920. package/vendor/skills/skills/pal/references/tracer.md +66 -0
  921. package/vendor/skills/skills/perplexity/README.md +212 -0
  922. package/vendor/skills/skills/perplexity/SKILL.md +143 -0
  923. package/vendor/skills/skills/pitch-deck/SKILL.md +259 -0
  924. package/vendor/skills/skills/pitch-deck/index.js +9 -0
  925. package/vendor/skills/skills/pitch-deck/package.json +11 -0
  926. package/vendor/skills/skills/pitch-deck/references/pitch_deck_best_practices.md +241 -0
  927. package/vendor/skills/skills/pitch-deck/scripts/create_pitch_deck.py +298 -0
  928. package/vendor/skills/skills/pitch-deck-visuals/SKILL.md +215 -0
  929. package/vendor/skills/skills/pitch-deck-visuals/_meta.json +11 -0
  930. package/vendor/skills/skills/pitch-gen/README.md +22 -0
  931. package/vendor/skills/skills/pitch-gen/SKILL.md +78 -0
  932. package/vendor/skills/skills/pitch-gen/_meta.json +11 -0
  933. package/vendor/skills/skills/pitch-gen/package-lock.json +876 -0
  934. package/vendor/skills/skills/pitch-gen/package.json +35 -0
  935. package/vendor/skills/skills/pitch-gen/src/cli.ts +26 -0
  936. package/vendor/skills/skills/pitch-gen/src/index.ts +18 -0
  937. package/vendor/skills/skills/pitch-gen/tsconfig.json +13 -0
  938. package/vendor/skills/skills/postgres-drizzle/SKILL.md +190 -0
  939. package/vendor/skills/skills/postgres-drizzle/references/CHEATSHEET.md +424 -0
  940. package/vendor/skills/skills/postgres-drizzle/references/MIGRATIONS.md +545 -0
  941. package/vendor/skills/skills/postgres-drizzle/references/PERFORMANCE.md +564 -0
  942. package/vendor/skills/skills/postgres-drizzle/references/POSTGRES.md +590 -0
  943. package/vendor/skills/skills/postgres-drizzle/references/QUERIES.md +701 -0
  944. package/vendor/skills/skills/postgres-drizzle/references/RELATIONS.md +651 -0
  945. package/vendor/skills/skills/postgres-drizzle/references/SCHEMA.md +574 -0
  946. package/vendor/skills/skills/pptx-creator/SKILL.md +239 -0
  947. package/vendor/skills/skills/pptx-creator/_meta.json +11 -0
  948. package/vendor/skills/skills/pptx-creator/references/outline-format.md +127 -0
  949. package/vendor/skills/skills/pptx-creator/scripts/analyze_template.py +182 -0
  950. package/vendor/skills/skills/pptx-creator/scripts/create_pptx.py +488 -0
  951. package/vendor/skills/skills/pptx-creator/scripts/create_template.py +427 -0
  952. package/vendor/skills/skills/pptx-creator/scripts/use_template.py +195 -0
  953. package/vendor/skills/skills/pptx-creator/templates/templates.json +70 -0
  954. package/vendor/skills/skills/professional-communication/README.md +234 -0
  955. package/vendor/skills/skills/professional-communication/SKILL.md +272 -0
  956. package/vendor/skills/skills/professional-communication/references/email-templates.md +300 -0
  957. package/vendor/skills/skills/professional-communication/references/jargon-simplification.md +164 -0
  958. package/vendor/skills/skills/professional-communication/references/meeting-structures.md +333 -0
  959. package/vendor/skills/skills/professional-communication/references/remote-async-communication.md +310 -0
  960. package/vendor/skills/skills/promo-video/SKILL.md +465 -0
  961. package/vendor/skills/skills/promo-video/metallic-swoosh.md +94 -0
  962. package/vendor/skills/skills/promo-video/music/inspired-ambient-141686.mp3 +0 -0
  963. package/vendor/skills/skills/promo-video/music/motivational-day-112790.mp3 +0 -0
  964. package/vendor/skills/skills/promo-video/music/the-upbeat-inspiring-corporate-142313.mp3 +0 -0
  965. package/vendor/skills/skills/promo-video/promo-patterns.md +184 -0
  966. package/vendor/skills/skills/promo-video/scripts/generate_voiceover.py +266 -0
  967. package/vendor/skills/skills/promo-video/voiceover.md +358 -0
  968. package/vendor/skills/skills/qa-test-planner/README.md +394 -0
  969. package/vendor/skills/skills/qa-test-planner/SKILL.md +827 -0
  970. package/vendor/skills/skills/qa-test-planner/references/bug_report_templates.md +457 -0
  971. package/vendor/skills/skills/qa-test-planner/references/figma_validation.md +381 -0
  972. package/vendor/skills/skills/qa-test-planner/references/regression_testing.md +406 -0
  973. package/vendor/skills/skills/qa-test-planner/references/test_case_templates.md +457 -0
  974. package/vendor/skills/skills/qa-test-planner/scripts/create_bug_report.sh +276 -0
  975. package/vendor/skills/skills/qa-test-planner/scripts/generate_test_cases.sh +302 -0
  976. package/vendor/skills/skills/ratatui-tui/SKILL.md +422 -0
  977. package/vendor/skills/skills/ratatui-tui/assets/templates/async-app/Cargo.lock +1914 -0
  978. package/vendor/skills/skills/ratatui-tui/assets/templates/async-app/Cargo.toml +11 -0
  979. package/vendor/skills/skills/ratatui-tui/assets/templates/async-app/src/main.rs +122 -0
  980. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/Cargo.lock +2433 -0
  981. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/Cargo.toml +24 -0
  982. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/src/action.rs +16 -0
  983. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/src/app.rs +97 -0
  984. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/src/config.rs +67 -0
  985. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/src/event.rs +44 -0
  986. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/src/logging.rs +34 -0
  987. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/src/main.rs +51 -0
  988. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/src/tui.rs +59 -0
  989. package/vendor/skills/skills/ratatui-tui/assets/templates/component-app/src/ui.rs +65 -0
  990. package/vendor/skills/skills/ratatui-tui/assets/templates/hello-world/Cargo.lock +1511 -0
  991. package/vendor/skills/skills/ratatui-tui/assets/templates/hello-world/Cargo.toml +8 -0
  992. package/vendor/skills/skills/ratatui-tui/assets/templates/hello-world/src/main.rs +23 -0
  993. package/vendor/skills/skills/ratatui-tui/assets/templates/simple-app/Cargo.lock +1692 -0
  994. package/vendor/skills/skills/ratatui-tui/assets/templates/simple-app/Cargo.toml +9 -0
  995. package/vendor/skills/skills/ratatui-tui/assets/templates/simple-app/src/main.rs +100 -0
  996. package/vendor/skills/skills/ratatui-tui/references/architecture-patterns.md +448 -0
  997. package/vendor/skills/skills/ratatui-tui/references/async-patterns.md +426 -0
  998. package/vendor/skills/skills/ratatui-tui/references/image-integration.md +395 -0
  999. package/vendor/skills/skills/ratatui-tui/references/style-guide.md +249 -0
  1000. package/vendor/skills/skills/react/SKILL.md +195 -0
  1001. package/vendor/skills/skills/react/references/best-practices.md +1093 -0
  1002. package/vendor/skills/skills/react/references/useeffect-patterns.md +620 -0
  1003. package/vendor/skills/skills/receiving-code-review/SKILL.md +226 -0
  1004. package/vendor/skills/skills/remotion-best-practices/SKILL.md +61 -0
  1005. package/vendor/skills/skills/remotion-best-practices/rules/3d.md +86 -0
  1006. package/vendor/skills/skills/remotion-best-practices/rules/animations.md +27 -0
  1007. package/vendor/skills/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +165 -0
  1008. package/vendor/skills/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +89 -0
  1009. package/vendor/skills/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +101 -0
  1010. package/vendor/skills/skills/remotion-best-practices/rules/assets.md +78 -0
  1011. package/vendor/skills/skills/remotion-best-practices/rules/audio-visualization.md +195 -0
  1012. package/vendor/skills/skills/remotion-best-practices/rules/audio.md +167 -0
  1013. package/vendor/skills/skills/remotion-best-practices/rules/calculate-metadata.md +118 -0
  1014. package/vendor/skills/skills/remotion-best-practices/rules/can-decode.md +75 -0
  1015. package/vendor/skills/skills/remotion-best-practices/rules/charts.md +116 -0
  1016. package/vendor/skills/skills/remotion-best-practices/rules/compositions.md +153 -0
  1017. package/vendor/skills/skills/remotion-best-practices/rules/display-captions.md +176 -0
  1018. package/vendor/skills/skills/remotion-best-practices/rules/extract-frames.md +217 -0
  1019. package/vendor/skills/skills/remotion-best-practices/rules/ffmpeg.md +34 -0
  1020. package/vendor/skills/skills/remotion-best-practices/rules/fonts.md +152 -0
  1021. package/vendor/skills/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  1022. package/vendor/skills/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  1023. package/vendor/skills/skills/remotion-best-practices/rules/get-video-duration.md +60 -0
  1024. package/vendor/skills/skills/remotion-best-practices/rules/gifs.md +135 -0
  1025. package/vendor/skills/skills/remotion-best-practices/rules/images.md +130 -0
  1026. package/vendor/skills/skills/remotion-best-practices/rules/import-srt-captions.md +69 -0
  1027. package/vendor/skills/skills/remotion-best-practices/rules/light-leaks.md +73 -0
  1028. package/vendor/skills/skills/remotion-best-practices/rules/lottie.md +67 -0
  1029. package/vendor/skills/skills/remotion-best-practices/rules/maps.md +405 -0
  1030. package/vendor/skills/skills/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
  1031. package/vendor/skills/skills/remotion-best-practices/rules/measuring-text.md +140 -0
  1032. package/vendor/skills/skills/remotion-best-practices/rules/parameters.md +109 -0
  1033. package/vendor/skills/skills/remotion-best-practices/rules/sequencing.md +118 -0
  1034. package/vendor/skills/skills/remotion-best-practices/rules/sfx.md +26 -0
  1035. package/vendor/skills/skills/remotion-best-practices/rules/subtitles.md +36 -0
  1036. package/vendor/skills/skills/remotion-best-practices/rules/tailwind.md +11 -0
  1037. package/vendor/skills/skills/remotion-best-practices/rules/text-animations.md +20 -0
  1038. package/vendor/skills/skills/remotion-best-practices/rules/timing.md +179 -0
  1039. package/vendor/skills/skills/remotion-best-practices/rules/transcribe-captions.md +70 -0
  1040. package/vendor/skills/skills/remotion-best-practices/rules/transitions.md +193 -0
  1041. package/vendor/skills/skills/remotion-best-practices/rules/transparent-videos.md +102 -0
  1042. package/vendor/skills/skills/remotion-best-practices/rules/trimming.md +51 -0
  1043. package/vendor/skills/skills/remotion-best-practices/rules/videos.md +169 -0
  1044. package/vendor/skills/skills/remotion-best-practices/rules/voiceover.md +94 -0
  1045. package/vendor/skills/skills/requirements-clarity/README.md +275 -0
  1046. package/vendor/skills/skills/requirements-clarity/SKILL.md +358 -0
  1047. package/vendor/skills/skills/rivetkit/SKILL.md +1058 -0
  1048. package/vendor/skills/skills/rivetkit/index.json +540 -0
  1049. package/vendor/skills/skills/rivetkit/openapi.json +1223 -0
  1050. package/vendor/skills/skills/rivetkit/reference/actors/access-control.md +133 -0
  1051. package/vendor/skills/skills/rivetkit/reference/actors/actions.md +386 -0
  1052. package/vendor/skills/skills/rivetkit/reference/actors/ai-and-user-generated-actors.md +309 -0
  1053. package/vendor/skills/skills/rivetkit/reference/actors/appearance.md +186 -0
  1054. package/vendor/skills/skills/rivetkit/reference/actors/authentication.md +598 -0
  1055. package/vendor/skills/skills/rivetkit/reference/actors/communicating-between-actors.md +335 -0
  1056. package/vendor/skills/skills/rivetkit/reference/actors/connections.md +444 -0
  1057. package/vendor/skills/skills/rivetkit/reference/actors/debugging.md +378 -0
  1058. package/vendor/skills/skills/rivetkit/reference/actors/design-patterns.md +630 -0
  1059. package/vendor/skills/skills/rivetkit/reference/actors/destroy.md +116 -0
  1060. package/vendor/skills/skills/rivetkit/reference/actors/ephemeral-variables.md +178 -0
  1061. package/vendor/skills/skills/rivetkit/reference/actors/errors.md +442 -0
  1062. package/vendor/skills/skills/rivetkit/reference/actors/events.md +393 -0
  1063. package/vendor/skills/skills/rivetkit/reference/actors/fetch-and-websocket-handler.md +9 -0
  1064. package/vendor/skills/skills/rivetkit/reference/actors/helper-types.md +9 -0
  1065. package/vendor/skills/skills/rivetkit/reference/actors/http-api.md +11 -0
  1066. package/vendor/skills/skills/rivetkit/reference/actors/input.md +308 -0
  1067. package/vendor/skills/skills/rivetkit/reference/actors/keys.md +269 -0
  1068. package/vendor/skills/skills/rivetkit/reference/actors/kv.md +126 -0
  1069. package/vendor/skills/skills/rivetkit/reference/actors/lifecycle.md +1052 -0
  1070. package/vendor/skills/skills/rivetkit/reference/actors/limits.md +143 -0
  1071. package/vendor/skills/skills/rivetkit/reference/actors/metadata.md +149 -0
  1072. package/vendor/skills/skills/rivetkit/reference/actors/postgres.md +262 -0
  1073. package/vendor/skills/skills/rivetkit/reference/actors/queues.md +414 -0
  1074. package/vendor/skills/skills/rivetkit/reference/actors/quickstart/backend.md +164 -0
  1075. package/vendor/skills/skills/rivetkit/reference/actors/quickstart/cloudflare-workers.md +412 -0
  1076. package/vendor/skills/skills/rivetkit/reference/actors/quickstart/next-js.md +122 -0
  1077. package/vendor/skills/skills/rivetkit/reference/actors/quickstart/react.md +144 -0
  1078. package/vendor/skills/skills/rivetkit/reference/actors/request-handler.md +241 -0
  1079. package/vendor/skills/skills/rivetkit/reference/actors/scaling.md +9 -0
  1080. package/vendor/skills/skills/rivetkit/reference/actors/schedule.md +102 -0
  1081. package/vendor/skills/skills/rivetkit/reference/actors/sharing-and-joining-state.md +9 -0
  1082. package/vendor/skills/skills/rivetkit/reference/actors/sqlite-drizzle.md +245 -0
  1083. package/vendor/skills/skills/rivetkit/reference/actors/sqlite.md +237 -0
  1084. package/vendor/skills/skills/rivetkit/reference/actors/state.md +204 -0
  1085. package/vendor/skills/skills/rivetkit/reference/actors/testing.md +237 -0
  1086. package/vendor/skills/skills/rivetkit/reference/actors/types.md +106 -0
  1087. package/vendor/skills/skills/rivetkit/reference/actors/versions.md +109 -0
  1088. package/vendor/skills/skills/rivetkit/reference/actors/websocket-handler.md +320 -0
  1089. package/vendor/skills/skills/rivetkit/reference/actors/workflows.md +1958 -0
  1090. package/vendor/skills/skills/rivetkit/reference/clients/javascript.md +236 -0
  1091. package/vendor/skills/skills/rivetkit/reference/clients/react.md +270 -0
  1092. package/vendor/skills/skills/rivetkit/reference/clients/swift.md +459 -0
  1093. package/vendor/skills/skills/rivetkit/reference/clients/swiftui.md +364 -0
  1094. package/vendor/skills/skills/rivetkit/reference/connect/aws-ecs.md +14 -0
  1095. package/vendor/skills/skills/rivetkit/reference/connect/aws-lambda.md +9 -0
  1096. package/vendor/skills/skills/rivetkit/reference/connect/cloudflare-workers.md +125 -0
  1097. package/vendor/skills/skills/rivetkit/reference/connect/freestyle.md +132 -0
  1098. package/vendor/skills/skills/rivetkit/reference/connect/gcp-cloud-run.md +75 -0
  1099. package/vendor/skills/skills/rivetkit/reference/connect/hetzner.md +9 -0
  1100. package/vendor/skills/skills/rivetkit/reference/connect/kubernetes.md +109 -0
  1101. package/vendor/skills/skills/rivetkit/reference/connect/railway.md +44 -0
  1102. package/vendor/skills/skills/rivetkit/reference/connect/supabase.md +9 -0
  1103. package/vendor/skills/skills/rivetkit/reference/connect/vercel.md +158 -0
  1104. package/vendor/skills/skills/rivetkit/reference/connect/vm-and-bare-metal.md +89 -0
  1105. package/vendor/skills/skills/rivetkit/reference/cookbook/multiplayer-game.md +714 -0
  1106. package/vendor/skills/skills/rivetkit/reference/general/actor-configuration.md +42 -0
  1107. package/vendor/skills/skills/rivetkit/reference/general/architecture.md +452 -0
  1108. package/vendor/skills/skills/rivetkit/reference/general/cors.md +71 -0
  1109. package/vendor/skills/skills/rivetkit/reference/general/docs-for-llms.md +56 -0
  1110. package/vendor/skills/skills/rivetkit/reference/general/edge.md +40 -0
  1111. package/vendor/skills/skills/rivetkit/reference/general/endpoints.md +129 -0
  1112. package/vendor/skills/skills/rivetkit/reference/general/environment-variables.md +73 -0
  1113. package/vendor/skills/skills/rivetkit/reference/general/http-server.md +144 -0
  1114. package/vendor/skills/skills/rivetkit/reference/general/logging.md +153 -0
  1115. package/vendor/skills/skills/rivetkit/reference/general/registry-configuration.md +98 -0
  1116. package/vendor/skills/skills/rivetkit/reference/general/runtime-modes.md +156 -0
  1117. package/vendor/skills/skills/rivetkit/reference/self-hosting/configuration.md +53 -0
  1118. package/vendor/skills/skills/rivetkit/reference/self-hosting/docker-compose.md +148 -0
  1119. package/vendor/skills/skills/rivetkit/reference/self-hosting/docker-container.md +93 -0
  1120. package/vendor/skills/skills/rivetkit/reference/self-hosting/filesystem.md +48 -0
  1121. package/vendor/skills/skills/rivetkit/reference/self-hosting/install.md +33 -0
  1122. package/vendor/skills/skills/rivetkit/reference/self-hosting/kubernetes.md +496 -0
  1123. package/vendor/skills/skills/rivetkit/reference/self-hosting/multi-region.md +11 -0
  1124. package/vendor/skills/skills/rivetkit/reference/self-hosting/postgres.md +193 -0
  1125. package/vendor/skills/skills/rivetkit/reference/self-hosting/railway.md +71 -0
  1126. package/vendor/skills/skills/rivetkit-client-javascript/SKILL.md +259 -0
  1127. package/vendor/skills/skills/rivetkit-client-javascript/index.json +7 -0
  1128. package/vendor/skills/skills/rivetkit-client-react/SKILL.md +293 -0
  1129. package/vendor/skills/skills/rivetkit-client-react/index.json +7 -0
  1130. package/vendor/skills/skills/rust-async-patterns/SKILL.md +519 -0
  1131. package/vendor/skills/skills/rust-best-practices/SKILL.md +104 -0
  1132. package/vendor/skills/skills/rust-best-practices/references/chapter_01.md +591 -0
  1133. package/vendor/skills/skills/rust-best-practices/references/chapter_02.md +119 -0
  1134. package/vendor/skills/skills/rust-best-practices/references/chapter_03.md +226 -0
  1135. package/vendor/skills/skills/rust-best-practices/references/chapter_04.md +187 -0
  1136. package/vendor/skills/skills/rust-best-practices/references/chapter_05.md +406 -0
  1137. package/vendor/skills/skills/rust-best-practices/references/chapter_06.md +168 -0
  1138. package/vendor/skills/skills/rust-best-practices/references/chapter_07.md +231 -0
  1139. package/vendor/skills/skills/rust-best-practices/references/chapter_08.md +276 -0
  1140. package/vendor/skills/skills/rust-best-practices/references/chapter_09.md +259 -0
  1141. package/vendor/skills/skills/rust-coding-guidelines/SKILL.md +95 -0
  1142. package/vendor/skills/skills/rust-coding-guidelines/index/rules-index.md +7 -0
  1143. package/vendor/skills/skills/rust-engineer/SKILL.md +89 -0
  1144. package/vendor/skills/skills/rust-engineer/references/async.md +458 -0
  1145. package/vendor/skills/skills/rust-engineer/references/error-handling.md +334 -0
  1146. package/vendor/skills/skills/rust-engineer/references/ownership.md +278 -0
  1147. package/vendor/skills/skills/rust-engineer/references/testing.md +470 -0
  1148. package/vendor/skills/skills/rust-engineer/references/traits.md +413 -0
  1149. package/vendor/skills/skills/sales-methodology-implementer/SKILL.md +735 -0
  1150. package/vendor/skills/skills/sentry-cli/SKILL.md +459 -0
  1151. package/vendor/skills/skills/shadcn/SKILL.md +141 -0
  1152. package/vendor/skills/skills/shadcn/references/patterns.md +587 -0
  1153. package/vendor/skills/skills/shadcn-ui/SKILL.md +1911 -0
  1154. package/vendor/skills/skills/shadcn-ui/references/chart.md +303 -0
  1155. package/vendor/skills/skills/shadcn-ui/references/learn.md +150 -0
  1156. package/vendor/skills/skills/shadcn-ui/references/official-ui-reference.md +1721 -0
  1157. package/vendor/skills/skills/shadcn-ui/references/reference.md +608 -0
  1158. package/vendor/skills/skills/shadcn-ui/references/ui-reference.md +1588 -0
  1159. package/vendor/skills/skills/ship-learn-next/README.md +191 -0
  1160. package/vendor/skills/skills/ship-learn-next/SKILL.md +359 -0
  1161. package/vendor/skills/skills/skill-writter/SKILL.md +408 -0
  1162. package/vendor/skills/skills/skills-best-practices/SKILL.md +51 -0
  1163. package/vendor/skills/skills/skills-best-practices/assets/SKILL.template.md +24 -0
  1164. package/vendor/skills/skills/skills-best-practices/references/checklist.md +37 -0
  1165. package/vendor/skills/skills/skills-best-practices/scripts/validate-metadata.py +46 -0
  1166. package/vendor/skills/skills/sourcebot/SKILL.md +89 -0
  1167. package/vendor/skills/skills/startup-validator/SKILL.md +425 -0
  1168. package/vendor/skills/skills/startup-validator/index.js +9 -0
  1169. package/vendor/skills/skills/startup-validator/package.json +11 -0
  1170. package/vendor/skills/skills/startup-validator/references/frameworks.md +134 -0
  1171. package/vendor/skills/skills/startup-validator/references/research_templates.md +191 -0
  1172. package/vendor/skills/skills/startup-validator/scripts/market_analyzer.py +290 -0
  1173. package/vendor/skills/skills/storybook/SKILL.md +440 -0
  1174. package/vendor/skills/skills/storybook-stories/SKILL.md +359 -0
  1175. package/vendor/skills/skills/storybook-stories/references/patterns.md +60 -0
  1176. package/vendor/skills/skills/stripe-best-practices/SKILL.md +30 -0
  1177. package/vendor/skills/skills/stripe-integration/SKILL.md +492 -0
  1178. package/vendor/skills/skills/stripe-subscriptions/SKILL.md +54 -0
  1179. package/vendor/skills/skills/stripe-webhooks/SKILL.md +163 -0
  1180. package/vendor/skills/skills/stripe-webhooks/examples/express/.env.example +5 -0
  1181. package/vendor/skills/skills/stripe-webhooks/examples/express/README.md +64 -0
  1182. package/vendor/skills/skills/stripe-webhooks/examples/express/package.json +19 -0
  1183. package/vendor/skills/skills/stripe-webhooks/examples/express/src/index.js +75 -0
  1184. package/vendor/skills/skills/stripe-webhooks/examples/express/test/webhook.test.js +129 -0
  1185. package/vendor/skills/skills/stripe-webhooks/examples/fastapi/.env.example +5 -0
  1186. package/vendor/skills/skills/stripe-webhooks/examples/fastapi/README.md +69 -0
  1187. package/vendor/skills/skills/stripe-webhooks/examples/fastapi/main.py +75 -0
  1188. package/vendor/skills/skills/stripe-webhooks/examples/fastapi/requirements.txt +6 -0
  1189. package/vendor/skills/skills/stripe-webhooks/examples/fastapi/test_webhook.py +121 -0
  1190. package/vendor/skills/skills/stripe-webhooks/examples/nextjs/.env.example +5 -0
  1191. package/vendor/skills/skills/stripe-webhooks/examples/nextjs/README.md +62 -0
  1192. package/vendor/skills/skills/stripe-webhooks/examples/nextjs/app/webhooks/stripe/route.ts +63 -0
  1193. package/vendor/skills/skills/stripe-webhooks/examples/nextjs/package.json +23 -0
  1194. package/vendor/skills/skills/stripe-webhooks/examples/nextjs/test/webhook.test.ts +139 -0
  1195. package/vendor/skills/skills/stripe-webhooks/examples/nextjs/vitest.config.ts +8 -0
  1196. package/vendor/skills/skills/stripe-webhooks/references/overview.md +62 -0
  1197. package/vendor/skills/skills/stripe-webhooks/references/setup.md +99 -0
  1198. package/vendor/skills/skills/stripe-webhooks/references/verification.md +154 -0
  1199. package/vendor/skills/skills/sync-provider/SKILL.md +348 -0
  1200. package/vendor/skills/skills/systematic-debugging/CREATION-LOG.md +133 -0
  1201. package/vendor/skills/skills/systematic-debugging/SKILL.md +305 -0
  1202. package/vendor/skills/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  1203. package/vendor/skills/skills/systematic-debugging/condition-based-waiting.md +120 -0
  1204. package/vendor/skills/skills/systematic-debugging/defense-in-depth.md +128 -0
  1205. package/vendor/skills/skills/systematic-debugging/find-polluter.sh +63 -0
  1206. package/vendor/skills/skills/systematic-debugging/root-cause-tracing.md +183 -0
  1207. package/vendor/skills/skills/systematic-debugging/test-academic.md +14 -0
  1208. package/vendor/skills/skills/systematic-debugging/test-pressure-1.md +65 -0
  1209. package/vendor/skills/skills/systematic-debugging/test-pressure-2.md +75 -0
  1210. package/vendor/skills/skills/systematic-debugging/test-pressure-3.md +75 -0
  1211. package/vendor/skills/skills/tailwindcss/SKILL.md +122 -0
  1212. package/vendor/skills/skills/tailwindcss/references/patterns.md +439 -0
  1213. package/vendor/skills/skills/tanstack/SKILL.md +278 -0
  1214. package/vendor/skills/skills/tanstack/references/form-patterns.md +638 -0
  1215. package/vendor/skills/skills/tanstack/references/query-patterns.md +343 -0
  1216. package/vendor/skills/skills/tanstack/references/router-patterns.md +373 -0
  1217. package/vendor/skills/skills/tanstack-query-best-practices/SKILL.md +115 -0
  1218. package/vendor/skills/skills/tanstack-query-best-practices/rules/cache-gc-time.md +93 -0
  1219. package/vendor/skills/skills/tanstack-query-best-practices/rules/cache-invalidation.md +114 -0
  1220. package/vendor/skills/skills/tanstack-query-best-practices/rules/cache-placeholder-vs-initial.md +152 -0
  1221. package/vendor/skills/skills/tanstack-query-best-practices/rules/cache-stale-time.md +80 -0
  1222. package/vendor/skills/skills/tanstack-query-best-practices/rules/err-error-boundaries.md +147 -0
  1223. package/vendor/skills/skills/tanstack-query-best-practices/rules/inf-page-params.md +119 -0
  1224. package/vendor/skills/skills/tanstack-query-best-practices/rules/mut-invalidate-queries.md +118 -0
  1225. package/vendor/skills/skills/tanstack-query-best-practices/rules/mut-mutation-state.md +164 -0
  1226. package/vendor/skills/skills/tanstack-query-best-practices/rules/mut-optimistic-updates.md +131 -0
  1227. package/vendor/skills/skills/tanstack-query-best-practices/rules/network-mode.md +168 -0
  1228. package/vendor/skills/skills/tanstack-query-best-practices/rules/parallel-use-queries.md +154 -0
  1229. package/vendor/skills/skills/tanstack-query-best-practices/rules/perf-select-transform.md +144 -0
  1230. package/vendor/skills/skills/tanstack-query-best-practices/rules/persist-queries.md +192 -0
  1231. package/vendor/skills/skills/tanstack-query-best-practices/rules/pf-intent-prefetch.md +137 -0
  1232. package/vendor/skills/skills/tanstack-query-best-practices/rules/qk-array-structure.md +50 -0
  1233. package/vendor/skills/skills/tanstack-query-best-practices/rules/qk-factory-pattern.md +104 -0
  1234. package/vendor/skills/skills/tanstack-query-best-practices/rules/qk-hierarchical-organization.md +76 -0
  1235. package/vendor/skills/skills/tanstack-query-best-practices/rules/qk-include-dependencies.md +62 -0
  1236. package/vendor/skills/skills/tanstack-query-best-practices/rules/qk-serializable.md +97 -0
  1237. package/vendor/skills/skills/tanstack-query-best-practices/rules/query-cancellation.md +168 -0
  1238. package/vendor/skills/skills/tanstack-query-best-practices/rules/ssr-dehydration.md +154 -0
  1239. package/vendor/skills/skills/tanstack-router-best-practices/SKILL.md +114 -0
  1240. package/vendor/skills/skills/tanstack-router-best-practices/rules/ctx-root-context.md +170 -0
  1241. package/vendor/skills/skills/tanstack-router-best-practices/rules/err-not-found.md +194 -0
  1242. package/vendor/skills/skills/tanstack-router-best-practices/rules/load-ensure-query-data.md +147 -0
  1243. package/vendor/skills/skills/tanstack-router-best-practices/rules/load-parallel.md +186 -0
  1244. package/vendor/skills/skills/tanstack-router-best-practices/rules/load-use-loaders.md +148 -0
  1245. package/vendor/skills/skills/tanstack-router-best-practices/rules/nav-link-component.md +171 -0
  1246. package/vendor/skills/skills/tanstack-router-best-practices/rules/nav-route-masks.md +195 -0
  1247. package/vendor/skills/skills/tanstack-router-best-practices/rules/org-virtual-routes.md +133 -0
  1248. package/vendor/skills/skills/tanstack-router-best-practices/rules/preload-intent.md +133 -0
  1249. package/vendor/skills/skills/tanstack-router-best-practices/rules/router-default-options.md +159 -0
  1250. package/vendor/skills/skills/tanstack-router-best-practices/rules/search-custom-serializer.md +198 -0
  1251. package/vendor/skills/skills/tanstack-router-best-practices/rules/search-validation.md +154 -0
  1252. package/vendor/skills/skills/tanstack-router-best-practices/rules/split-lazy-routes.md +148 -0
  1253. package/vendor/skills/skills/tanstack-router-best-practices/rules/ts-register-router.md +113 -0
  1254. package/vendor/skills/skills/tanstack-router-best-practices/rules/ts-use-from-param.md +130 -0
  1255. package/vendor/skills/skills/tanstack-start-best-practices/SKILL.md +110 -0
  1256. package/vendor/skills/skills/tanstack-start-best-practices/rules/api-routes.md +236 -0
  1257. package/vendor/skills/skills/tanstack-start-best-practices/rules/auth-route-protection.md +188 -0
  1258. package/vendor/skills/skills/tanstack-start-best-practices/rules/auth-session-management.md +189 -0
  1259. package/vendor/skills/skills/tanstack-start-best-practices/rules/deploy-adapters.md +197 -0
  1260. package/vendor/skills/skills/tanstack-start-best-practices/rules/env-functions.md +207 -0
  1261. package/vendor/skills/skills/tanstack-start-best-practices/rules/err-server-errors.md +189 -0
  1262. package/vendor/skills/skills/tanstack-start-best-practices/rules/file-separation.md +151 -0
  1263. package/vendor/skills/skills/tanstack-start-best-practices/rules/mw-request-middleware.md +157 -0
  1264. package/vendor/skills/skills/tanstack-start-best-practices/rules/sf-create-server-fn.md +146 -0
  1265. package/vendor/skills/skills/tanstack-start-best-practices/rules/sf-input-validation.md +168 -0
  1266. package/vendor/skills/skills/tanstack-start-best-practices/rules/ssr-hydration-safety.md +184 -0
  1267. package/vendor/skills/skills/tanstack-start-best-practices/rules/ssr-prerender.md +190 -0
  1268. package/vendor/skills/skills/tanstack-start-best-practices/rules/ssr-streaming.md +201 -0
  1269. package/vendor/skills/skills/tauri-v2/README.md +157 -0
  1270. package/vendor/skills/skills/tauri-v2/SKILL.md +378 -0
  1271. package/vendor/skills/skills/tauri-v2/assets/README.md +18 -0
  1272. package/vendor/skills/skills/tauri-v2/references/README.md +10 -0
  1273. package/vendor/skills/skills/tauri-v2/references/capabilities-reference.md +310 -0
  1274. package/vendor/skills/skills/tauri-v2/references/ipc-patterns.md +484 -0
  1275. package/vendor/skills/skills/tauri-v2/scripts/README.md +31 -0
  1276. package/vendor/skills/skills/tech-logos/SKILL.md +88 -0
  1277. package/vendor/skills/skills/terraform-style-guide/SKILL.md +357 -0
  1278. package/vendor/skills/skills/test-antipatterns/SKILL.md +309 -0
  1279. package/vendor/skills/skills/to-prompt/SKILL.md +90 -0
  1280. package/vendor/skills/skills/typescript-advanced/SKILL.md +760 -0
  1281. package/vendor/skills/skills/typescript-advanced/references/best-practices.md +358 -0
  1282. package/vendor/skills/skills/ui-ux-pro-max/SKILL.md +404 -0
  1283. package/vendor/skills/skills/ui-ux-pro-max/data/charts.csv +26 -0
  1284. package/vendor/skills/skills/ui-ux-pro-max/data/colors.csv +97 -0
  1285. package/vendor/skills/skills/ui-ux-pro-max/data/icons.csv +101 -0
  1286. package/vendor/skills/skills/ui-ux-pro-max/data/landing.csv +31 -0
  1287. package/vendor/skills/skills/ui-ux-pro-max/data/products.csv +97 -0
  1288. package/vendor/skills/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  1289. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  1290. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  1291. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  1292. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  1293. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  1294. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  1295. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  1296. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  1297. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  1298. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  1299. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  1300. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  1301. package/vendor/skills/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  1302. package/vendor/skills/skills/ui-ux-pro-max/data/styles.csv +68 -0
  1303. package/vendor/skills/skills/ui-ux-pro-max/data/typography.csv +58 -0
  1304. package/vendor/skills/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  1305. package/vendor/skills/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  1306. package/vendor/skills/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  1307. package/vendor/skills/skills/ui-ux-pro-max/scripts/core.py +253 -0
  1308. package/vendor/skills/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  1309. package/vendor/skills/skills/ui-ux-pro-max/scripts/search.py +114 -0
  1310. package/vendor/skills/skills/vercel-composition-patterns/AGENTS.md +917 -0
  1311. package/vendor/skills/skills/vercel-composition-patterns/SKILL.md +88 -0
  1312. package/vendor/skills/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +94 -0
  1313. package/vendor/skills/skills/vercel-composition-patterns/rules/architecture-compound-components.md +108 -0
  1314. package/vendor/skills/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +84 -0
  1315. package/vendor/skills/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +94 -0
  1316. package/vendor/skills/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
  1317. package/vendor/skills/skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
  1318. package/vendor/skills/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +103 -0
  1319. package/vendor/skills/skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
  1320. package/vendor/skills/skills/vercel-react-best-practices/AGENTS.md +2367 -0
  1321. package/vendor/skills/skills/vercel-react-best-practices/SKILL.md +127 -0
  1322. package/vendor/skills/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  1323. package/vendor/skills/skills/vercel-react-best-practices/rules/advanced-use-latest.md +49 -0
  1324. package/vendor/skills/skills/vercel-react-best-practices/rules/async-api-routes.md +35 -0
  1325. package/vendor/skills/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  1326. package/vendor/skills/skills/vercel-react-best-practices/rules/async-dependencies.md +37 -0
  1327. package/vendor/skills/skills/vercel-react-best-practices/rules/async-parallel.md +24 -0
  1328. package/vendor/skills/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  1329. package/vendor/skills/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  1330. package/vendor/skills/skills/vercel-react-best-practices/rules/bundle-conditional.md +37 -0
  1331. package/vendor/skills/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +48 -0
  1332. package/vendor/skills/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +34 -0
  1333. package/vendor/skills/skills/vercel-react-best-practices/rules/bundle-preload.md +44 -0
  1334. package/vendor/skills/skills/vercel-react-best-practices/rules/client-event-listeners.md +78 -0
  1335. package/vendor/skills/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +74 -0
  1336. package/vendor/skills/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  1337. package/vendor/skills/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  1338. package/vendor/skills/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +57 -0
  1339. package/vendor/skills/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  1340. package/vendor/skills/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  1341. package/vendor/skills/skills/vercel-react-best-practices/rules/js-cache-storage.md +68 -0
  1342. package/vendor/skills/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  1343. package/vendor/skills/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  1344. package/vendor/skills/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  1345. package/vendor/skills/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  1346. package/vendor/skills/skills/vercel-react-best-practices/rules/js-length-check-first.md +50 -0
  1347. package/vendor/skills/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  1348. package/vendor/skills/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  1349. package/vendor/skills/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  1350. package/vendor/skills/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  1351. package/vendor/skills/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
  1352. package/vendor/skills/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +32 -0
  1353. package/vendor/skills/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  1354. package/vendor/skills/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +36 -0
  1355. package/vendor/skills/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +72 -0
  1356. package/vendor/skills/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  1357. package/vendor/skills/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  1358. package/vendor/skills/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  1359. package/vendor/skills/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  1360. package/vendor/skills/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +77 -0
  1361. package/vendor/skills/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +56 -0
  1362. package/vendor/skills/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  1363. package/vendor/skills/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  1364. package/vendor/skills/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  1365. package/vendor/skills/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  1366. package/vendor/skills/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  1367. package/vendor/skills/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  1368. package/vendor/skills/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  1369. package/vendor/skills/skills/verification-before-completion/SKILL.md +147 -0
  1370. package/vendor/skills/skills/vitest/GENERATION.md +5 -0
  1371. package/vendor/skills/skills/vitest/SKILL.md +53 -0
  1372. package/vendor/skills/skills/vitest/references/advanced-environments.md +264 -0
  1373. package/vendor/skills/skills/vitest/references/advanced-projects.md +300 -0
  1374. package/vendor/skills/skills/vitest/references/advanced-type-testing.md +242 -0
  1375. package/vendor/skills/skills/vitest/references/advanced-vi.md +249 -0
  1376. package/vendor/skills/skills/vitest/references/core-cli.md +167 -0
  1377. package/vendor/skills/skills/vitest/references/core-config.md +177 -0
  1378. package/vendor/skills/skills/vitest/references/core-describe.md +193 -0
  1379. package/vendor/skills/skills/vitest/references/core-expect.md +207 -0
  1380. package/vendor/skills/skills/vitest/references/core-hooks.md +245 -0
  1381. package/vendor/skills/skills/vitest/references/core-test-api.md +237 -0
  1382. package/vendor/skills/skills/vitest/references/features-concurrency.md +250 -0
  1383. package/vendor/skills/skills/vitest/references/features-context.md +240 -0
  1384. package/vendor/skills/skills/vitest/references/features-coverage.md +202 -0
  1385. package/vendor/skills/skills/vitest/references/features-filtering.md +208 -0
  1386. package/vendor/skills/skills/vitest/references/features-mocking.md +272 -0
  1387. package/vendor/skills/skills/vitest/references/features-snapshots.md +207 -0
  1388. package/vendor/skills/skills/web-design-guidelines/SKILL.md +40 -0
  1389. package/vendor/skills/skills/workflow/SKILL.md +373 -0
  1390. package/vendor/skills/skills/wrangler/SKILL.md +871 -0
  1391. package/vendor/skills/skills/writing-clearly-and-concisely/README.md +167 -0
  1392. package/vendor/skills/skills/writing-clearly-and-concisely/SKILL.md +93 -0
  1393. package/vendor/skills/skills/writing-clearly-and-concisely/elements-of-style/01-introductory.md +3 -0
  1394. package/vendor/skills/skills/writing-clearly-and-concisely/elements-of-style/02-elementary-rules-of-usage.md +214 -0
  1395. package/vendor/skills/skills/writing-clearly-and-concisely/elements-of-style/03-elementary-principles-of-composition.md +398 -0
  1396. package/vendor/skills/skills/writing-clearly-and-concisely/elements-of-style/04-a-few-matters-of-form.md +89 -0
  1397. package/vendor/skills/skills/writing-clearly-and-concisely/elements-of-style/05-words-and-expressions-commonly-misused.md +348 -0
  1398. package/vendor/skills/skills/writing-clearly-and-concisely/signs-of-ai-writing.md +900 -0
  1399. package/vendor/skills/skills/xstate/SKILL.md +374 -0
  1400. package/vendor/skills/skills/xstate/references/machine-patterns.md +914 -0
  1401. package/vendor/skills/skills/xstate/references/query-patterns.md +661 -0
  1402. package/vendor/skills/skills/xstate/references/store-patterns.md +1032 -0
  1403. package/vendor/skills/skills/zod/AGENTS.md +97 -0
  1404. package/vendor/skills/skills/zod/README.md +79 -0
  1405. package/vendor/skills/skills/zod/SKILL.md +128 -0
  1406. package/vendor/skills/skills/zod/references/compose-intersection.md +143 -0
  1407. package/vendor/skills/skills/zod/references/compose-lazy-recursive.md +138 -0
  1408. package/vendor/skills/skills/zod/references/compose-pipe.md +114 -0
  1409. package/vendor/skills/skills/zod/references/compose-preprocess.md +131 -0
  1410. package/vendor/skills/skills/zod/references/compose-shared-schemas.md +142 -0
  1411. package/vendor/skills/skills/zod/references/error-avoid-throwing-in-refine.md +134 -0
  1412. package/vendor/skills/skills/zod/references/error-custom-messages.md +127 -0
  1413. package/vendor/skills/skills/zod/references/error-i18n.md +140 -0
  1414. package/vendor/skills/skills/zod/references/error-path-for-nested.md +135 -0
  1415. package/vendor/skills/skills/zod/references/error-use-flatten.md +135 -0
  1416. package/vendor/skills/skills/zod/references/object-discriminated-unions.md +136 -0
  1417. package/vendor/skills/skills/zod/references/object-extend-for-composition.md +146 -0
  1418. package/vendor/skills/skills/zod/references/object-optional-vs-nullable.md +120 -0
  1419. package/vendor/skills/skills/zod/references/object-partial-for-updates.md +124 -0
  1420. package/vendor/skills/skills/zod/references/object-pick-omit.md +147 -0
  1421. package/vendor/skills/skills/zod/references/object-strict-vs-strip.md +122 -0
  1422. package/vendor/skills/skills/zod/references/parse-async-for-async-refinements.md +127 -0
  1423. package/vendor/skills/skills/zod/references/parse-avoid-double-validation.md +130 -0
  1424. package/vendor/skills/skills/zod/references/parse-handle-all-issues.md +126 -0
  1425. package/vendor/skills/skills/zod/references/parse-never-trust-json.md +116 -0
  1426. package/vendor/skills/skills/zod/references/parse-use-safeparse.md +103 -0
  1427. package/vendor/skills/skills/zod/references/parse-validate-early.md +125 -0
  1428. package/vendor/skills/skills/zod/references/perf-arrays.md +154 -0
  1429. package/vendor/skills/skills/zod/references/perf-avoid-dynamic-creation.md +142 -0
  1430. package/vendor/skills/skills/zod/references/perf-cache-schemas.md +143 -0
  1431. package/vendor/skills/skills/zod/references/perf-lazy-loading.md +136 -0
  1432. package/vendor/skills/skills/zod/references/perf-zod-mini.md +118 -0
  1433. package/vendor/skills/skills/zod/references/refine-add-path.md +149 -0
  1434. package/vendor/skills/skills/zod/references/refine-catch.md +138 -0
  1435. package/vendor/skills/skills/zod/references/refine-defaults.md +132 -0
  1436. package/vendor/skills/skills/zod/references/refine-transform-coerce.md +103 -0
  1437. package/vendor/skills/skills/zod/references/refine-vs-superrefine.md +159 -0
  1438. package/vendor/skills/skills/zod/references/schema-avoid-optional-abuse.md +94 -0
  1439. package/vendor/skills/skills/zod/references/schema-coercion-for-form-data.md +89 -0
  1440. package/vendor/skills/skills/zod/references/schema-string-validations.md +87 -0
  1441. package/vendor/skills/skills/zod/references/schema-use-enums.md +106 -0
  1442. package/vendor/skills/skills/zod/references/schema-use-primitives-correctly.md +63 -0
  1443. package/vendor/skills/skills/zod/references/schema-use-unknown-not-any.md +86 -0
  1444. package/vendor/skills/skills/zod/references/type-branded-types.md +106 -0
  1445. package/vendor/skills/skills/zod/references/type-enable-strict-mode.md +132 -0
  1446. package/vendor/skills/skills/zod/references/type-export-schemas-and-types.md +117 -0
  1447. package/vendor/skills/skills/zod/references/type-input-vs-output.md +116 -0
  1448. package/vendor/skills/skills/zod/references/type-use-z-infer.md +113 -0
  1449. package/vendor/skills/skills/zustand/SKILL.md +154 -0
  1450. package/vendor/skills/skills/zustand/references/patterns.md +924 -0
@@ -0,0 +1,2946 @@
1
+ import { spinner } from "@clack/prompts";
2
+ import { spawn } from "node:child_process";
3
+ import { readdir } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import type { GeneratorConfig } from "./cli.ts";
6
+ import { MODULE_REGISTRY, resolveSelectedModules } from "./modules/index.ts";
7
+ import type { ModuleName } from "./modules/types.ts";
8
+ import {
9
+ copyDirectoryWithTemplates as copyDirectory,
10
+ ensureDir,
11
+ fileExists,
12
+ pathExists,
13
+ writeTextFile,
14
+ } from "./utils/files.ts";
15
+ import { mergePackageJson, type PackageJsonShape } from "./utils/packages.ts";
16
+ import { buildTemplateTokens, replaceTemplateTokens } from "./utils/template.ts";
17
+ import { generateTanStackStart } from "./builders/tanstack-start.ts";
18
+ import {
19
+ type ClaudeMdBuilder,
20
+ buildClaudeMd,
21
+ buildClaudeSettings,
22
+ buildCommitlintConfig,
23
+ buildDockerCompose,
24
+ buildGitignore,
25
+ buildInitTestDbScript,
26
+ buildMakefile,
27
+ copySkillsToAgentDirs,
28
+ patchPluginNames,
29
+ resolveSkillsForModules,
30
+ SKILLS_DIR,
31
+ TEMPLATES_DIR,
32
+ toJson,
33
+ writeInstructionFiles,
34
+ } from "./builders/shared.ts";
35
+ import type { GenerateContext } from "./builders/types.ts";
36
+
37
+ export interface GenerateResult {
38
+ resolvedModules: ModuleName[];
39
+ targetDir: string;
40
+ }
41
+
42
+ const BASE_ROOT_DIR = path.join(TEMPLATES_DIR, "base", "root");
43
+ const BASE_FRONTEND_DIR = path.join(TEMPLATES_DIR, "base", "frontend");
44
+ const BASE_BACKEND_DIR = path.join(TEMPLATES_DIR, "base", "backend");
45
+
46
+ function resolveTargetDirectory(targetDir: string) {
47
+ return path.resolve(process.cwd(), targetDir);
48
+ }
49
+
50
+ async function resolveModuleOverlayTargetDir(targetDir: string, overlayDir: string) {
51
+ const entries = await readdir(overlayDir, { withFileTypes: true });
52
+ const hasWorkspaceRootEntries = entries.some(
53
+ entry =>
54
+ entry.name === "packages" ||
55
+ entry.name.startsWith(".") ||
56
+ entry.name === "package.json" ||
57
+ entry.name === "turbo.json"
58
+ );
59
+
60
+ return hasWorkspaceRootEntries ? targetDir : path.join(targetDir, "packages/backend");
61
+ }
62
+
63
+ async function assertTargetDirectoryIsReady(targetDir: string) {
64
+ if (!(await fileExists(targetDir))) {
65
+ return;
66
+ }
67
+
68
+ const entries = await readdir(targetDir);
69
+ if (entries.length > 0) {
70
+ throw new Error(`Target directory is not empty: ${targetDir}`);
71
+ }
72
+ }
73
+
74
+ function runCommand(command: string, args: string[], cwd: string) {
75
+ return new Promise<void>((resolve, reject) => {
76
+ const child = spawn(command, args, {
77
+ cwd,
78
+ stdio: "inherit",
79
+ });
80
+
81
+ child.on("error", reject);
82
+ child.on("exit", code => {
83
+ if (code === 0) {
84
+ resolve();
85
+ return;
86
+ }
87
+
88
+ reject(new Error(`${command} ${args.join(" ")} failed with code ${code ?? "unknown"}`));
89
+ });
90
+ });
91
+ }
92
+
93
+ function buildRootPackageJson(context: GenerateContext): PackageJsonShape {
94
+ const basePackageJson: PackageJsonShape = {
95
+ name: context.projectName,
96
+ private: true,
97
+ workspaces: ["packages/*"],
98
+ scripts: {
99
+ prepare: "husky",
100
+ dev: "turbo run dev --filter=./packages/frontend --filter=./packages/backend --parallel",
101
+ build: "turbo run build",
102
+ lint: "bun run format && bunx oxlint",
103
+ typecheck: "bunx tsgo --project tsconfig.json --noEmit && turbo run typecheck",
104
+ format: "bunx oxfmt --write .",
105
+ "format:check": "bunx oxfmt --check .",
106
+ test: "turbo run test",
107
+ "db:generate": "turbo run db:generate",
108
+ "db:migrate": "turbo run db:migrate",
109
+ },
110
+ devDependencies: {
111
+ "@commitlint/cli": "^20.5.0",
112
+ "@commitlint/config-conventional": "^20.5.0",
113
+ "@tanstack/router-plugin": "1.166.12",
114
+ "@testing-library/jest-dom": "^6.9.1",
115
+ "@types/jsdom": "^28.0.0",
116
+ "@types/node": "^25.5.0",
117
+ "@types/react": "19.2.14",
118
+ "@types/react-dom": "19.2.3",
119
+ "@typescript/native-preview": "^7.0.0-dev.20260316.1",
120
+ "@vitest/ui": "4.1.0",
121
+ husky: "9.1.7",
122
+ jsdom: "^28.1.0",
123
+ "lint-staged": "16.4.0",
124
+ oxfmt: "^0.40.0",
125
+ oxlint: "1.55.0",
126
+ tailwindcss: "4.2.1",
127
+ turbo: "^2.8.16",
128
+ vite: "^8.0.0",
129
+ vitest: "4.1.0",
130
+ },
131
+ "lint-staged": {
132
+ "*.{js,jsx,ts,tsx}": ["oxfmt", "oxlint"],
133
+ "*.{css,scss,html,json,jsonc,yaml,yml,md,markdown}": ["oxfmt"],
134
+ },
135
+ engines: {
136
+ node: ">=22.0.0 <25",
137
+ },
138
+ packageManager: "bun@1.3.4",
139
+ };
140
+
141
+ const fragments = context.resolvedModules.map(moduleName => ({
142
+ scripts: MODULE_REGISTRY[moduleName].root?.scripts,
143
+ dependencies: MODULE_REGISTRY[moduleName].root?.dependencies,
144
+ devDependencies: MODULE_REGISTRY[moduleName].root?.devDependencies,
145
+ }));
146
+
147
+ return mergePackageJson(basePackageJson, ...fragments);
148
+ }
149
+
150
+ function buildFrontendPackageJson(context: GenerateContext): PackageJsonShape {
151
+ const basePackageJson: PackageJsonShape = {
152
+ name: "frontend",
153
+ private: true,
154
+ type: "module",
155
+ scripts: {
156
+ dev: "vite --port 5173",
157
+ build: "vite build && bunx tsgo --noEmit",
158
+ preview: "vite preview",
159
+ test: "bunx vitest run",
160
+ typecheck: "bunx tsgo --noEmit",
161
+ },
162
+ dependencies: {
163
+ "@base-ui/react": "^1.3.0",
164
+ "@fontsource-variable/geist": "^5.2.8",
165
+ "@fontsource/bricolage-grotesque": "^5.2.10",
166
+ "@hookform/resolvers": "^5.2.2",
167
+ "@tabler/icons-react": "^3.40.0",
168
+ "@tailwindcss/vite": "^4.2.1",
169
+ "@tanstack/react-query": "^5.90.21",
170
+ "@tanstack/react-query-devtools": "^5.91.3",
171
+ "@tanstack/react-router": "^1.167.3",
172
+ "@tanstack/react-router-devtools": "^1.166.9",
173
+ "class-variance-authority": "^0.7.1",
174
+ clsx: "^2.1.1",
175
+ cmdk: "^1.1.1",
176
+ "date-fns": "^4.1.0",
177
+ "embla-carousel-react": "^8.6.0",
178
+ "input-otp": "^1.4.2",
179
+ "lucide-react": "^0.577.0",
180
+ "next-themes": "^0.4.6",
181
+ react: "^19.2.4",
182
+ "react-day-picker": "^9.14.0",
183
+ "react-dom": "^19.2.4",
184
+ "react-hook-form": "^7.71.2",
185
+ "react-resizable-panels": "^4.7.3",
186
+ recharts: "2.15.4",
187
+ sonner: "^2.0.7",
188
+ "tailwind-merge": "^3.5.0",
189
+ tailwindcss: "^4.2.1",
190
+ "tw-animate-css": "^1.4.0",
191
+ vaul: "^1.1.2",
192
+ zod: "^4.3.6",
193
+ zustand: "^5.0.11",
194
+ },
195
+ devDependencies: {
196
+ "@babel/plugin-syntax-jsx": "^7.28.6",
197
+ "@rolldown/plugin-babel": "^0.2.1",
198
+ "@tanstack/devtools-vite": "^0.6.0",
199
+ "@testing-library/dom": "^10.4.1",
200
+ "@testing-library/react": "^16.3.2",
201
+ "@vitejs/plugin-react": "^6.0.1",
202
+ "babel-plugin-react-compiler": "^1.0.0",
203
+ "web-vitals": "^5.1.0",
204
+ },
205
+ };
206
+
207
+ const fragments = context.resolvedModules.map(moduleName => ({
208
+ scripts: MODULE_REGISTRY[moduleName].frontend?.scripts,
209
+ dependencies: MODULE_REGISTRY[moduleName].frontend?.dependencies,
210
+ devDependencies: MODULE_REGISTRY[moduleName].frontend?.devDependencies,
211
+ }));
212
+
213
+ return mergePackageJson(basePackageJson, ...fragments);
214
+ }
215
+
216
+ function buildBackendPackageJson(context: GenerateContext): PackageJsonShape {
217
+ const basePackageJson: PackageJsonShape = {
218
+ name: "backend",
219
+ type: "module",
220
+ scripts: {
221
+ dev: "bun --watch src/index.ts",
222
+ build: "bun build src/index.ts --outdir dist --target bun",
223
+ start: "bun dist/index.js",
224
+ test: "bunx vitest run --config vitest.config.ts",
225
+ "test:watch": "bunx vitest --config vitest.config.ts",
226
+ typecheck: "bunx tsgo --noEmit",
227
+ "db:generate": "bunx drizzle-kit generate",
228
+ "db:migrate": "bunx drizzle-kit migrate",
229
+ },
230
+ dependencies: {
231
+ "@hono/zod-openapi": "^1.2.2",
232
+ "@hono/zod-validator": "^0.7.6",
233
+ "@logtape/logtape": "^2.0.4",
234
+ "@opentelemetry/api": "^1.9.0",
235
+ "@scalar/hono-api-reference": "^0.10.3",
236
+ "drizzle-orm": "^0.45.1",
237
+ "es-toolkit": "^1.45.1",
238
+ hono: "^4.12.7",
239
+ postgres: "^3.4.8",
240
+ "prom-client": "^15.1.3",
241
+ uuid: "^13.0.0",
242
+ zod: "^4.3.6",
243
+ },
244
+ devDependencies: {
245
+ "@types/bun": "^1.3.10",
246
+ "@types/node": "^25.5.0",
247
+ dotenv: "^17.3.1",
248
+ "drizzle-kit": "^0.31.9",
249
+ tsx: "^4.7.1",
250
+ vitest: "4.1.0",
251
+ },
252
+ };
253
+
254
+ const fragments = context.resolvedModules.map(moduleName => ({
255
+ scripts: MODULE_REGISTRY[moduleName].backend?.scripts,
256
+ dependencies: MODULE_REGISTRY[moduleName].backend?.dependencies,
257
+ devDependencies: MODULE_REGISTRY[moduleName].backend?.devDependencies,
258
+ }));
259
+
260
+ return mergePackageJson(basePackageJson, ...fragments);
261
+ }
262
+
263
+ function buildTurboConfig(context: GenerateContext) {
264
+ const tasks: Record<string, Record<string, unknown>> = {
265
+ build: {
266
+ dependsOn: ["^build"],
267
+ outputs: ["dist/**"],
268
+ },
269
+ dev: {
270
+ cache: false,
271
+ persistent: true,
272
+ },
273
+ lint: {
274
+ dependsOn: ["^lint"],
275
+ },
276
+ typecheck: {
277
+ dependsOn: ["^typecheck"],
278
+ },
279
+ test: {
280
+ cache: false,
281
+ },
282
+ "db:generate": {
283
+ cache: false,
284
+ },
285
+ "db:migrate": {
286
+ cache: false,
287
+ },
288
+ };
289
+
290
+ if (context.resolvedModules.includes("storybook")) {
291
+ tasks.storybook = {
292
+ cache: false,
293
+ persistent: true,
294
+ };
295
+ tasks["build-storybook"] = {
296
+ dependsOn: ["^build"],
297
+ outputs: ["storybook-static/**"],
298
+ };
299
+ }
300
+
301
+ return { $schema: "https://turbo.build/schema.json", tasks };
302
+ }
303
+
304
+ function buildOxlintConfig(projectName: string) {
305
+ return toJson({
306
+ $schema: "./node_modules/oxlint/configuration_schema.json",
307
+ plugins: ["unicorn", "typescript", "oxc"],
308
+ jsPlugins: [
309
+ "./lint-plugins/react-component-complexity.mjs",
310
+ "./lint-plugins/react-hooks-separation.mjs",
311
+ "./lint-plugins/test-file-location.mjs",
312
+ ],
313
+ rules: {
314
+ "no-unused-vars": "error",
315
+ "no-unused-private-class-members": "error",
316
+ "unicorn/no-empty-file": "warn",
317
+ },
318
+ overrides: [
319
+ {
320
+ files: ["packages/frontend/src/**/*.tsx"],
321
+ rules: {
322
+ [`${projectName}-react/max-component-complexity`]: [
323
+ "error",
324
+ {
325
+ maxHooks: 5,
326
+ maxHandlers: 3,
327
+ maxTotal: 7,
328
+ },
329
+ ],
330
+ [`${projectName}-react-hooks/no-mixed-hooks-and-components`]: "warn",
331
+ },
332
+ },
333
+ {
334
+ files: ["packages/frontend/src/**/*.{ts,tsx}"],
335
+ rules: {
336
+ [`${projectName}-react-hooks/hooks-in-hooks-folder`]: "warn",
337
+ },
338
+ },
339
+ {
340
+ files: ["packages/frontend/src/components/ui/**/*.{ts,tsx}"],
341
+ rules: {
342
+ [`${projectName}-react/max-component-complexity`]: "off",
343
+ [`${projectName}-react-hooks/no-mixed-hooks-and-components`]: "off",
344
+ [`${projectName}-react-hooks/hooks-in-hooks-folder`]: "off",
345
+ },
346
+ },
347
+ {
348
+ files: ["**/*.test.{ts,tsx}", "**/__tests__/**/*.{ts,tsx}", "**/*.stories.{ts,tsx}"],
349
+ rules: {
350
+ [`${projectName}-react/max-component-complexity`]: "off",
351
+ [`${projectName}-react-hooks/no-mixed-hooks-and-components`]: "off",
352
+ [`${projectName}-react-hooks/hooks-in-hooks-folder`]: "off",
353
+ },
354
+ },
355
+ ],
356
+ });
357
+ }
358
+
359
+ // ---------------------------------------------------------------------------
360
+ // Separated stack CLAUDE.md builder
361
+ // ---------------------------------------------------------------------------
362
+
363
+ const separatedClaudeMdBuilder: ClaudeMdBuilder = {
364
+ buildClaudeMdArchitectureSection(_context: GenerateContext): string {
365
+ return [
366
+ "## Architecture",
367
+ "",
368
+ "**{{projectTitle}}** is a monorepo with two main packages, orchestrated by Turborepo and managed with Bun.",
369
+ "",
370
+ "### Monorepo Structure",
371
+ "",
372
+ "```",
373
+ "packages/",
374
+ "├── frontend/ # React 19 SPA (Vite + TanStack Router)",
375
+ "└── backend/ # Hono API server (Drizzle ORM + PostgreSQL)",
376
+ "```",
377
+ "",
378
+ "### Path Aliases",
379
+ "",
380
+ "- `@/*` maps to `./src/*` in each package (tsconfig paths)",
381
+ "",
382
+ "### Frontend (`packages/frontend`)",
383
+ "",
384
+ "React 19 single-page application with client-side routing.",
385
+ "",
386
+ "```",
387
+ "src/",
388
+ "├── routes/ # TanStack file-based routes",
389
+ "├── components/ # React components (ui/, feature-specific/)",
390
+ "├── hooks/ # Shared React hooks",
391
+ "├── lib/ # Client utilities",
392
+ "├── stores/ # Zustand stores",
393
+ "├── data/ # Data layer (TanStack Query, collections)",
394
+ "├── styles.css # Tailwind v4 theme",
395
+ "└── routeTree.gen.ts # Auto-generated route tree (never edit)",
396
+ "```",
397
+ "",
398
+ "### Backend (`packages/backend`)",
399
+ "",
400
+ "Hono API server following feature-based module architecture.",
401
+ "",
402
+ "```",
403
+ "src/",
404
+ "├── app.ts # Main Hono app (plugin composition + route mounting)",
405
+ "├── index.ts # Server startup",
406
+ "├── modules/ # Feature modules (1 Hono instance = 1 controller)",
407
+ "│ └── <feature>/",
408
+ "│ ├── route.ts # Hono instance with route handlers",
409
+ "│ ├── usecases.ts # Business logic (pure functions)",
410
+ "│ ├── model.ts # Zod schemas and types",
411
+ "│ └── repository.ts # Database operations (Drizzle)",
412
+ "├── plugins/ # Cross-cutting concerns (auth, error handling)",
413
+ "├── lib/ # Shared utilities",
414
+ "├── db/ # Database layer (Drizzle schema, migrations)",
415
+ "└── types/ # TypeScript type definitions",
416
+ "```",
417
+ "",
418
+ "### Data Flow",
419
+ "",
420
+ "- **Client**: TanStack Query for server state; Zustand for shared client state",
421
+ "- **Server**: Hono route handlers delegate to usecases, which call repositories",
422
+ "- **Database**: PostgreSQL 16 via Drizzle ORM",
423
+ "",
424
+ "### Tooling",
425
+ "",
426
+ "- **Package manager**: Bun",
427
+ "- **Monorepo orchestration**: Turborepo",
428
+ "- **Linting**: Oxlint",
429
+ "- **Formatting**: Oxfmt (printWidth: 100)",
430
+ "- **Type checking**: tsc",
431
+ "- **Testing**: Vitest + Testing Library",
432
+ "- **Commits**: Conventional Commits + commitlint + husky + lint-staged",
433
+ ].join("\n");
434
+ },
435
+ buildSkillEnforcementBackendSection(_context: GenerateContext): string[] {
436
+ return [
437
+ "- **Hono (routes, middleware, plugins)**: Use `hono` skill",
438
+ "- **Database/schema/queries**: Use `postgres-drizzle` skill",
439
+ "- **Drizzle ORM patterns**: Use `drizzle-orm` skill",
440
+ "- **Drizzle migrations**: Use `drizzle-safe-migrations` skill",
441
+ "- **Validation (Zod schemas)**: Use `zod` skill",
442
+ "- **Utility functions (es-toolkit)**: Use `es-toolkit` skill",
443
+ ];
444
+ },
445
+ buildBackendArchitectureRules(): string {
446
+ return [
447
+ "## Backend Architecture Rules",
448
+ "",
449
+ "- Follow the **1 Hono instance = 1 controller** principle",
450
+ "- Keep route handlers thin — delegate to usecases",
451
+ "- Usecases contain pure business logic (no HTTP context)",
452
+ "- Repositories handle all database operations via Drizzle",
453
+ "- Use Zod validation at API boundaries",
454
+ "- Never edit files in the `drizzle/` folder (auto-generated)",
455
+ ].join("\n");
456
+ },
457
+ };
458
+
459
+ function buildCiWorkflow() {
460
+ const scopes = ["repo", "frontend", "backend", "ui", "auth", "billing", "docs", "test"];
461
+
462
+ return [
463
+ "name: CI",
464
+ "",
465
+ "on:",
466
+ " pull_request:",
467
+ " branches:",
468
+ " - main",
469
+ " push:",
470
+ " branches:",
471
+ " - main",
472
+ "",
473
+ "jobs:",
474
+ " validate-title:",
475
+ " runs-on: ubuntu-latest",
476
+ " if: github.event_name == 'pull_request'",
477
+ " steps:",
478
+ " - uses: amannn/action-semantic-pull-request@v6",
479
+ " env:",
480
+ " GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}",
481
+ " with:",
482
+ " requireScope: true",
483
+ " types: |",
484
+ " build",
485
+ " ci",
486
+ " docs",
487
+ " feat",
488
+ " fix",
489
+ " refactor",
490
+ " test",
491
+ " scopes: |",
492
+ ...scopes.map(scope => ` ${scope}`),
493
+ " check:",
494
+ " runs-on: ubuntu-latest",
495
+ " steps:",
496
+ " - uses: actions/checkout@v5",
497
+ " - uses: ./.github/actions/setup-bun",
498
+ " - run: bun install --frozen-lockfile",
499
+ " - run: make check",
500
+ ].join("\n");
501
+ }
502
+
503
+ function buildFrontendMain() {
504
+ return [
505
+ 'import { RouterProvider, createRouter } from "@tanstack/react-router";',
506
+ 'import { StrictMode } from "react";',
507
+ 'import ReactDOM from "react-dom/client";',
508
+ 'import { routeTree } from "./routeTree.gen";',
509
+ 'import * as TanStackQueryProvider from "./integrations/tanstack-query/root-provider";',
510
+ 'import "./styles.css";',
511
+ "",
512
+ "const TanStackQueryProviderContext = TanStackQueryProvider.getContext();",
513
+ "const router = createRouter({",
514
+ " routeTree,",
515
+ " context: {",
516
+ " ...TanStackQueryProviderContext,",
517
+ " },",
518
+ ' defaultPreload: "intent",',
519
+ " scrollRestoration: true,",
520
+ " defaultStructuralSharing: true,",
521
+ " defaultPreloadStaleTime: 0,",
522
+ "});",
523
+ "",
524
+ 'declare module "@tanstack/react-router" {',
525
+ " interface Register {",
526
+ " router: typeof router;",
527
+ " }",
528
+ "}",
529
+ "",
530
+ 'const rootElement = document.getElementById("app");',
531
+ "if (rootElement && !rootElement.innerHTML) {",
532
+ " const root = ReactDOM.createRoot(rootElement);",
533
+ " root.render(",
534
+ " <StrictMode>",
535
+ " <TanStackQueryProvider.Provider {...TanStackQueryProviderContext}>",
536
+ " <RouterProvider router={router} />",
537
+ " </TanStackQueryProvider.Provider>",
538
+ " </StrictMode>",
539
+ " );",
540
+ "}",
541
+ "",
542
+ ].join("\n");
543
+ }
544
+
545
+ function buildFrontendIndexHtml(context: GenerateContext) {
546
+ return replaceTemplateTokens(
547
+ [
548
+ "<!doctype html>",
549
+ '<html lang="en">',
550
+ " <head>",
551
+ ' <meta charset="UTF-8" />',
552
+ ' <meta name="viewport" content="width=device-width, initial-scale=1.0" />',
553
+ ' <meta name="description" content="{{projectTitle}} full-stack workspace generated by devstack" />',
554
+ " <title>{{projectTitle}}</title>",
555
+ " </head>",
556
+ " <body>",
557
+ ' <div id="app"></div>',
558
+ ' <script type="module" src="/src/main.tsx"></script>',
559
+ " </body>",
560
+ "</html>",
561
+ "",
562
+ ].join("\n"),
563
+ context.tokens
564
+ );
565
+ }
566
+
567
+ function buildFrontendStyles() {
568
+ return [
569
+ '@import "tailwindcss";',
570
+ '@import "tw-animate-css";',
571
+ '@import "shadcn/tailwind.css";',
572
+ '@import "@fontsource-variable/geist";',
573
+ '@import "@fontsource/bricolage-grotesque/500.css";',
574
+ '@import "@fontsource/bricolage-grotesque/700.css";',
575
+ "",
576
+ "@custom-variant dark (&:is(.dark *));",
577
+ "",
578
+ ":root {",
579
+ " --background: oklch(0.99 0.01 95);",
580
+ " --foreground: oklch(0.22 0.02 95);",
581
+ " --card: oklch(0.995 0.008 95);",
582
+ " --card-foreground: oklch(0.22 0.02 95);",
583
+ " --popover: oklch(0.995 0.008 95);",
584
+ " --popover-foreground: oklch(0.22 0.02 95);",
585
+ " --primary: oklch(0.66 0.16 53);",
586
+ " --primary-foreground: oklch(0.99 0.01 95);",
587
+ " --secondary: oklch(0.95 0.01 90);",
588
+ " --secondary-foreground: oklch(0.28 0.02 95);",
589
+ " --muted: oklch(0.95 0.01 90);",
590
+ " --muted-foreground: oklch(0.55 0.02 95);",
591
+ " --accent: oklch(0.93 0.02 72);",
592
+ " --accent-foreground: oklch(0.28 0.02 95);",
593
+ " --destructive: oklch(0.62 0.24 26);",
594
+ " --border: oklch(0.9 0.01 92);",
595
+ " --input: oklch(0.9 0.01 92);",
596
+ " --ring: oklch(0.72 0.04 70);",
597
+ " --radius: 1rem;",
598
+ " --sidebar: oklch(0.985 0.01 92);",
599
+ " --sidebar-foreground: oklch(0.22 0.02 95);",
600
+ " --sidebar-primary: oklch(0.66 0.16 53);",
601
+ " --sidebar-primary-foreground: oklch(0.99 0.01 95);",
602
+ " --sidebar-accent: oklch(0.93 0.02 72);",
603
+ " --sidebar-accent-foreground: oklch(0.28 0.02 95);",
604
+ " --sidebar-border: oklch(0.9 0.01 92);",
605
+ " --sidebar-ring: oklch(0.72 0.04 70);",
606
+ "}",
607
+ "",
608
+ ".dark {",
609
+ " --background: oklch(0.18 0.01 92);",
610
+ " --foreground: oklch(0.98 0.01 95);",
611
+ " --card: oklch(0.22 0.01 92);",
612
+ " --card-foreground: oklch(0.98 0.01 95);",
613
+ " --popover: oklch(0.22 0.01 92);",
614
+ " --popover-foreground: oklch(0.98 0.01 95);",
615
+ " --primary: oklch(0.72 0.17 62);",
616
+ " --primary-foreground: oklch(0.19 0.01 92);",
617
+ " --secondary: oklch(0.28 0.01 92);",
618
+ " --secondary-foreground: oklch(0.98 0.01 95);",
619
+ " --muted: oklch(0.28 0.01 92);",
620
+ " --muted-foreground: oklch(0.72 0.01 95);",
621
+ " --accent: oklch(0.28 0.02 80);",
622
+ " --accent-foreground: oklch(0.98 0.01 95);",
623
+ " --destructive: oklch(0.7 0.19 22);",
624
+ " --border: oklch(1 0 0 / 10%);",
625
+ " --input: oklch(1 0 0 / 15%);",
626
+ " --ring: oklch(0.62 0.04 70);",
627
+ " --sidebar: oklch(0.18 0.01 92);",
628
+ " --sidebar-foreground: oklch(0.98 0.01 95);",
629
+ " --sidebar-primary: oklch(0.72 0.17 62);",
630
+ " --sidebar-primary-foreground: oklch(0.19 0.01 92);",
631
+ " --sidebar-accent: oklch(0.28 0.02 80);",
632
+ " --sidebar-accent-foreground: oklch(0.98 0.01 95);",
633
+ " --sidebar-border: oklch(1 0 0 / 10%);",
634
+ " --sidebar-ring: oklch(0.62 0.04 70);",
635
+ "}",
636
+ "",
637
+ "@theme inline {",
638
+ ' --font-sans: "Geist Variable", sans-serif;',
639
+ ' --font-display: "Bricolage Grotesque", sans-serif;',
640
+ " --color-background: var(--background);",
641
+ " --color-foreground: var(--foreground);",
642
+ " --color-card: var(--card);",
643
+ " --color-card-foreground: var(--card-foreground);",
644
+ " --color-popover: var(--popover);",
645
+ " --color-popover-foreground: var(--popover-foreground);",
646
+ " --color-primary: var(--primary);",
647
+ " --color-primary-foreground: var(--primary-foreground);",
648
+ " --color-secondary: var(--secondary);",
649
+ " --color-secondary-foreground: var(--secondary-foreground);",
650
+ " --color-muted: var(--muted);",
651
+ " --color-muted-foreground: var(--muted-foreground);",
652
+ " --color-accent: var(--accent);",
653
+ " --color-accent-foreground: var(--accent-foreground);",
654
+ " --color-destructive: var(--destructive);",
655
+ " --color-border: var(--border);",
656
+ " --color-input: var(--input);",
657
+ " --color-ring: var(--ring);",
658
+ " --color-sidebar: var(--sidebar);",
659
+ " --color-sidebar-foreground: var(--sidebar-foreground);",
660
+ " --color-sidebar-primary: var(--sidebar-primary);",
661
+ " --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);",
662
+ " --color-sidebar-accent: var(--sidebar-accent);",
663
+ " --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);",
664
+ " --color-sidebar-border: var(--sidebar-border);",
665
+ " --color-sidebar-ring: var(--sidebar-ring);",
666
+ " --radius-sm: calc(var(--radius) - 4px);",
667
+ " --radius-md: calc(var(--radius) - 2px);",
668
+ " --radius-lg: var(--radius);",
669
+ " --radius-xl: calc(var(--radius) + 4px);",
670
+ "}",
671
+ "",
672
+ "@layer base {",
673
+ " * {",
674
+ " @apply border-border outline-ring/50;",
675
+ " }",
676
+ "",
677
+ " html,",
678
+ " body,",
679
+ " #app {",
680
+ " min-height: 100%;",
681
+ " }",
682
+ "",
683
+ " body {",
684
+ " @apply bg-background font-sans text-foreground antialiased;",
685
+ " background-image: radial-gradient(circle at top left, color-mix(in oklch, var(--accent) 35%, transparent), transparent 35%),",
686
+ " linear-gradient(180deg, color-mix(in oklch, var(--background) 96%, black 4%), var(--background));",
687
+ " }",
688
+ "}",
689
+ "",
690
+ ].join("\n");
691
+ }
692
+
693
+ function buildFrontendThemeStore(context: GenerateContext) {
694
+ return replaceTemplateTokens(
695
+ [
696
+ 'import { create } from "zustand";',
697
+ 'import { createJSONStorage, persist, type StateStorage } from "zustand/middleware";',
698
+ "",
699
+ 'type Theme = "light" | "dark" | "system";',
700
+ "",
701
+ "type ThemeState = {",
702
+ " theme: Theme;",
703
+ " setTheme: (theme: Theme) => void;",
704
+ "};",
705
+ "",
706
+ 'function getSystemTheme(): "light" | "dark" {',
707
+ ' if (typeof window === "undefined") return "light";',
708
+ ' return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";',
709
+ "}",
710
+ "",
711
+ "function applyTheme(theme: Theme) {",
712
+ " const root = window.document.documentElement;",
713
+ ' root.classList.remove("light", "dark");',
714
+ ' root.classList.add(theme === "system" ? getSystemTheme() : theme);',
715
+ "}",
716
+ "",
717
+ "const noopStorage: StateStorage = {",
718
+ " getItem: () => null,",
719
+ " setItem: () => {},",
720
+ " removeItem: () => {},",
721
+ "};",
722
+ "",
723
+ "function getThemeStorage(): Storage | undefined {",
724
+ ' if (typeof window === "undefined") return undefined;',
725
+ " return window.localStorage;",
726
+ "}",
727
+ "",
728
+ "export const useThemeStore = create<ThemeState>()(",
729
+ " persist(",
730
+ " set => ({",
731
+ ' theme: "system",',
732
+ " setTheme(theme) {",
733
+ " applyTheme(theme);",
734
+ " set({ theme });",
735
+ " },",
736
+ " }),",
737
+ " {",
738
+ ' name: "{{projectName}}-theme",',
739
+ " storage: createJSONStorage(() => getThemeStorage() ?? noopStorage),",
740
+ " onRehydrateStorage: () => state => {",
741
+ " if (state?.theme) {",
742
+ " applyTheme(state.theme);",
743
+ " }",
744
+ " },",
745
+ " }",
746
+ " )",
747
+ ");",
748
+ "",
749
+ 'if (typeof window !== "undefined") {',
750
+ " applyTheme(useThemeStore.getState().theme);",
751
+ "}",
752
+ "",
753
+ ].join("\n"),
754
+ context.tokens
755
+ );
756
+ }
757
+
758
+ function buildFrontendSidebar(context: GenerateContext) {
759
+ return replaceTemplateTokens(
760
+ [
761
+ 'import type * as React from "react";',
762
+ 'import { Link, useRouterState } from "@tanstack/react-router";',
763
+ 'import { LayoutDashboardIcon, LifeBuoyIcon, Settings2Icon } from "lucide-react";',
764
+ "import {",
765
+ " Sidebar,",
766
+ " SidebarContent,",
767
+ " SidebarFooter,",
768
+ " SidebarGroup,",
769
+ " SidebarGroupContent,",
770
+ " SidebarHeader,",
771
+ " SidebarMenu,",
772
+ " SidebarMenuButton,",
773
+ " SidebarMenuItem,",
774
+ '} from "@/components/ui/sidebar";',
775
+ "",
776
+ "type NavItem = {",
777
+ " title: string;",
778
+ " icon: React.ComponentType<{ className?: string }>;",
779
+ ' to?: "/" | "/settings";',
780
+ "};",
781
+ "",
782
+ "const navItems: NavItem[] = [",
783
+ ' { title: "Overview", to: "/", icon: LayoutDashboardIcon },',
784
+ ' { title: "Settings", to: "/settings", icon: Settings2Icon },',
785
+ "];",
786
+ "",
787
+ "export function AppSidebar(props: React.ComponentProps<typeof Sidebar>) {",
788
+ " const routerState = useRouterState();",
789
+ " const currentPath = routerState.location.pathname;",
790
+ "",
791
+ " return (",
792
+ ' <Sidebar collapsible="none" variant="sidebar" className="min-h-svh" {...props}>',
793
+ " <SidebarHeader>",
794
+ " <SidebarMenu>",
795
+ " <SidebarMenuItem>",
796
+ ' <SidebarMenuButton size="lg" render={<Link to="/" />}>',
797
+ ' <div className="grid size-8 place-items-center rounded-lg bg-primary text-sm font-semibold text-primary-foreground">',
798
+ " {{projectTitle}}".slice(0, 1),
799
+ " </div>",
800
+ ' <span className="font-display font-semibold">{{projectTitle}}</span>',
801
+ " </SidebarMenuButton>",
802
+ " </SidebarMenuItem>",
803
+ " </SidebarMenu>",
804
+ " </SidebarHeader>",
805
+ " <SidebarContent>",
806
+ " <SidebarGroup>",
807
+ " <SidebarGroupContent>",
808
+ " <SidebarMenu>",
809
+ " {navItems.map(item => {",
810
+ ' const isActive = item.to != null && (item.to === "/" ? currentPath === "/" : currentPath.startsWith(item.to));',
811
+ " return (",
812
+ " <SidebarMenuItem key={item.title}>",
813
+ " <SidebarMenuButton tooltip={item.title} isActive={isActive} render={item.to ? <Link to={item.to} /> : undefined}>",
814
+ " <item.icon />",
815
+ " <span>{item.title}</span>",
816
+ " </SidebarMenuButton>",
817
+ " </SidebarMenuItem>",
818
+ " );",
819
+ " })}",
820
+ " </SidebarMenu>",
821
+ " </SidebarGroupContent>",
822
+ " </SidebarGroup>",
823
+ " </SidebarContent>",
824
+ " <SidebarFooter>",
825
+ " <SidebarMenu>",
826
+ " <SidebarMenuItem>",
827
+ ' <SidebarMenuButton tooltip="Help">',
828
+ " <LifeBuoyIcon />",
829
+ " <span>Help</span>",
830
+ " </SidebarMenuButton>",
831
+ " </SidebarMenuItem>",
832
+ " </SidebarMenu>",
833
+ " </SidebarFooter>",
834
+ " </Sidebar>",
835
+ " );",
836
+ "}",
837
+ "",
838
+ ].join("\n"),
839
+ context.tokens
840
+ ).replace('{{projectTitle}}".slice(0, 1)', context.tokens.projectTitle.slice(0, 1));
841
+ }
842
+
843
+ function buildFrontendDashboardIndex(context: GenerateContext) {
844
+ return replaceTemplateTokens(
845
+ [
846
+ 'import { createFileRoute } from "@tanstack/react-router";',
847
+ 'import { DashboardTopbar } from "@/components/dashboard-topbar";',
848
+ 'import { Button } from "@/components/ui/button";',
849
+ 'import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";',
850
+ 'import { Surface } from "@/components/ui/surface";',
851
+ "",
852
+ 'export const Route = createFileRoute("/_dashboard/")({',
853
+ " component: DashboardPage,",
854
+ "});",
855
+ "",
856
+ "function DashboardPage() {",
857
+ " return (",
858
+ " <>",
859
+ ' <DashboardTopbar title="Overview" />',
860
+ ' <div className="grid flex-1 gap-4 p-4 lg:grid-cols-[1.2fr_0.8fr]">',
861
+ " <Card>",
862
+ " <CardHeader>",
863
+ ' <CardTitle className="font-display text-3xl">{{projectTitle}}</CardTitle>',
864
+ " <CardDescription>",
865
+ " A clean starting point for product teams building with React, Hono and Drizzle.",
866
+ " </CardDescription>",
867
+ " </CardHeader>",
868
+ ' <CardContent className="grid gap-4">',
869
+ " <Surface>",
870
+ ' <div className="text-sm text-muted-foreground">Frontend</div>',
871
+ ' <div className="mt-2 text-xl font-semibold">React 19 + TanStack Router + Query</div>',
872
+ " </Surface>",
873
+ " <Surface>",
874
+ ' <div className="text-sm text-muted-foreground">Backend</div>',
875
+ ' <div className="mt-2 text-xl font-semibold">Hono + Drizzle + PostgreSQL</div>',
876
+ " </Surface>",
877
+ " </CardContent>",
878
+ " </Card>",
879
+ " <Card>",
880
+ " <CardHeader>",
881
+ " <CardTitle>Next steps</CardTitle>",
882
+ " <CardDescription>Use this shell as the first module you replace with your own domain.</CardDescription>",
883
+ " </CardHeader>",
884
+ ' <CardContent className="grid gap-3">',
885
+ ' <Button asChild><a href="https://hono.dev" target="_blank" rel="noreferrer">Read the Hono docs</a></Button>',
886
+ ' <Button variant="outline" asChild><a href="https://tanstack.com/router" target="_blank" rel="noreferrer">Review the router setup</a></Button>',
887
+ " </CardContent>",
888
+ " </Card>",
889
+ " </div>",
890
+ " </>",
891
+ " );",
892
+ "}",
893
+ "",
894
+ ].join("\n"),
895
+ context.tokens
896
+ );
897
+ }
898
+
899
+ function buildFrontendSettings() {
900
+ return [
901
+ 'import { createFileRoute } from "@tanstack/react-router";',
902
+ 'import { BellRingIcon, PaletteIcon, ShieldCheckIcon } from "lucide-react";',
903
+ 'import { DashboardTopbar } from "@/components/dashboard-topbar";',
904
+ 'import { Button } from "@/components/ui/button";',
905
+ 'import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";',
906
+ 'import { Surface } from "@/components/ui/surface";',
907
+ "",
908
+ 'export const Route = createFileRoute("/_dashboard/settings")({',
909
+ " component: SettingsPage,",
910
+ "});",
911
+ "",
912
+ "function SettingsPage() {",
913
+ " return (",
914
+ " <>",
915
+ ' <DashboardTopbar title="Settings" />',
916
+ ' <div className="grid flex-1 gap-4 p-4 xl:grid-cols-[1.1fr_0.9fr]">',
917
+ " <Card>",
918
+ " <CardHeader>",
919
+ ' <CardTitle className="text-lg">Workspace Preferences</CardTitle>',
920
+ " <CardDescription>Keep this page generic and replace it with your own product settings.</CardDescription>",
921
+ " </CardHeader>",
922
+ ' <CardContent className="grid gap-3">',
923
+ " <Surface>",
924
+ ' <div className="flex items-start justify-between gap-4">',
925
+ ' <div className="flex gap-3">',
926
+ ' <div className="grid size-11 place-items-center rounded-2xl bg-primary/15 text-primary"><PaletteIcon className="size-5" /></div>',
927
+ " <div>",
928
+ ' <h3 className="font-display text-base font-semibold tracking-tight">Interface Density</h3>',
929
+ ' <p className="mt-1 text-sm text-muted-foreground">Tune the shell layout and spacing once your domain model is in place.</p>',
930
+ " </div>",
931
+ " </div>",
932
+ ' <Button variant="outline">Comfortable</Button>',
933
+ " </div>",
934
+ " </Surface>",
935
+ " <Surface>",
936
+ ' <div className="flex items-start justify-between gap-4">',
937
+ ' <div className="flex gap-3">',
938
+ ' <div className="grid size-11 place-items-center rounded-2xl bg-primary/15 text-primary"><BellRingIcon className="size-5" /></div>',
939
+ " <div>",
940
+ ' <h3 className="font-display text-base font-semibold tracking-tight">Notifications</h3>',
941
+ ' <p className="mt-1 text-sm text-muted-foreground">Decide which changes deserve attention before you wire the real event sources.</p>',
942
+ " </div>",
943
+ " </div>",
944
+ " <Button>Enabled</Button>",
945
+ " </div>",
946
+ " </Surface>",
947
+ " <Surface>",
948
+ ' <div className="flex items-start justify-between gap-4">',
949
+ ' <div className="flex gap-3">',
950
+ ' <div className="grid size-11 place-items-center rounded-2xl bg-primary/15 text-primary"><ShieldCheckIcon className="size-5" /></div>',
951
+ " <div>",
952
+ ' <h3 className="font-display text-base font-semibold tracking-tight">Review Gates</h3>',
953
+ ' <p className="mt-1 text-sm text-muted-foreground">Reserve destructive flows for deliberate confirmations and audit-friendly actions.</p>',
954
+ " </div>",
955
+ " </div>",
956
+ ' <Button variant="outline">Manage</Button>',
957
+ " </div>",
958
+ " </Surface>",
959
+ " </CardContent>",
960
+ " </Card>",
961
+ " </div>",
962
+ " </>",
963
+ " );",
964
+ "}",
965
+ "",
966
+ ].join("\n");
967
+ }
968
+
969
+ function buildFrontendRouteTree() {
970
+ return [
971
+ "/* eslint-disable */",
972
+ "",
973
+ "// @ts-nocheck",
974
+ "",
975
+ "import { Route as rootRouteImport } from './routes/__root'",
976
+ "import { Route as DashboardRouteImport } from './routes/_dashboard'",
977
+ "import { Route as DashboardIndexRouteImport } from './routes/_dashboard/index'",
978
+ "import { Route as DashboardSettingsRouteImport } from './routes/_dashboard/settings'",
979
+ "",
980
+ "const DashboardRoute = DashboardRouteImport.update({",
981
+ " id: '/_dashboard',",
982
+ " getParentRoute: () => rootRouteImport,",
983
+ "} as any)",
984
+ "const DashboardIndexRoute = DashboardIndexRouteImport.update({",
985
+ " id: '/',",
986
+ " path: '/',",
987
+ " getParentRoute: () => DashboardRoute,",
988
+ "} as any)",
989
+ "const DashboardSettingsRoute = DashboardSettingsRouteImport.update({",
990
+ " id: '/settings',",
991
+ " path: '/settings',",
992
+ " getParentRoute: () => DashboardRoute,",
993
+ "} as any)",
994
+ "",
995
+ "export const routeTree = rootRouteImport",
996
+ " ._addFileChildren({",
997
+ " DashboardRoute: DashboardRoute._addFileChildren({",
998
+ " DashboardIndexRoute,",
999
+ " DashboardSettingsRoute,",
1000
+ " }),",
1001
+ " })",
1002
+ " ._addFileTypes<any>()",
1003
+ "",
1004
+ ].join("\n");
1005
+ }
1006
+
1007
+ function buildFrontendVitestConfig(context: GenerateContext) {
1008
+ return replaceTemplateTokens(
1009
+ [
1010
+ 'import { defineConfig } from "vitest/config";',
1011
+ 'import viteReact from "@vitejs/plugin-react";',
1012
+ 'import { fileURLToPath, URL } from "node:url";',
1013
+ "",
1014
+ "export default defineConfig({",
1015
+ " plugins: [viteReact()],",
1016
+ " resolve: {",
1017
+ " alias: {",
1018
+ ' "@": fileURLToPath(new URL("./src", import.meta.url)),',
1019
+ " },",
1020
+ " },",
1021
+ " test: {",
1022
+ ' name: "{{projectName}}",',
1023
+ ' environment: "jsdom",',
1024
+ " globals: true,",
1025
+ ' include: ["src/**/*.{test,spec}.{ts,tsx}"],',
1026
+ ' exclude: ["**/node_modules/**", "**/dist/**"],',
1027
+ ' setupFiles: ["./src/test-setup.ts"],',
1028
+ " },",
1029
+ "});",
1030
+ "",
1031
+ ].join("\n"),
1032
+ context.tokens
1033
+ );
1034
+ }
1035
+
1036
+ function buildFrontendAppTest(context: GenerateContext) {
1037
+ return replaceTemplateTokens(
1038
+ [
1039
+ 'import { render, screen } from "@testing-library/react";',
1040
+ 'import App from "./App";',
1041
+ "",
1042
+ 'describe("App", () => {',
1043
+ ' it("renders the scaffold shell", async () => {',
1044
+ " render(<App />);",
1045
+ ' expect(await screen.findByText("{{projectTitle}}")).toBeInTheDocument();',
1046
+ " });",
1047
+ "});",
1048
+ "",
1049
+ ].join("\n"),
1050
+ context.tokens
1051
+ );
1052
+ }
1053
+
1054
+ function buildBackendIndex(context: GenerateContext) {
1055
+ const lines = [
1056
+ 'import app from "./app";',
1057
+ 'import { env } from "./env";',
1058
+ 'import { logger } from "./lib/logger";',
1059
+ ];
1060
+
1061
+ if (context.resolvedModules.includes("observability")) {
1062
+ lines.push(
1063
+ 'import { initializeSentry } from "./lib/sentry";',
1064
+ 'import { initializeTracing, shutdownTracing } from "./lib/tracing";'
1065
+ );
1066
+ }
1067
+
1068
+ if (context.resolvedModules.includes("storage")) {
1069
+ lines.push('import { initializeStorageBucket } from "./lib/storage";');
1070
+ }
1071
+
1072
+ lines.push("", "const port = env.PORT;", "");
1073
+
1074
+ if (context.resolvedModules.includes("observability")) {
1075
+ lines.push("initializeSentry();", "await initializeTracing();");
1076
+ }
1077
+
1078
+ if (context.resolvedModules.includes("storage")) {
1079
+ lines.push("await initializeStorageBucket();");
1080
+ }
1081
+
1082
+ lines.push(
1083
+ "",
1084
+ "const server = Bun.serve({",
1085
+ " port,",
1086
+ " fetch: app.fetch,",
1087
+ "});",
1088
+ "",
1089
+ 'logger.info("Server started", {',
1090
+ " port: server.port,",
1091
+ " url: `http://localhost:${server.port}`,",
1092
+ "});"
1093
+ );
1094
+
1095
+ if (context.resolvedModules.includes("observability")) {
1096
+ lines.push(
1097
+ "",
1098
+ 'for (const signal of ["SIGINT", "SIGTERM"] as const) {',
1099
+ " process.on(signal, () => {",
1100
+ ' logger.info("Shutting down gracefully", { signal });',
1101
+ " server.stop();",
1102
+ " void shutdownTracing().finally(() => process.exit(0));",
1103
+ " });",
1104
+ "}"
1105
+ );
1106
+ }
1107
+
1108
+ return `${lines.join("\n")}\n`;
1109
+ }
1110
+
1111
+ function buildBackendEnvTs(context: GenerateContext) {
1112
+ const lines = [
1113
+ 'import { mapValues } from "es-toolkit/object";',
1114
+ 'import { trim } from "es-toolkit/string";',
1115
+ 'import { z } from "zod";',
1116
+ "",
1117
+ 'const isTest = process.env.NODE_ENV === "test";',
1118
+ "const SECRET_KEY_PATTERN = /(SECRET|API_KEY|TOKEN|_KEY|PASSWORD)/i;",
1119
+ "",
1120
+ "const normalizeOptionalValue = (value: unknown) => {",
1121
+ " if (value === undefined) return undefined;",
1122
+ ' if (typeof value === "string") {',
1123
+ " const normalized = trim(value);",
1124
+ ' if (normalized === "" || normalized.toLowerCase() === "undefined" || normalized.toLowerCase() === "null") {',
1125
+ " return undefined;",
1126
+ " }",
1127
+ " return normalized;",
1128
+ " }",
1129
+ " return value;",
1130
+ "};",
1131
+ "",
1132
+ "const optionalString = z.preprocess(normalizeOptionalValue, z.string().min(1).optional());",
1133
+ "const optionalUrl = z.preprocess(normalizeOptionalValue, z.string().url().optional());",
1134
+ "const _optionalBoolean = z.preprocess(value => {",
1135
+ " const normalized = normalizeOptionalValue(value);",
1136
+ " if (normalized === undefined) return undefined;",
1137
+ ' if (typeof normalized === "boolean") return normalized;',
1138
+ ' if (typeof normalized === "string") {',
1139
+ " switch (normalized.toLowerCase()) {",
1140
+ ' case "1":',
1141
+ ' case "true":',
1142
+ ' case "yes":',
1143
+ " return true;",
1144
+ ' case "0":',
1145
+ ' case "false":',
1146
+ ' case "no":',
1147
+ " return false;",
1148
+ " default:",
1149
+ " return normalized;",
1150
+ " }",
1151
+ " }",
1152
+ " return normalized;",
1153
+ "}, z.boolean().optional());",
1154
+ "const _optionalPositiveInteger = z.preprocess(normalizeOptionalValue, z.coerce.number().int().positive().optional());",
1155
+ "const _requiredSecret = (testDefault: string) => (isTest ? z.string().min(1).default(testDefault) : z.string().min(1));",
1156
+ "",
1157
+ "const envSchema = z.object({",
1158
+ ' NODE_ENV: z.enum(["development", "production", "test"]).default("development"),',
1159
+ " PORT: z.coerce.number().int().positive().default(3000),",
1160
+ " DATABASE_URL: z.string().trim().min(1),",
1161
+ " DATABASE_URL_TEST: optionalString,",
1162
+ ' APP_URL: optionalUrl.default("http://localhost:5173"),',
1163
+ ' CORS_ORIGIN: optionalString.default("http://localhost:5173"),',
1164
+ ];
1165
+
1166
+ if (context.resolvedModules.includes("auth")) {
1167
+ lines.push(
1168
+ ' BETTER_AUTH_SECRET: _requiredSecret("test-better-auth-secret-0123456789abcdef"),',
1169
+ ' BETTER_AUTH_URL: z.string().url().default("http://localhost:3000"),'
1170
+ );
1171
+ }
1172
+
1173
+ if (context.resolvedModules.includes("redis")) {
1174
+ lines.push(
1175
+ ' REDIS_URL: z.string().min(1).default("redis://localhost:6379"),',
1176
+ " RATE_LIMIT_WINDOW_MS: _optionalPositiveInteger,",
1177
+ " RATE_LIMIT_AUTHENTICATED_LIMIT: _optionalPositiveInteger,",
1178
+ " RATE_LIMIT_PUBLIC_LIMIT: _optionalPositiveInteger,",
1179
+ " RATE_LIMIT_WEBHOOK_LIMIT: _optionalPositiveInteger,"
1180
+ );
1181
+ }
1182
+
1183
+ if (context.resolvedModules.includes("storage")) {
1184
+ lines.push(
1185
+ " S3_ENDPOINT: optionalUrl,",
1186
+ ' S3_REGION: optionalString.default("sa-east-1"),',
1187
+ " S3_ACCESS_KEY: optionalString,",
1188
+ " S3_SECRET_KEY: optionalString,",
1189
+ " S3_BUCKET: optionalString,"
1190
+ );
1191
+ }
1192
+
1193
+ if (context.resolvedModules.includes("email")) {
1194
+ lines.push(
1195
+ " RESEND_API_KEY: optionalString,",
1196
+ " EMAIL_FROM: optionalString,",
1197
+ " MAILPIT_HOST: optionalString,",
1198
+ " MAILPIT_PORT: _optionalPositiveInteger,"
1199
+ );
1200
+ }
1201
+
1202
+ if (context.resolvedModules.includes("stripe")) {
1203
+ lines.push(
1204
+ ' STRIPE_SECRET_KEY: z.preprocess(normalizeOptionalValue, z.string().startsWith("sk_").optional()),',
1205
+ ' STRIPE_WEBHOOK_SECRET: z.preprocess(normalizeOptionalValue, z.string().startsWith("whsec_").optional()),',
1206
+ " STRIPE_CHECKOUT_SUCCESS_PATH: optionalString,",
1207
+ " STRIPE_CHECKOUT_CANCEL_PATH: optionalString,"
1208
+ );
1209
+ }
1210
+
1211
+ if (context.resolvedModules.includes("inngest")) {
1212
+ lines.push(" INNGEST_EVENT_KEY: optionalString,", " INNGEST_SIGNING_KEY: optionalString,");
1213
+ }
1214
+
1215
+ if (context.resolvedModules.includes("observability")) {
1216
+ lines.push(
1217
+ " SENTRY_DSN: optionalUrl,",
1218
+ " TRACING_ENABLED: _optionalBoolean,",
1219
+ " OTEL_EXPORTER_OTLP_ENDPOINT: optionalUrl,",
1220
+ " OTEL_SERVICE_NAME: optionalString,"
1221
+ );
1222
+ }
1223
+
1224
+ lines.push(
1225
+ "});",
1226
+ "",
1227
+ "export function loadEnv(rawEnv: Record<string, string | undefined> = process.env) {",
1228
+ " const parsed = envSchema.safeParse(rawEnv);",
1229
+ " if (!parsed.success) {",
1230
+ " throw new Error(`Invalid environment variables:\\n${JSON.stringify(parsed.error.format(), null, 2)}`);",
1231
+ " }",
1232
+ " return parsed.data;",
1233
+ "}",
1234
+ "",
1235
+ "export const env = loadEnv();",
1236
+ "export type Env = z.infer<typeof envSchema>;",
1237
+ "",
1238
+ 'const _hasString = (value: string | undefined) => typeof value === "string" && trim(value).length > 0;',
1239
+ "",
1240
+ "export const featureAvailability = {"
1241
+ );
1242
+
1243
+ const features = [
1244
+ `auth: ${context.resolvedModules.includes("auth") ? "_hasString(env.BETTER_AUTH_SECRET)" : "false"}`,
1245
+ `organizations: ${context.resolvedModules.includes("organizations") ? "_hasString(env.BETTER_AUTH_SECRET)" : "false"}`,
1246
+ `redis: ${context.resolvedModules.includes("redis") ? "_hasString(env.REDIS_URL)" : "false"}`,
1247
+ `storage: ${context.resolvedModules.includes("storage") ? "_hasString(env.S3_BUCKET)" : "false"}`,
1248
+ `email: ${context.resolvedModules.includes("email") ? "_hasString(env.EMAIL_FROM) || _hasString(env.RESEND_API_KEY)" : "false"}`,
1249
+ `stripe: ${context.resolvedModules.includes("stripe") ? "_hasString(env.STRIPE_SECRET_KEY) && _hasString(env.STRIPE_WEBHOOK_SECRET)" : "false"}`,
1250
+ `inngest: ${context.resolvedModules.includes("inngest") ? "_hasString(env.INNGEST_SIGNING_KEY) || _hasString(env.INNGEST_EVENT_KEY)" : "false"}`,
1251
+ `observability: ${context.resolvedModules.includes("observability") ? "_hasString(env.SENTRY_DSN) || Boolean(env.TRACING_ENABLED)" : "false"}`,
1252
+ ];
1253
+
1254
+ lines.push(...features.map(item => ` ${item},`));
1255
+ lines.push(
1256
+ "} as const;",
1257
+ "",
1258
+ "function redactEnvValue(key: string, value: unknown) {",
1259
+ ' if (key === "DATABASE_URL" || key === "DATABASE_URL_TEST") return "[REDACTED]";',
1260
+ ' return SECRET_KEY_PATTERN.test(key) ? "[REDACTED]" : value;',
1261
+ "}",
1262
+ "",
1263
+ "export const redactedEnv = mapValues(env, (value, key) => redactEnvValue(key, value));",
1264
+ ""
1265
+ );
1266
+
1267
+ return `${lines.join("\n")}\n`;
1268
+ }
1269
+
1270
+ function buildBackendEnvExample(context: GenerateContext) {
1271
+ const sections = [
1272
+ "# Server",
1273
+ "PORT=3000",
1274
+ "NODE_ENV=development",
1275
+ "",
1276
+ "# Database",
1277
+ `DATABASE_URL=postgresql://postgres:postgres@localhost:5432/${context.projectName}?schema=public`,
1278
+ `DATABASE_URL_TEST=postgresql://postgres:postgres@localhost:5432/${context.projectName}_test?schema=public`,
1279
+ "",
1280
+ "# Frontend",
1281
+ "APP_URL=http://localhost:5173",
1282
+ "CORS_ORIGIN=http://localhost:5173",
1283
+ ];
1284
+
1285
+ for (const moduleName of context.resolvedModules) {
1286
+ const envVars = MODULE_REGISTRY[moduleName].envVars;
1287
+ if (!envVars?.length) {
1288
+ continue;
1289
+ }
1290
+
1291
+ sections.push("", `# ${MODULE_REGISTRY[moduleName].label}`);
1292
+ for (const envVar of envVars) {
1293
+ sections.push(replaceTemplateTokens(`${envVar.key}=${envVar.value}`, context.tokens));
1294
+ }
1295
+ }
1296
+
1297
+ return `${sections.join("\n")}\n`;
1298
+ }
1299
+
1300
+ function buildBackendItemsSchema() {
1301
+ return [
1302
+ 'import { pgTable, text, timestamp } from "drizzle-orm/pg-core";',
1303
+ 'import { generateId } from "../../lib/id";',
1304
+ "",
1305
+ 'export const items = pgTable("items", {',
1306
+ ' id: text("id").primaryKey().$defaultFn(() => generateId()),',
1307
+ ' name: text("name").notNull(),',
1308
+ ' description: text("description"),',
1309
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
1310
+ ' updated_at: timestamp("updated_at").defaultNow().$onUpdate(() => new Date()).notNull(),',
1311
+ "});",
1312
+ "",
1313
+ "export type Item = typeof items.$inferSelect;",
1314
+ "export type NewItem = typeof items.$inferInsert;",
1315
+ "",
1316
+ ].join("\n");
1317
+ }
1318
+
1319
+ function buildBackendSchemaIndex(context: GenerateContext) {
1320
+ const exports = ['export * from "./items";'];
1321
+ if (context.resolvedModules.includes("auth")) exports.push('export * from "./auth";');
1322
+ if (context.resolvedModules.includes("stripe")) exports.push('export * from "./billing";');
1323
+ return `${exports.join("\n")}\n`;
1324
+ }
1325
+
1326
+ function buildBackendTypesIndex(context: GenerateContext) {
1327
+ if (!context.resolvedModules.includes("auth")) {
1328
+ return "export {};\n";
1329
+ }
1330
+
1331
+ return ['export type { AuthSession, AuthUser } from "../plugins/auth";', ""].join("\n");
1332
+ }
1333
+
1334
+ function buildBackendPluginsIndex(context: GenerateContext) {
1335
+ const lines = [
1336
+ 'export { errorHandler } from "./error";',
1337
+ 'export { loggingMiddleware } from "./logging";',
1338
+ 'export { metricsMiddleware, metricsRoutes } from "./metrics";',
1339
+ 'export { openApiRoutes } from "./openapi";',
1340
+ 'export { REQUEST_ID_HEADER, requestIdMiddleware } from "./request-id";',
1341
+ 'export type { RequestIdVariables } from "./request-id";',
1342
+ ];
1343
+
1344
+ if (context.resolvedModules.includes("auth")) {
1345
+ lines.push(
1346
+ 'export { auth, authHandler, requireAuth, requireSuperadmin, sessionMiddleware } from "./auth";',
1347
+ 'export type { AuthSession, AuthUser, AuthVariables } from "./auth";'
1348
+ );
1349
+ }
1350
+
1351
+ if (context.resolvedModules.includes("organizations")) {
1352
+ lines.push('export { requireActiveOrg } from "./auth";');
1353
+ }
1354
+
1355
+ if (context.resolvedModules.includes("redis")) {
1356
+ lines.push(
1357
+ 'export { authenticatedRateLimit, publicRateLimit, webhookRateLimit } from "./rate-limiter";',
1358
+ 'export type { RateLimitVariables } from "./rate-limiter";'
1359
+ );
1360
+ }
1361
+
1362
+ if (context.resolvedModules.includes("observability")) {
1363
+ lines.push(
1364
+ 'export { tracingMiddleware } from "../lib/tracing";',
1365
+ 'export type { TracingVariables } from "../lib/tracing";'
1366
+ );
1367
+ }
1368
+
1369
+ return `${lines.join("\n")}\n`;
1370
+ }
1371
+
1372
+ function buildBackendHealthRoute(context: GenerateContext) {
1373
+ const imports = [
1374
+ 'import { sql } from "drizzle-orm";',
1375
+ 'import { Hono } from "hono";',
1376
+ 'import { db } from "../db/index";',
1377
+ ];
1378
+
1379
+ const checks = [
1380
+ " try {",
1381
+ " await db.execute(sql`select 1`);",
1382
+ " } catch {",
1383
+ ' return c.json({ status: "not_ready", checks: { postgres: "error" } }, 503);',
1384
+ " }",
1385
+ ];
1386
+
1387
+ if (context.resolvedModules.includes("redis")) {
1388
+ imports.push('import { getRedisClient } from "../lib/redis";');
1389
+ checks.push(
1390
+ " try {",
1391
+ " const pong = await getRedisClient().ping();",
1392
+ ' if (pong !== "PONG") throw new Error("Redis did not respond with PONG");',
1393
+ " } catch {",
1394
+ ' return c.json({ status: "not_ready", checks: { postgres: "ok", redis: "error" } }, 503);',
1395
+ " }"
1396
+ );
1397
+ }
1398
+
1399
+ return [
1400
+ ...imports,
1401
+ "",
1402
+ "const healthRoutes = new Hono();",
1403
+ "",
1404
+ 'healthRoutes.get("/", c => {',
1405
+ ' return c.json({ status: "ok", timestamp: new Date().toISOString() });',
1406
+ "});",
1407
+ "",
1408
+ 'healthRoutes.get("/ready", async c => {',
1409
+ ...checks,
1410
+ ' return c.json({ status: "ready", timestamp: new Date().toISOString() });',
1411
+ "});",
1412
+ "",
1413
+ "export { healthRoutes };",
1414
+ "",
1415
+ ].join("\n");
1416
+ }
1417
+
1418
+ function buildBackendItemsModel() {
1419
+ return [
1420
+ 'import { z } from "zod";',
1421
+ "",
1422
+ "export const itemSchema = z.object({",
1423
+ " id: z.string().trim().min(1),",
1424
+ " name: z.string().trim().min(1),",
1425
+ " description: z.string().trim().min(1).nullable().optional(),",
1426
+ "});",
1427
+ "",
1428
+ "export const createItemSchema = itemSchema.omit({ id: true });",
1429
+ "export const updateItemSchema = createItemSchema.partial();",
1430
+ "",
1431
+ "export type ItemDto = z.infer<typeof itemSchema>;",
1432
+ "export type CreateItemInput = z.infer<typeof createItemSchema>;",
1433
+ "export type UpdateItemInput = z.infer<typeof updateItemSchema>;",
1434
+ "",
1435
+ ].join("\n");
1436
+ }
1437
+
1438
+ function buildBackendItemsRepository() {
1439
+ return [
1440
+ 'import { eq } from "drizzle-orm";',
1441
+ 'import { db, type Database } from "../../db";',
1442
+ 'import { items, type NewItem } from "../../db/schema";',
1443
+ "",
1444
+ 'type Transaction = Parameters<Parameters<Database["transaction"]>[0]>[0];',
1445
+ "type DatabaseClient = Database | Transaction;",
1446
+ "",
1447
+ "export function listItems(database: DatabaseClient = db) {",
1448
+ " return database.select().from(items);",
1449
+ "}",
1450
+ "",
1451
+ "export async function findItemById(id: string, database: DatabaseClient = db) {",
1452
+ " const [record] = await database.select().from(items).where(eq(items.id, id)).limit(1);",
1453
+ " return record ?? null;",
1454
+ "}",
1455
+ "",
1456
+ "export async function createItem(data: NewItem, database: DatabaseClient = db) {",
1457
+ " const [record] = await database.insert(items).values(data).returning();",
1458
+ ' if (!record) throw new Error("Failed to create item");',
1459
+ " return record;",
1460
+ "}",
1461
+ "",
1462
+ "export async function updateItem(id: string, data: Partial<NewItem>, database: DatabaseClient = db) {",
1463
+ " const [record] = await database.update(items).set(data).where(eq(items.id, id)).returning();",
1464
+ " return record ?? null;",
1465
+ "}",
1466
+ "",
1467
+ "export async function deleteItem(id: string, database: DatabaseClient = db) {",
1468
+ " const [record] = await database.delete(items).where(eq(items.id, id)).returning();",
1469
+ " return record ?? null;",
1470
+ "}",
1471
+ "",
1472
+ ].join("\n");
1473
+ }
1474
+
1475
+ function buildBackendItemsUsecases() {
1476
+ return [
1477
+ 'import { NotFoundError } from "../../lib/errors";',
1478
+ 'import type { CreateItemInput, UpdateItemInput } from "./model";',
1479
+ 'import * as repository from "./repository";',
1480
+ "",
1481
+ "export function listItems() {",
1482
+ " return repository.listItems();",
1483
+ "}",
1484
+ "",
1485
+ "export async function getItem(id: string) {",
1486
+ " const item = await repository.findItemById(id);",
1487
+ ' if (!item) throw new NotFoundError("Item");',
1488
+ " return item;",
1489
+ "}",
1490
+ "",
1491
+ "export function createItem(input: CreateItemInput) {",
1492
+ " return repository.createItem(input);",
1493
+ "}",
1494
+ "",
1495
+ "export async function updateItem(id: string, input: UpdateItemInput) {",
1496
+ " const item = await repository.updateItem(id, input);",
1497
+ ' if (!item) throw new NotFoundError("Item");',
1498
+ " return item;",
1499
+ "}",
1500
+ "",
1501
+ "export async function deleteItem(id: string) {",
1502
+ " const item = await repository.deleteItem(id);",
1503
+ ' if (!item) throw new NotFoundError("Item");',
1504
+ " return item;",
1505
+ "}",
1506
+ "",
1507
+ ].join("\n");
1508
+ }
1509
+
1510
+ function buildBackendItemsRoute() {
1511
+ return [
1512
+ 'import { zValidator } from "@hono/zod-validator";',
1513
+ 'import { Hono } from "hono";',
1514
+ 'import { created, ok } from "../../lib/response";',
1515
+ 'import { createItemSchema, updateItemSchema } from "./model";',
1516
+ 'import * as usecases from "./usecases";',
1517
+ "",
1518
+ "export const itemsModule = new Hono()",
1519
+ ' .get("/", async c => c.json(ok(await usecases.listItems())))',
1520
+ ' .post("/", zValidator("json", createItemSchema), async c => c.json(created(await usecases.createItem(c.req.valid("json"))), 201))',
1521
+ ' .get("/:id", async c => c.json(ok(await usecases.getItem(c.req.param("id")))))',
1522
+ ' .patch("/:id", zValidator("json", updateItemSchema), async c => c.json(ok(await usecases.updateItem(c.req.param("id"), c.req.valid("json")))))',
1523
+ ' .delete("/:id", async c => c.json(ok(await usecases.deleteItem(c.req.param("id")))));',
1524
+ "",
1525
+ ].join("\n");
1526
+ }
1527
+
1528
+ function buildBackendItemsIndex() {
1529
+ return 'export { itemsModule } from "./route";\n';
1530
+ }
1531
+
1532
+ function buildBackendApp(context: GenerateContext) {
1533
+ const imports = [
1534
+ 'import { cors } from "hono/cors";',
1535
+ 'import { env } from "./env";',
1536
+ 'import { createOpenApiApp } from "./lib/openapi";',
1537
+ 'import { configureBackendLogger } from "./lib/logger";',
1538
+ 'import { itemsModule } from "./modules/items";',
1539
+ "import {",
1540
+ " errorHandler,",
1541
+ " loggingMiddleware,",
1542
+ " metricsMiddleware,",
1543
+ " metricsRoutes,",
1544
+ " openApiRoutes,",
1545
+ " requestIdMiddleware,",
1546
+ " REQUEST_ID_HEADER,",
1547
+ " type RequestIdVariables,",
1548
+ '} from "./plugins";',
1549
+ 'import { healthRoutes } from "./routes/health";',
1550
+ ];
1551
+
1552
+ const appVariables: string[] = ["RequestIdVariables"];
1553
+
1554
+ if (context.resolvedModules.includes("auth")) {
1555
+ imports.push(
1556
+ 'import { authHandler, requireAuth, sessionMiddleware, type AuthVariables } from "./plugins";'
1557
+ );
1558
+ appVariables.push("AuthVariables");
1559
+ }
1560
+
1561
+ if (context.resolvedModules.includes("organizations")) {
1562
+ imports.push('import { requireActiveOrg } from "./plugins";');
1563
+ }
1564
+
1565
+ if (context.resolvedModules.includes("redis")) {
1566
+ imports.push(
1567
+ 'import { authenticatedRateLimit, publicRateLimit, webhookRateLimit, type RateLimitVariables } from "./plugins";'
1568
+ );
1569
+ appVariables.push("RateLimitVariables");
1570
+ }
1571
+
1572
+ if (context.resolvedModules.includes("observability")) {
1573
+ imports.push('import { tracingMiddleware, type TracingVariables } from "./plugins";');
1574
+ appVariables.push("TracingVariables");
1575
+ }
1576
+
1577
+ if (context.resolvedModules.includes("stripe")) {
1578
+ imports.push('import { stripeWebhooksRoutes } from "./routes/webhooks";');
1579
+ imports.push('import { billingModule } from "./modules/billing";');
1580
+ }
1581
+
1582
+ if (context.resolvedModules.includes("inngest")) {
1583
+ imports.push('import { inngestServeHandler } from "./lib/inngest";');
1584
+ }
1585
+
1586
+ const lines = [
1587
+ ...imports,
1588
+ "",
1589
+ "configureBackendLogger();",
1590
+ "",
1591
+ `type AppVariables = ${appVariables.join(" & ")};`,
1592
+ "",
1593
+ "const app = createOpenApiApp<{ Variables: AppVariables }>();",
1594
+ "const apiRoutes = createOpenApiApp<{ Variables: AppVariables }>();",
1595
+ "",
1596
+ "app.onError(errorHandler);",
1597
+ 'app.use("*", requestIdMiddleware);',
1598
+ ];
1599
+
1600
+ if (context.resolvedModules.includes("observability")) {
1601
+ lines.push('app.use("*", tracingMiddleware);');
1602
+ }
1603
+
1604
+ lines.push(
1605
+ 'app.use("*", metricsMiddleware);',
1606
+ 'app.use("*", loggingMiddleware);',
1607
+ "app.use(",
1608
+ ' "*",',
1609
+ " cors({",
1610
+ " origin: env.CORS_ORIGIN,",
1611
+ ' allowHeaders: ["Content-Type", "Authorization", "X-Organization-Id", REQUEST_ID_HEADER],',
1612
+ ' allowMethods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],',
1613
+ " credentials: true,",
1614
+ " exposeHeaders: [REQUEST_ID_HEADER],",
1615
+ " })",
1616
+ ");",
1617
+ "",
1618
+ 'app.doc31("/openapi.json", {',
1619
+ ' openapi: "3.1.0",',
1620
+ " info: {",
1621
+ ` title: "${context.tokens.projectTitle} API",`,
1622
+ ' version: "1.0.0",',
1623
+ ` description: "${context.tokens.projectTitle} REST API",`,
1624
+ " },",
1625
+ ' servers: [{ url: env.APP_URL, description: "Application" }],',
1626
+ "});",
1627
+ 'app.route("/", openApiRoutes);',
1628
+ 'app.route("/metrics", metricsRoutes);',
1629
+ 'app.route("/health", healthRoutes);'
1630
+ );
1631
+
1632
+ if (context.resolvedModules.includes("stripe")) {
1633
+ if (context.resolvedModules.includes("redis")) {
1634
+ lines.push('app.use("/api/webhooks/*", webhookRateLimit);');
1635
+ }
1636
+ lines.push('app.route("/api/webhooks", stripeWebhooksRoutes);');
1637
+ }
1638
+
1639
+ if (context.resolvedModules.includes("inngest")) {
1640
+ lines.push('app.on(["GET", "POST"], "/api/inngest", inngestServeHandler);');
1641
+ }
1642
+
1643
+ if (context.resolvedModules.includes("auth")) {
1644
+ if (context.resolvedModules.includes("redis")) {
1645
+ lines.push('app.use("/api/auth/*", publicRateLimit);');
1646
+ }
1647
+ lines.push('app.on(["GET", "POST"], "/api/auth/*", authHandler);');
1648
+ lines.push('apiRoutes.use("*", sessionMiddleware);');
1649
+ if (context.resolvedModules.includes("redis")) {
1650
+ lines.push('apiRoutes.use("*", authenticatedRateLimit);');
1651
+ }
1652
+ lines.push('apiRoutes.use("*", requireAuth);');
1653
+ if (context.resolvedModules.includes("organizations")) {
1654
+ lines.push('apiRoutes.use("*", requireActiveOrg);');
1655
+ }
1656
+ } else if (context.resolvedModules.includes("redis")) {
1657
+ lines.push('apiRoutes.use("*", publicRateLimit);');
1658
+ }
1659
+
1660
+ lines.push('apiRoutes.route("/items", itemsModule);');
1661
+
1662
+ if (context.resolvedModules.includes("stripe")) {
1663
+ lines.push('apiRoutes.route("/billing", billingModule);');
1664
+ }
1665
+
1666
+ lines.push('app.route("/api/v1", apiRoutes);', "", "export default app;", "");
1667
+ return lines.join("\n");
1668
+ }
1669
+
1670
+ function buildAuthPlugin(context: GenerateContext) {
1671
+ const requireActiveOrg = context.resolvedModules.includes("organizations")
1672
+ ? [
1673
+ "",
1674
+ "export const requireActiveOrg = createMiddleware<{ Variables: AuthVariables }>(async (c, next) => {",
1675
+ ' const session = c.get("session");',
1676
+ " const activeOrganizationId = session?.activeOrganizationId ?? null;",
1677
+ " if (!activeOrganizationId) {",
1678
+ ' throw new ForbiddenError("No active organization");',
1679
+ " }",
1680
+ ' c.set("orgId", activeOrganizationId);',
1681
+ " await next();",
1682
+ "});",
1683
+ ].join("\n")
1684
+ : "";
1685
+
1686
+ return [
1687
+ 'import { createMiddleware } from "hono/factory";',
1688
+ 'import { auth } from "../lib/auth/auth";',
1689
+ 'import { ForbiddenError, UnauthorizedError } from "../lib/errors";',
1690
+ "",
1691
+ "export type AuthUser = typeof auth.$Infer.Session.user;",
1692
+ "export type AuthSession = typeof auth.$Infer.Session.session;",
1693
+ "export type AuthVariables = {",
1694
+ " orgId: string | null;",
1695
+ " session: AuthSession | null;",
1696
+ " user: AuthUser | null;",
1697
+ "};",
1698
+ "",
1699
+ "export const sessionMiddleware = createMiddleware<{ Variables: AuthVariables }>(async (c, next) => {",
1700
+ " const session = await auth.api.getSession({ headers: c.req.raw.headers });",
1701
+ " if (!session) {",
1702
+ ' c.set("user", null);',
1703
+ ' c.set("session", null);',
1704
+ ' c.set("orgId", null);',
1705
+ " await next();",
1706
+ " return;",
1707
+ " }",
1708
+ ' c.set("user", session.user);',
1709
+ ' c.set("session", session.session);',
1710
+ ' c.set("orgId", session.session.activeOrganizationId ?? null);',
1711
+ " await next();",
1712
+ "});",
1713
+ "",
1714
+ "export const requireAuth = createMiddleware<{ Variables: AuthVariables }>(async (c, next) => {",
1715
+ ' if (!c.get("user")) {',
1716
+ " throw new UnauthorizedError();",
1717
+ " }",
1718
+ " await next();",
1719
+ "});",
1720
+ requireActiveOrg,
1721
+ "",
1722
+ "export const requireSuperadmin = createMiddleware<{ Variables: AuthVariables }>(async (c, next) => {",
1723
+ ' if (c.get("user")?.role !== "superadmin") {',
1724
+ " throw new ForbiddenError();",
1725
+ " }",
1726
+ " await next();",
1727
+ "});",
1728
+ "",
1729
+ "export const authHandler = (c: { req: { raw: Request } }) => auth.handler(c.req.raw);",
1730
+ "export { auth };",
1731
+ "",
1732
+ ].join("\n");
1733
+ }
1734
+
1735
+ function buildAuthConfig(context: GenerateContext) {
1736
+ const pluginImports = context.resolvedModules.includes("organizations")
1737
+ ? 'import { admin, organization } from "better-auth/plugins";'
1738
+ : 'import { admin } from "better-auth/plugins";';
1739
+
1740
+ const orgPluginBlock = context.resolvedModules.includes("organizations")
1741
+ ? [
1742
+ " organization({",
1743
+ " allowUserToCreateOrganization: true,",
1744
+ " schema: {",
1745
+ ' session: { fields: { activeOrganizationId: "active_organization_id" } },',
1746
+ ' organization: { fields: { createdAt: "created_at", updatedAt: "updated_at" } },',
1747
+ ' member: { fields: { organizationId: "organization_id", userId: "user_id", createdAt: "created_at" } },',
1748
+ ' invitation: { fields: { organizationId: "organization_id", inviterId: "inviter_id", expiresAt: "expires_at", createdAt: "created_at" } },',
1749
+ " },",
1750
+ " }),",
1751
+ ].join("\n")
1752
+ : "";
1753
+
1754
+ const schemaEntries = [
1755
+ " user: schema.user,",
1756
+ " session: schema.session,",
1757
+ " account: schema.account,",
1758
+ " verification: schema.verification,",
1759
+ ];
1760
+ if (context.resolvedModules.includes("organizations")) {
1761
+ schemaEntries.push(
1762
+ " organization: schema.organization,",
1763
+ " member: schema.member,",
1764
+ " invitation: schema.invitation,"
1765
+ );
1766
+ }
1767
+
1768
+ return replaceTemplateTokens(
1769
+ [
1770
+ 'import { betterAuth } from "better-auth";',
1771
+ 'import { drizzleAdapter } from "better-auth/adapters/drizzle";',
1772
+ pluginImports,
1773
+ 'import { db } from "../../db";',
1774
+ 'import { env } from "../../env";',
1775
+ 'import * as schema from "../../db/schema";',
1776
+ 'import { generateId } from "../id";',
1777
+ "",
1778
+ 'const trustedOrigins = [env.BETTER_AUTH_URL, ...env.CORS_ORIGIN.split(",").map(origin => origin.trim())].filter(Boolean);',
1779
+ "",
1780
+ "export const auth = betterAuth({",
1781
+ " secret: env.BETTER_AUTH_SECRET,",
1782
+ " baseURL: env.BETTER_AUTH_URL,",
1783
+ " trustedOrigins,",
1784
+ " database: drizzleAdapter(db, {",
1785
+ ' provider: "pg",',
1786
+ " schema: {",
1787
+ ...schemaEntries,
1788
+ " },",
1789
+ " }),",
1790
+ " emailAndPassword: {",
1791
+ " enabled: true,",
1792
+ " minPasswordLength: 8,",
1793
+ " maxPasswordLength: 128,",
1794
+ " },",
1795
+ " advanced: {",
1796
+ " database: {",
1797
+ " generateId: () => generateId(),",
1798
+ " },",
1799
+ ' cookiePrefix: "{{projectName}}",',
1800
+ ' useSecureCookies: env.NODE_ENV === "production",',
1801
+ " },",
1802
+ " session: {",
1803
+ " cookieCache: { enabled: true, maxAge: 60 * 5 },",
1804
+ " expiresIn: 60 * 60 * 24 * 7,",
1805
+ " updateAge: 60 * 60 * 24,",
1806
+ " fields: {",
1807
+ ' userId: "user_id",',
1808
+ ' expiresAt: "expires_at",',
1809
+ ' ipAddress: "ip_address",',
1810
+ ' userAgent: "user_agent",',
1811
+ ' activeOrganizationId: "active_organization_id",',
1812
+ ' impersonatedBy: "impersonated_by",',
1813
+ ' createdAt: "created_at",',
1814
+ ' updatedAt: "updated_at",',
1815
+ " },",
1816
+ " },",
1817
+ ' user: { fields: { emailVerified: "email_verified", createdAt: "created_at", updatedAt: "updated_at" } },',
1818
+ ' account: { fields: { userId: "user_id", accountId: "account_id", providerId: "provider_id", accessToken: "access_token", refreshToken: "refresh_token", idToken: "id_token", accessTokenExpiresAt: "access_token_expires_at", refreshTokenExpiresAt: "refresh_token_expires_at", createdAt: "created_at", updatedAt: "updated_at" } },',
1819
+ ' verification: { fields: { expiresAt: "expires_at", createdAt: "created_at", updatedAt: "updated_at" } },',
1820
+ " plugins: [",
1821
+ orgPluginBlock,
1822
+ " admin({",
1823
+ ' adminRoles: ["superadmin"],',
1824
+ " schema: {",
1825
+ ' user: { fields: { banReason: "ban_reason", banExpires: "ban_expires" } },',
1826
+ ' session: { fields: { impersonatedBy: "impersonated_by" } },',
1827
+ " },",
1828
+ " }),",
1829
+ " ],",
1830
+ "});",
1831
+ "",
1832
+ "export type Auth = typeof auth;",
1833
+ "",
1834
+ ].join("\n"),
1835
+ context.tokens
1836
+ );
1837
+ }
1838
+
1839
+ function buildAuthContext() {
1840
+ return [
1841
+ 'import type { Context } from "hono";',
1842
+ 'import { auth } from "./auth";',
1843
+ "",
1844
+ "export type AuthUser = typeof auth.$Infer.Session.user;",
1845
+ "export type AuthSession = typeof auth.$Infer.Session.session;",
1846
+ "",
1847
+ "export async function getAuthContext(c: Context) {",
1848
+ " const session = await auth.api.getSession({ headers: c.req.raw.headers });",
1849
+ " if (!session) {",
1850
+ " return { user: null, session: null, activeOrganizationId: null };",
1851
+ " }",
1852
+ " return {",
1853
+ " user: session.user,",
1854
+ " session: session.session,",
1855
+ " activeOrganizationId: session.session.activeOrganizationId ?? null,",
1856
+ " };",
1857
+ "}",
1858
+ "",
1859
+ ].join("\n");
1860
+ }
1861
+
1862
+ function buildAuthSchema(context: GenerateContext) {
1863
+ const basic = [
1864
+ 'import { boolean, index, jsonb, pgTable, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";',
1865
+ 'import { generateId } from "../../lib/id";',
1866
+ "",
1867
+ 'export const user = pgTable("user", {',
1868
+ ' id: text("id").primaryKey(),',
1869
+ ' name: text("name").notNull(),',
1870
+ ' email: text("email").notNull().unique(),',
1871
+ ' email_verified: boolean("email_verified").default(false).notNull(),',
1872
+ ' image: text("image"),',
1873
+ ' role: text("role"),',
1874
+ ' banned: boolean("banned").default(false).notNull(),',
1875
+ ' ban_reason: text("ban_reason"),',
1876
+ ' ban_expires: timestamp("ban_expires"),',
1877
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
1878
+ ' updated_at: timestamp("updated_at").defaultNow().$onUpdate(() => new Date()).notNull(),',
1879
+ "});",
1880
+ "",
1881
+ context.resolvedModules.includes("organizations")
1882
+ ? 'export const organization = pgTable("organization", { id: text("id").primaryKey().$defaultFn(() => generateId()), name: text("name").notNull(), slug: text("slug").notNull().unique(), logo: text("logo"), metadata: jsonb("metadata").$type<Record<string, unknown>>(), created_at: timestamp("created_at").defaultNow().notNull(), updated_at: timestamp("updated_at").defaultNow().$onUpdate(() => new Date()) });'
1883
+ : "",
1884
+ "",
1885
+ 'export const session = pgTable("session", {',
1886
+ ' id: text("id").primaryKey(),',
1887
+ ' expires_at: timestamp("expires_at").notNull(),',
1888
+ ' token: text("token").notNull().unique(),',
1889
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
1890
+ ' updated_at: timestamp("updated_at").$onUpdate(() => new Date()).notNull(),',
1891
+ ' ip_address: text("ip_address"),',
1892
+ ' user_agent: text("user_agent"),',
1893
+ ` active_organization_id: text("active_organization_id")${context.resolvedModules.includes("organizations") ? '.references(() => organization.id, { onDelete: "set null" })' : ""},`,
1894
+ ' impersonated_by: text("impersonated_by").references(() => user.id, { onDelete: "set null" }),',
1895
+ ' user_id: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),',
1896
+ '}, table => [index("session_user_id_idx").on(table.user_id)]);',
1897
+ "",
1898
+ 'export const account = pgTable("account", {',
1899
+ ' id: text("id").primaryKey(),',
1900
+ ' account_id: text("account_id").notNull(),',
1901
+ ' provider_id: text("provider_id").notNull(),',
1902
+ ' user_id: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),',
1903
+ ' access_token: text("access_token"),',
1904
+ ' refresh_token: text("refresh_token"),',
1905
+ ' id_token: text("id_token"),',
1906
+ ' access_token_expires_at: timestamp("access_token_expires_at"),',
1907
+ ' refresh_token_expires_at: timestamp("refresh_token_expires_at"),',
1908
+ ' scope: text("scope"),',
1909
+ ' password: text("password"),',
1910
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
1911
+ ' updated_at: timestamp("updated_at").$onUpdate(() => new Date()).notNull(),',
1912
+ '}, table => [index("account_user_id_idx").on(table.user_id)]);',
1913
+ "",
1914
+ 'export const verification = pgTable("verification", {',
1915
+ ' id: text("id").primaryKey(),',
1916
+ ' identifier: text("identifier").notNull(),',
1917
+ ' value: text("value").notNull(),',
1918
+ ' expires_at: timestamp("expires_at").notNull(),',
1919
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
1920
+ ' updated_at: timestamp("updated_at").defaultNow().$onUpdate(() => new Date()).notNull(),',
1921
+ '}, table => [index("verification_identifier_idx").on(table.identifier)]);',
1922
+ ];
1923
+
1924
+ if (!context.resolvedModules.includes("organizations")) {
1925
+ return `${basic.join("\n")}\n`;
1926
+ }
1927
+
1928
+ return [
1929
+ ...basic,
1930
+ "",
1931
+ 'export const member = pgTable("member", {',
1932
+ ' id: text("id").primaryKey().$defaultFn(() => generateId()),',
1933
+ ' organization_id: text("organization_id").notNull().references(() => organization.id, { onDelete: "cascade" }),',
1934
+ ' user_id: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),',
1935
+ ' role: text("role").notNull(),',
1936
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
1937
+ '}, table => [index("member_organization_id_idx").on(table.organization_id), index("member_user_id_idx").on(table.user_id), uniqueIndex("member_org_user_unique").on(table.organization_id, table.user_id)]);',
1938
+ "",
1939
+ 'export const invitation = pgTable("invitation", {',
1940
+ ' id: text("id").primaryKey().$defaultFn(() => generateId()),',
1941
+ ' organization_id: text("organization_id").notNull().references(() => organization.id, { onDelete: "cascade" }),',
1942
+ ' email: text("email").notNull(),',
1943
+ ' role: text("role").notNull(),',
1944
+ ' status: text("status").default("pending").notNull(),',
1945
+ ' expires_at: timestamp("expires_at").notNull(),',
1946
+ ' inviter_id: text("inviter_id").notNull().references(() => user.id, { onDelete: "cascade" }),',
1947
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
1948
+ '}, table => [index("invitation_organization_id_idx").on(table.organization_id), index("invitation_inviter_id_idx").on(table.inviter_id), index("invitation_email_idx").on(table.email)]);',
1949
+ "",
1950
+ ].join("\n");
1951
+ }
1952
+
1953
+ function buildOrganizationFiles() {
1954
+ return {
1955
+ "src/lib/auth/org-context.ts": [
1956
+ 'import type { Context } from "hono";',
1957
+ 'import { ValidationError } from "../errors";',
1958
+ 'import type { AuthSession, AuthUser } from "./auth-context";',
1959
+ "",
1960
+ "type OrgContextVariables = { user: AuthUser | null; session: AuthSession | null };",
1961
+ "",
1962
+ "export function getOrgId<Variables extends OrgContextVariables>(c: Context<{ Variables: Variables }>) {",
1963
+ ' const user = c.get("user");',
1964
+ ' const session = c.get("session");',
1965
+ ' if (user?.role === "superadmin") {',
1966
+ ' const organizationId = c.req.header("x-organization-id");',
1967
+ ' if (!organizationId) throw new ValidationError("Superadmin must specify X-Organization-Id");',
1968
+ " return organizationId;",
1969
+ " }",
1970
+ " const activeOrganizationId = session?.activeOrganizationId ?? null;",
1971
+ ' if (!activeOrganizationId) throw new ValidationError("No active organization");',
1972
+ " return activeOrganizationId;",
1973
+ "}",
1974
+ "",
1975
+ ].join("\n"),
1976
+ "src/lib/auth/permissions.ts": [
1977
+ "export const defaultOrganizationRoles = {",
1978
+ ' owner: ["organizations:manage", "billing:manage", "items:write", "items:read"],',
1979
+ ' admin: ["items:write", "items:read", "billing:read"],',
1980
+ ' member: ["items:read"],',
1981
+ "} as const;",
1982
+ "",
1983
+ "export function createAccessControl() {",
1984
+ " return defaultOrganizationRoles;",
1985
+ "}",
1986
+ "",
1987
+ ].join("\n"),
1988
+ };
1989
+ }
1990
+
1991
+ function buildStripeFiles(context: GenerateContext) {
1992
+ const webhookBody = context.resolvedModules.includes("inngest")
1993
+ ? ' await inngest.send({ name: "billing/stripe.webhook.received", data: { eventId: event.id, eventType: event.type, payload: event as unknown as Record<string, unknown> } });'
1994
+ : " void event;";
1995
+
1996
+ const webhookImport = context.resolvedModules.includes("inngest")
1997
+ ? 'import { inngest } from "../lib/inngest";'
1998
+ : "";
1999
+
2000
+ return {
2001
+ "src/lib/integrations/stripe.ts": [
2002
+ 'import Stripe from "stripe";',
2003
+ 'import { env } from "../../env";',
2004
+ "",
2005
+ 'const DEFAULT_CHECKOUT_CANCEL_PATH = "/billing";',
2006
+ 'const DEFAULT_CHECKOUT_SUCCESS_PATH = "/billing/success";',
2007
+ "",
2008
+ "function trimTrailingSlashes(value: string) {",
2009
+ ' return value.replace(/\\/+$/, "");',
2010
+ "}",
2011
+ "",
2012
+ "export class StripeClient {",
2013
+ ' constructor(public readonly sdk = new Stripe(env.STRIPE_SECRET_KEY ?? "sk_test_placeholder", { maxNetworkRetries: 2 })) {}',
2014
+ "",
2015
+ " buildCheckoutCancelUrl() {",
2016
+ " return `${trimTrailingSlashes(env.APP_URL)}${env.STRIPE_CHECKOUT_CANCEL_PATH ?? DEFAULT_CHECKOUT_CANCEL_PATH}`;",
2017
+ " }",
2018
+ "",
2019
+ " buildCheckoutSuccessUrl() {",
2020
+ " return `${trimTrailingSlashes(env.APP_URL)}${env.STRIPE_CHECKOUT_SUCCESS_PATH ?? DEFAULT_CHECKOUT_SUCCESS_PATH}?session_id={CHECKOUT_SESSION_ID}`;",
2021
+ " }",
2022
+ "",
2023
+ " constructWebhookEvent(input: { payload: string; signature: string }) {",
2024
+ " if (!env.STRIPE_WEBHOOK_SECRET) {",
2025
+ ' throw new Error("Stripe webhook secret is missing");',
2026
+ " }",
2027
+ " return this.sdk.webhooks.constructEvent(input.payload, input.signature, env.STRIPE_WEBHOOK_SECRET);",
2028
+ " }",
2029
+ "",
2030
+ " createCheckoutSession(input: { customerId: string; planId: string; planSlug: string; priceId: string }) {",
2031
+ " return this.sdk.checkout.sessions.create({",
2032
+ ' mode: "subscription",',
2033
+ " customer: input.customerId,",
2034
+ " line_items: [{ price: input.priceId, quantity: 1 }],",
2035
+ " metadata: { plan_id: input.planId, plan_slug: input.planSlug },",
2036
+ " subscription_data: { metadata: { plan_id: input.planId, plan_slug: input.planSlug } },",
2037
+ " success_url: this.buildCheckoutSuccessUrl(),",
2038
+ " cancel_url: this.buildCheckoutCancelUrl(),",
2039
+ " });",
2040
+ " }",
2041
+ "}",
2042
+ "",
2043
+ "export const stripeClient = new StripeClient();",
2044
+ "",
2045
+ ].join("\n"),
2046
+ "src/lib/billing.ts": [
2047
+ 'import { db, type Database } from "../db";',
2048
+ 'import type { BillingFeature } from "../db/schema";',
2049
+ 'import * as billingRepository from "../modules/billing/repository";',
2050
+ "",
2051
+ 'type Transaction = Parameters<Parameters<Database["transaction"]>[0]>[0];',
2052
+ "type DatabaseClient = Database | Transaction;",
2053
+ "",
2054
+ "export async function hasFeature(organizationId: string, feature: BillingFeature, database: DatabaseClient = db) {",
2055
+ " const value = await billingRepository.getFeatureValueForOrganization(database, organizationId, feature);",
2056
+ " if (!value) return false;",
2057
+ ' return value.value_type === "boolean" ? value.value_boolean ?? false : (value.value_integer ?? 0) !== 0;',
2058
+ "}",
2059
+ "",
2060
+ "export async function getFeatureLimit(organizationId: string, feature: BillingFeature, database: DatabaseClient = db) {",
2061
+ " const value = await billingRepository.getFeatureValueForOrganization(database, organizationId, feature);",
2062
+ ' if (!value || value.value_type !== "integer") return 0;',
2063
+ " return value.value_integer ?? 0;",
2064
+ "}",
2065
+ "",
2066
+ ].join("\n"),
2067
+ "src/routes/webhooks.ts": [
2068
+ 'import { Hono } from "hono";',
2069
+ webhookImport,
2070
+ 'import { stripeClient } from "../lib/integrations/stripe";',
2071
+ "",
2072
+ "export const stripeWebhooksRoutes = new Hono();",
2073
+ "",
2074
+ 'stripeWebhooksRoutes.post("/stripe", async c => {',
2075
+ " const rawBody = await c.req.text();",
2076
+ ' const signature = c.req.header("stripe-signature");',
2077
+ " if (!signature) {",
2078
+ ' return c.json({ error: "Invalid webhook signature" }, 400);',
2079
+ " }",
2080
+ " let event;",
2081
+ " try {",
2082
+ " event = stripeClient.constructWebhookEvent({ payload: rawBody, signature });",
2083
+ " } catch {",
2084
+ ' return c.json({ error: "Invalid webhook signature" }, 400);',
2085
+ " }",
2086
+ webhookBody,
2087
+ " return c.json({ received: true }, 200);",
2088
+ "});",
2089
+ "",
2090
+ ]
2091
+ .filter(Boolean)
2092
+ .join("\n"),
2093
+ "src/db/schema/billing.ts": [
2094
+ 'import { boolean, index, integer, pgEnum, pgTable, text, timestamp, uniqueIndex, varchar } from "drizzle-orm/pg-core";',
2095
+ 'import { generateId } from "../../lib/id";',
2096
+ context.resolvedModules.includes("organizations")
2097
+ ? 'import { organization } from "./auth";'
2098
+ : 'import { user as organization } from "./auth";',
2099
+ "",
2100
+ 'export const billingFeatureValues = ["projects", "storage", "team_members", "priority_support"] as const;',
2101
+ 'export const billingPlanFeatureValueTypeValues = ["boolean", "integer"] as const;',
2102
+ 'export const billingSubscriptionStatusValues = ["active", "past_due", "canceled", "trialing"] as const;',
2103
+ "",
2104
+ 'export const billingFeatureEnum = pgEnum("billing_feature", billingFeatureValues);',
2105
+ 'export const billingPlanFeatureValueTypeEnum = pgEnum("billing_plan_feature_value_type", billingPlanFeatureValueTypeValues);',
2106
+ 'export const billingSubscriptionStatusEnum = pgEnum("billing_subscription_status", billingSubscriptionStatusValues);',
2107
+ "",
2108
+ "export type BillingFeature = (typeof billingFeatureValues)[number];",
2109
+ "",
2110
+ 'export const plan = pgTable("plan", {',
2111
+ ' id: text("id").primaryKey().$defaultFn(() => generateId()),',
2112
+ ' name: varchar("name", { length: 100 }).notNull(),',
2113
+ ' slug: varchar("slug", { length: 50 }).notNull(),',
2114
+ ' stripe_price_id: text("stripe_price_id").notNull(),',
2115
+ ' monthly_price_cents: integer("monthly_price_cents").notNull(),',
2116
+ ' is_active: boolean("is_active").default(true).notNull(),',
2117
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
2118
+ ' updated_at: timestamp("updated_at").defaultNow().$onUpdate(() => new Date()).notNull(),',
2119
+ '}, table => [uniqueIndex("plan_slug_unique").on(table.slug), uniqueIndex("plan_stripe_price_id_unique").on(table.stripe_price_id), index("plan_is_active_idx").on(table.is_active)]);',
2120
+ "",
2121
+ 'export const planFeature = pgTable("plan_feature", {',
2122
+ ' id: text("id").primaryKey().$defaultFn(() => generateId()),',
2123
+ ' plan_id: text("plan_id").notNull().references(() => plan.id, { onDelete: "cascade" }),',
2124
+ ' feature: billingFeatureEnum("feature").notNull(),',
2125
+ ' value_type: billingPlanFeatureValueTypeEnum("value_type").notNull(),',
2126
+ ' value_boolean: boolean("value_boolean"),',
2127
+ ' value_integer: integer("value_integer"),',
2128
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
2129
+ ' updated_at: timestamp("updated_at").defaultNow().$onUpdate(() => new Date()).notNull(),',
2130
+ '}, table => [index("plan_feature_plan_id_idx").on(table.plan_id), uniqueIndex("plan_feature_plan_feature_unique").on(table.plan_id, table.feature)]);',
2131
+ "",
2132
+ 'export const subscription = pgTable("subscription", {',
2133
+ ' id: text("id").primaryKey().$defaultFn(() => generateId()),',
2134
+ ` organization_id: text("organization_id").notNull().references(() => organization.id, { onDelete: "cascade" }),`,
2135
+ ' plan_id: text("plan_id").notNull().references(() => plan.id, { onDelete: "restrict" }),',
2136
+ ' stripe_subscription_id: text("stripe_subscription_id").notNull(),',
2137
+ ' stripe_customer_id: text("stripe_customer_id").notNull(),',
2138
+ ' status: billingSubscriptionStatusEnum("status").notNull(),',
2139
+ ' current_period_start: timestamp("current_period_start"),',
2140
+ ' current_period_end: timestamp("current_period_end"),',
2141
+ ' canceled_at: timestamp("canceled_at"),',
2142
+ ' created_at: timestamp("created_at").defaultNow().notNull(),',
2143
+ ' updated_at: timestamp("updated_at").defaultNow().$onUpdate(() => new Date()).notNull(),',
2144
+ '}, table => [uniqueIndex("subscription_org_id_unique").on(table.organization_id), uniqueIndex("subscription_stripe_subscription_id_unique").on(table.stripe_subscription_id), index("subscription_plan_id_idx").on(table.plan_id), index("subscription_status_idx").on(table.status)]);',
2145
+ "",
2146
+ ].join("\n"),
2147
+ "src/modules/billing/model.ts": [
2148
+ 'import { z } from "zod";',
2149
+ "",
2150
+ 'const billingFeatureSchema = z.enum(["projects", "storage", "team_members", "priority_support"]);',
2151
+ "export const planSchema = z.object({ id: z.string(), name: z.string(), slug: z.string(), stripe_price_id: z.string(), monthly_price_cents: z.number().int(), is_active: z.boolean() });",
2152
+ 'export const planFeatureSchema = z.object({ id: z.string(), plan_id: z.string(), feature: billingFeatureSchema, value_type: z.enum(["boolean", "integer"]), value_boolean: z.boolean().nullable().optional(), value_integer: z.number().int().nullable().optional() });',
2153
+ 'export const subscriptionSchema = z.object({ id: z.string(), organization_id: z.string(), plan_id: z.string(), stripe_subscription_id: z.string(), stripe_customer_id: z.string(), status: z.enum(["active", "past_due", "canceled", "trialing"]) });',
2154
+ "export const tenantBillingResponseSchema = z.object({ plans: z.array(planSchema.extend({ features: z.array(planFeatureSchema) })), subscription: subscriptionSchema.nullable(), features: z.record(z.string(), z.union([z.boolean(), z.number().int()])) });",
2155
+ "export const checkoutSessionRequestSchema = z.object({ plan_id: z.string().trim().min(1) });",
2156
+ "",
2157
+ ].join("\n"),
2158
+ "src/modules/billing/repository.ts": [
2159
+ 'import { and, asc, eq, inArray } from "drizzle-orm";',
2160
+ 'import { db, type Database } from "../../db";',
2161
+ 'import { plan, planFeature, subscription, type BillingFeature } from "../../db/schema";',
2162
+ "",
2163
+ 'type Transaction = Parameters<Parameters<Database["transaction"]>[0]>[0];',
2164
+ "type DatabaseClient = Database | Transaction;",
2165
+ 'const ACTIVE_STATUSES = ["active", "trialing"] as const;',
2166
+ "",
2167
+ "export async function listPlansWithFeatures(database: DatabaseClient = db) {",
2168
+ " const plans = await database.select().from(plan).orderBy(asc(plan.monthly_price_cents));",
2169
+ " const features = await database.select().from(planFeature);",
2170
+ " return plans.map(record => ({ plan: record, features: features.filter(feature => feature.plan_id === record.id) }));",
2171
+ "}",
2172
+ "",
2173
+ "export async function findSubscriptionByOrganizationId(organizationId: string, database: DatabaseClient = db) {",
2174
+ " const [record] = await database.select().from(subscription).where(eq(subscription.organization_id, organizationId)).limit(1);",
2175
+ " return record ?? null;",
2176
+ "}",
2177
+ "",
2178
+ "export async function getFeatureValueForOrganization(database: DatabaseClient, organizationId: string, feature: BillingFeature) {",
2179
+ " const [record] = await database",
2180
+ " .select({ feature: planFeature })",
2181
+ " .from(subscription)",
2182
+ " .innerJoin(planFeature, eq(subscription.plan_id, planFeature.plan_id))",
2183
+ " .where(and(eq(subscription.organization_id, organizationId), inArray(subscription.status, ACTIVE_STATUSES), eq(planFeature.feature, feature)))",
2184
+ " .limit(1);",
2185
+ " return record?.feature ?? null;",
2186
+ "}",
2187
+ "",
2188
+ ].join("\n"),
2189
+ "src/modules/billing/usecases.ts": [
2190
+ 'import { db } from "../../db";',
2191
+ 'import { stripeClient } from "../../lib/integrations/stripe";',
2192
+ 'import { NotFoundError } from "../../lib/errors";',
2193
+ 'import * as repository from "./repository";',
2194
+ "",
2195
+ "export async function buildBillingView(organizationId: string) {",
2196
+ " const plans = await repository.listPlansWithFeatures(db);",
2197
+ " const subscription = await repository.findSubscriptionByOrganizationId(organizationId, db);",
2198
+ ' const features = Object.fromEntries((subscription ? plans.find(plan => plan.plan.id === subscription.plan_id)?.features ?? [] : []).map(feature => [feature.feature, feature.value_type === "boolean" ? feature.value_boolean ?? false : feature.value_integer ?? 0]));',
2199
+ " return { plans, subscription, features };",
2200
+ "}",
2201
+ "",
2202
+ "export async function createCheckoutSessionForOrganization(organizationId: string, planId: string) {",
2203
+ " const plans = await repository.listPlansWithFeatures(db);",
2204
+ " const targetPlan = plans.find(plan => plan.plan.id === planId)?.plan;",
2205
+ ' if (!targetPlan) throw new NotFoundError("Billing plan");',
2206
+ " return stripeClient.createCheckoutSession({ customerId: organizationId, planId: targetPlan.id, planSlug: targetPlan.slug, priceId: targetPlan.stripe_price_id });",
2207
+ "}",
2208
+ "",
2209
+ ].join("\n"),
2210
+ "src/modules/billing/route.ts": [
2211
+ 'import { zValidator } from "@hono/zod-validator";',
2212
+ 'import { Hono } from "hono";',
2213
+ 'import { ok } from "../../lib/response";',
2214
+ context.resolvedModules.includes("organizations")
2215
+ ? 'import { getOrgId } from "../../lib/auth/org-context";'
2216
+ : "",
2217
+ 'import { checkoutSessionRequestSchema } from "./model";',
2218
+ 'import { buildBillingView, createCheckoutSessionForOrganization } from "./usecases";',
2219
+ "",
2220
+ "export const billingModule = new Hono()",
2221
+ ' .get("/", async c => {',
2222
+ ` const organizationId = ${context.resolvedModules.includes("organizations") ? "getOrgId(c)" : 'c.get("user")?.id ?? "anonymous"'};`,
2223
+ " return c.json(ok(await buildBillingView(organizationId)));",
2224
+ " })",
2225
+ ' .post("/checkout-session", zValidator("json", checkoutSessionRequestSchema), async c => {',
2226
+ ` const organizationId = ${context.resolvedModules.includes("organizations") ? "getOrgId(c)" : 'c.get("user")?.id ?? "anonymous"'};`,
2227
+ ' const session = await createCheckoutSessionForOrganization(organizationId, c.req.valid("json").plan_id);',
2228
+ " return c.redirect(session.url ?? `/billing?session_id=${session.id}`, 303);",
2229
+ " });",
2230
+ "",
2231
+ ]
2232
+ .filter(Boolean)
2233
+ .join("\n"),
2234
+ };
2235
+ }
2236
+
2237
+ function buildStorageFiles() {
2238
+ return {
2239
+ "src/lib/storage/client.ts": [
2240
+ 'import { GetObjectCommand, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";',
2241
+ 'import { getSignedUrl } from "@aws-sdk/s3-request-presigner";',
2242
+ 'import { env } from "../../env";',
2243
+ "",
2244
+ "export function createStorageClient() {",
2245
+ " return new S3Client({",
2246
+ ' region: env.S3_REGION ?? "sa-east-1",',
2247
+ " endpoint: env.S3_ENDPOINT,",
2248
+ " forcePathStyle: Boolean(env.S3_ENDPOINT),",
2249
+ " credentials: env.S3_ACCESS_KEY && env.S3_SECRET_KEY ? { accessKeyId: env.S3_ACCESS_KEY, secretAccessKey: env.S3_SECRET_KEY } : undefined,",
2250
+ " });",
2251
+ "}",
2252
+ "",
2253
+ "export async function createPresignedUploadUrl(key: string, contentType: string) {",
2254
+ " const client = createStorageClient();",
2255
+ " return getSignedUrl(client, new PutObjectCommand({ Bucket: env.S3_BUCKET, Key: key, ContentType: contentType }), { expiresIn: 900 });",
2256
+ "}",
2257
+ "",
2258
+ "export async function createPresignedDownloadUrl(key: string) {",
2259
+ " const client = createStorageClient();",
2260
+ " return getSignedUrl(client, new GetObjectCommand({ Bucket: env.S3_BUCKET, Key: key }), { expiresIn: 3600 });",
2261
+ "}",
2262
+ "",
2263
+ ].join("\n"),
2264
+ "src/lib/storage/index.ts": 'export * from "./client";\n',
2265
+ };
2266
+ }
2267
+
2268
+ function buildEmailFiles() {
2269
+ return {
2270
+ "src/lib/emails/send.ts": [
2271
+ 'import { render } from "@react-email/components";',
2272
+ 'import nodemailer from "nodemailer";',
2273
+ 'import { z } from "zod";',
2274
+ 'import { createResendClient } from "../integrations/resend";',
2275
+ 'import { BaseEmail } from "./templates/base";',
2276
+ "",
2277
+ "const sendEmailSchema = z.object({",
2278
+ " subject: z.string().trim().min(1),",
2279
+ " to: z.array(z.string().email()).min(1),",
2280
+ " body: z.string().trim().min(1),",
2281
+ "});",
2282
+ "",
2283
+ "export async function sendEmail(input: z.input<typeof sendEmailSchema>) {",
2284
+ " const payload = sendEmailSchema.parse(input);",
2285
+ " const html = await render(BaseEmail({ body: payload.body, heading: payload.subject }));",
2286
+ " if (process.env.RESEND_API_KEY) {",
2287
+ " const resendClient = createResendClient();",
2288
+ ' return resendClient.sendEmail({ from: process.env.EMAIL_FROM ?? "noreply@example.com", html, subject: payload.subject, text: payload.body, to: payload.to });',
2289
+ " }",
2290
+ ' const transporter = nodemailer.createTransport({ host: process.env.MAILPIT_HOST ?? "127.0.0.1", port: Number(process.env.MAILPIT_PORT ?? 1025), secure: false });',
2291
+ ' return transporter.sendMail({ from: process.env.EMAIL_FROM ?? "noreply@example.com", html, subject: payload.subject, text: payload.body, to: payload.to });',
2292
+ "}",
2293
+ "",
2294
+ ].join("\n"),
2295
+ "src/lib/emails/templates/base.tsx": [
2296
+ 'import { Body, Container, Head, Heading, Html, Preview, Section, Text } from "@react-email/components";',
2297
+ "",
2298
+ "export function BaseEmail(props: { body: string; heading: string }) {",
2299
+ " return (",
2300
+ " <Html>",
2301
+ " <Head />",
2302
+ " <Preview>{props.heading}</Preview>",
2303
+ " <Body style={{ backgroundColor: '#f6f4ef', fontFamily: 'Geist, sans-serif' }}>",
2304
+ " <Container style={{ maxWidth: '560px', margin: '40px auto', backgroundColor: '#ffffff', padding: '32px', borderRadius: '24px' }}>",
2305
+ " <Section>",
2306
+ " <Heading>{props.heading}</Heading>",
2307
+ " <Text>{props.body}</Text>",
2308
+ " </Section>",
2309
+ " </Container>",
2310
+ " </Body>",
2311
+ " </Html>",
2312
+ " );",
2313
+ "}",
2314
+ "",
2315
+ ].join("\n"),
2316
+ "src/lib/integrations/resend.ts": [
2317
+ 'import { z } from "zod";',
2318
+ "",
2319
+ "const sendEmailSchema = z.object({",
2320
+ " from: z.string().trim().min(1),",
2321
+ " html: z.string().trim().min(1),",
2322
+ " subject: z.string().trim().min(1),",
2323
+ " text: z.string().trim().min(1),",
2324
+ " to: z.array(z.string().email()).min(1),",
2325
+ "});",
2326
+ "",
2327
+ "export function createResendClient(fetcher: typeof fetch = fetch) {",
2328
+ " return {",
2329
+ " async sendEmail(input: z.input<typeof sendEmailSchema>) {",
2330
+ " const payload = sendEmailSchema.parse(input);",
2331
+ ' const response = await fetcher("https://api.resend.com/emails", {',
2332
+ ' method: "POST",',
2333
+ ' headers: { Authorization: `Bearer ${process.env.RESEND_API_KEY}`, "content-type": "application/json" },',
2334
+ " body: JSON.stringify(payload),",
2335
+ " });",
2336
+ " if (!response.ok) {",
2337
+ " throw new Error(`Resend request failed with status ${response.status}`);",
2338
+ " }",
2339
+ " return response.json();",
2340
+ " },",
2341
+ " };",
2342
+ "}",
2343
+ "",
2344
+ ].join("\n"),
2345
+ };
2346
+ }
2347
+
2348
+ function buildInngestFiles(context: GenerateContext) {
2349
+ return {
2350
+ "src/lib/inngest.ts": [
2351
+ 'import { EventSchemas, Inngest } from "inngest";',
2352
+ 'import { z } from "zod";',
2353
+ "",
2354
+ `export const INNGEST_APP_ID = "${context.projectName}";`,
2355
+ 'export const INNGEST_SERVE_PATH = "/api/inngest";',
2356
+ "",
2357
+ "export const billingStripeWebhookReceivedEventDataSchema = z.object({",
2358
+ " eventId: z.string().trim().min(1),",
2359
+ " eventType: z.string().trim().min(1),",
2360
+ " payload: z.record(z.string(), z.unknown()),",
2361
+ "});",
2362
+ "",
2363
+ "export const emailSendRequestedEventDataSchema = z.object({",
2364
+ " emails: z.array(z.object({ to: z.array(z.string().email()).min(1), subject: z.string().trim().min(1), body: z.string().trim().min(1) })).min(1),",
2365
+ "});",
2366
+ "",
2367
+ "export const inngest = new Inngest({",
2368
+ ` id: "${context.projectName}",`,
2369
+ " schemas: new EventSchemas().fromSchema({",
2370
+ ' "billing/stripe.webhook.received": billingStripeWebhookReceivedEventDataSchema,',
2371
+ ' "email/send.requested": emailSendRequestedEventDataSchema,',
2372
+ " }),",
2373
+ "});",
2374
+ "",
2375
+ 'export const inngestServeHandler = inngest.createFunction({ id: "health-check" }, { event: "email/send.requested" }, async ({ event }) => ({ count: event.data.emails.length }));',
2376
+ "",
2377
+ ].join("\n"),
2378
+ "src/jobs/index.ts": [
2379
+ 'import { inngest } from "../lib/inngest";',
2380
+ "",
2381
+ "export const exampleJob = inngest.createFunction(",
2382
+ ' { id: "example-job" },',
2383
+ ' { event: "email/send.requested" },',
2384
+ " async ({ event }) => ({ processed: event.data.emails.length })",
2385
+ ");",
2386
+ "",
2387
+ "export const functions = [exampleJob];",
2388
+ "",
2389
+ ].join("\n"),
2390
+ "src/jobs/example.ts": "export {};\n",
2391
+ };
2392
+ }
2393
+
2394
+ function buildObservabilityFiles(context: GenerateContext) {
2395
+ return {
2396
+ "src/lib/tracing.ts": replaceTemplateTokens(
2397
+ [
2398
+ 'import { trace, SpanKind, SpanStatusCode, context, propagation, ROOT_CONTEXT, type TextMapGetter, type TextMapSetter } from "@opentelemetry/api";',
2399
+ 'import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";',
2400
+ 'import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";',
2401
+ 'import { resourceFromAttributes } from "@opentelemetry/resources";',
2402
+ 'import { NodeSDK } from "@opentelemetry/sdk-node";',
2403
+ 'import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";',
2404
+ 'import { createMiddleware } from "hono/factory";',
2405
+ "",
2406
+ "let tracingSdk: NodeSDK | null = null;",
2407
+ "const headersGetter: TextMapGetter<Headers> = { get: (carrier, key) => carrier.get(key) ?? undefined, keys: carrier => Array.from(carrier.keys()) };",
2408
+ "const headersSetter: TextMapSetter<Headers> = { set: (carrier, key, value) => carrier.set(key, value) };",
2409
+ "",
2410
+ "export type TracingVariables = Record<string, never>;",
2411
+ "",
2412
+ "export async function initializeTracing(rawEnv: Record<string, string | undefined> = process.env) {",
2413
+ ' if (rawEnv.TRACING_ENABLED === "0" || rawEnv.NODE_ENV === "test") return false;',
2414
+ " if (tracingSdk) return true;",
2415
+ " tracingSdk = new NodeSDK({",
2416
+ " autoDetectResources: false,",
2417
+ " resource: resourceFromAttributes({",
2418
+ ' "deployment.environment.name": rawEnv.NODE_ENV ?? "development",',
2419
+ ' "service.name": rawEnv.OTEL_SERVICE_NAME ?? "{{projectName}}-backend",',
2420
+ " }),",
2421
+ ' spanProcessors: [new BatchSpanProcessor(new OTLPTraceExporter({ url: rawEnv.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://localhost:4317" }))],',
2422
+ " instrumentations: [new HttpInstrumentation()],",
2423
+ " });",
2424
+ " await tracingSdk.start();",
2425
+ " return true;",
2426
+ "}",
2427
+ "",
2428
+ "export async function shutdownTracing() {",
2429
+ " if (!tracingSdk) return;",
2430
+ " const sdk = tracingSdk;",
2431
+ " tracingSdk = null;",
2432
+ " await sdk.shutdown();",
2433
+ "}",
2434
+ "",
2435
+ "export const tracingMiddleware = createMiddleware(async (c, next) => {",
2436
+ ' const tracer = trace.getTracer("{{projectName}}-backend");',
2437
+ " const extractedContext = propagation.extract(ROOT_CONTEXT, c.req.raw.headers, headersGetter);",
2438
+ " return tracer.startActiveSpan(`${c.req.method} ${new URL(c.req.url).pathname}`, { kind: SpanKind.SERVER }, extractedContext, async span => {",
2439
+ " try {",
2440
+ " await next();",
2441
+ ' span.setAttribute("http.response.status_code", c.res.status);',
2442
+ " span.setStatus({ code: c.res.status >= 500 ? SpanStatusCode.ERROR : SpanStatusCode.OK });",
2443
+ " } catch (error) {",
2444
+ " span.recordException(error as Error);",
2445
+ " span.setStatus({ code: SpanStatusCode.ERROR });",
2446
+ " throw error;",
2447
+ " } finally {",
2448
+ " propagation.inject(context.active(), c.res.headers, headersSetter);",
2449
+ " span.end();",
2450
+ " }",
2451
+ " });",
2452
+ "});",
2453
+ "",
2454
+ ].join("\n"),
2455
+ context.tokens
2456
+ ),
2457
+ "src/lib/sentry.ts": [
2458
+ 'import * as Sentry from "@sentry/bun";',
2459
+ "",
2460
+ "let isSentryInitialized = false;",
2461
+ "",
2462
+ "function parseTracesSampleRate(rawValue: string | undefined) {",
2463
+ " if (!rawValue) return 0.1;",
2464
+ " const parsedValue = Number(rawValue);",
2465
+ " return Number.isFinite(parsedValue) && parsedValue >= 0 && parsedValue <= 1 ? parsedValue : 0.1;",
2466
+ "}",
2467
+ "",
2468
+ "export function initializeSentry(rawEnv: Record<string, string | undefined> = process.env) {",
2469
+ " const dsn = rawEnv.SENTRY_DSN?.trim();",
2470
+ " if (!dsn || isSentryInitialized) return Boolean(dsn);",
2471
+ ' Sentry.init({ dsn, enabled: true, environment: rawEnv.NODE_ENV ?? "development", tracesSampleRate: parseTracesSampleRate(rawEnv.SENTRY_TRACES_SAMPLE_RATE) });',
2472
+ " isSentryInitialized = true;",
2473
+ " return true;",
2474
+ "}",
2475
+ "",
2476
+ ].join("\n"),
2477
+ };
2478
+ }
2479
+
2480
+ function buildRedisFiles() {
2481
+ return {
2482
+ "src/lib/redis.ts": [
2483
+ 'import type { RedisClient as RateLimitRedisClient } from "@hono-rate-limiter/redis";',
2484
+ "",
2485
+ 'type BunRedisClient = import("bun").RedisClient;',
2486
+ 'type BunRedisConstructor = typeof import("bun").RedisClient;',
2487
+ "",
2488
+ "let sharedRedisClient: BunRedisClient | null = null;",
2489
+ "",
2490
+ "export function hasBunRedisClient() {",
2491
+ " const bun = globalThis as typeof globalThis & { Bun?: { RedisClient?: BunRedisConstructor } };",
2492
+ ' return typeof bun.Bun?.RedisClient === "function";',
2493
+ "}",
2494
+ "",
2495
+ "export function getRedisClient(rawEnv: Record<string, string | undefined> = process.env) {",
2496
+ " const bun = globalThis as typeof globalThis & { Bun?: { RedisClient?: BunRedisConstructor } };",
2497
+ " const RedisClient = bun.Bun?.RedisClient;",
2498
+ ' if (!RedisClient) throw new Error("Bun RedisClient is unavailable outside the Bun runtime");',
2499
+ " if (!sharedRedisClient) {",
2500
+ ' sharedRedisClient = new RedisClient(rawEnv.REDIS_URL ?? "redis://localhost:6379");',
2501
+ " }",
2502
+ " return sharedRedisClient;",
2503
+ "}",
2504
+ "",
2505
+ "export function createRedisRateLimitClient(rawEnv: Record<string, string | undefined> = process.env): RateLimitRedisClient {",
2506
+ " const client = getRedisClient(rawEnv);",
2507
+ " return {",
2508
+ " async scriptLoad(script: string) {",
2509
+ ' const result = await client.send("SCRIPT", ["LOAD", script]);',
2510
+ ' if (typeof result !== "string") throw new TypeError("Redis SCRIPT LOAD returned a non-string response");',
2511
+ " return result;",
2512
+ " },",
2513
+ " evalsha(sha1: string, keys: string[], args: unknown[]) {",
2514
+ ' return client.send("EVALSHA", [sha1, keys.length.toString(), ...keys, ...args.map(String)]);',
2515
+ " },",
2516
+ " decr(key: string) { return client.decr(key); },",
2517
+ " del(key: string) { return client.del(key); },",
2518
+ " };",
2519
+ "}",
2520
+ "",
2521
+ ].join("\n"),
2522
+ "src/plugins/rate-limiter.ts": [
2523
+ 'import { RedisStore } from "@hono-rate-limiter/redis";',
2524
+ 'import { createMiddleware } from "hono/factory";',
2525
+ 'import { MemoryStore, rateLimiter } from "hono-rate-limiter";',
2526
+ 'import { z } from "zod";',
2527
+ 'import { createRedisRateLimitClient, hasBunRedisClient } from "../lib/redis";',
2528
+ "",
2529
+ "const environmentSchema = z.object({",
2530
+ " RATE_LIMIT_WINDOW_MS: z.coerce.number().int().positive().optional(),",
2531
+ " RATE_LIMIT_AUTHENTICATED_LIMIT: z.coerce.number().int().positive().optional(),",
2532
+ " RATE_LIMIT_PUBLIC_LIMIT: z.coerce.number().int().positive().optional(),",
2533
+ " RATE_LIMIT_WEBHOOK_LIMIT: z.coerce.number().int().positive().optional(),",
2534
+ "});",
2535
+ "",
2536
+ "function resolveConfig(rawEnv: Record<string, string | undefined> = process.env) {",
2537
+ " const parsedEnv = environmentSchema.parse(rawEnv);",
2538
+ " return {",
2539
+ " windowMs: parsedEnv.RATE_LIMIT_WINDOW_MS ?? 60000,",
2540
+ " limits: {",
2541
+ " authenticated: parsedEnv.RATE_LIMIT_AUTHENTICATED_LIMIT ?? 300,",
2542
+ " public: parsedEnv.RATE_LIMIT_PUBLIC_LIMIT ?? 30,",
2543
+ " webhook: parsedEnv.RATE_LIMIT_WEBHOOK_LIMIT ?? 120,",
2544
+ " },",
2545
+ " };",
2546
+ "}",
2547
+ "",
2548
+ "function createStore() {",
2549
+ " if (!hasBunRedisClient()) return new MemoryStore();",
2550
+ " return new RedisStore({ client: createRedisRateLimitClient() });",
2551
+ "}",
2552
+ "",
2553
+ "function createLimiter(limit: number, keyGenerator: (c: any) => string) {",
2554
+ " const config = resolveConfig();",
2555
+ " return createMiddleware(async (c, next) => {",
2556
+ " const handler = rateLimiter({ keyGenerator, limit, standardHeaders: 'draft-6', store: createStore(), windowMs: config.windowMs });",
2557
+ " return handler(c, next);",
2558
+ " });",
2559
+ "}",
2560
+ "",
2561
+ "export type RateLimitVariables = Record<string, never>;",
2562
+ 'export const publicRateLimit = createLimiter(resolveConfig().limits.public, c => c.req.header("x-forwarded-for") ?? c.req.header("x-real-ip") ?? "unknown-ip");',
2563
+ 'export const authenticatedRateLimit = createLimiter(resolveConfig().limits.authenticated, c => c.get("user")?.id ?? c.req.header("x-forwarded-for") ?? "anonymous");',
2564
+ "export const webhookRateLimit = createLimiter(resolveConfig().limits.webhook, c => c.req.path);",
2565
+ "",
2566
+ ].join("\n"),
2567
+ };
2568
+ }
2569
+
2570
+ function buildStorybookFiles() {
2571
+ return {
2572
+ "packages/frontend/.storybook/main.ts": [
2573
+ 'import type { StorybookConfig } from "@storybook/react-vite";',
2574
+ "",
2575
+ "const config: StorybookConfig = {",
2576
+ ' framework: "@storybook/react-vite",',
2577
+ ' stories: ["../src/**/*.stories.@(ts|tsx)"],',
2578
+ ' addons: ["@storybook/addon-a11y", "@storybook/addon-docs", "@storybook/addon-onboarding", "@storybook/addon-themes"],',
2579
+ "};",
2580
+ "",
2581
+ "export default config;",
2582
+ "",
2583
+ ].join("\n"),
2584
+ "packages/frontend/.storybook/preview.tsx": [
2585
+ 'import type { Preview } from "@storybook/react";',
2586
+ 'import "../src/styles.css";',
2587
+ "",
2588
+ "const preview: Preview = {",
2589
+ " parameters: {",
2590
+ ' backgrounds: { default: "app" },',
2591
+ " },",
2592
+ "};",
2593
+ "",
2594
+ "export default preview;",
2595
+ "",
2596
+ ].join("\n"),
2597
+ "packages/frontend/src/components/ui/button.stories.tsx": [
2598
+ 'import type { Meta, StoryObj } from "@storybook/react";',
2599
+ 'import { Button } from "./button";',
2600
+ "",
2601
+ "const meta = {",
2602
+ ' title: "UI/Button",',
2603
+ " component: Button,",
2604
+ "} satisfies Meta<typeof Button>;",
2605
+ "",
2606
+ "export default meta;",
2607
+ "type Story = StoryObj<typeof meta>;",
2608
+ "",
2609
+ "export const Primary: Story = {",
2610
+ " args: {",
2611
+ ' children: "Click me",',
2612
+ " },",
2613
+ "};",
2614
+ "",
2615
+ ].join("\n"),
2616
+ };
2617
+ }
2618
+
2619
+ async function writeModuleFiles(context: GenerateContext) {
2620
+ if (context.resolvedModules.includes("auth")) {
2621
+ await writeTextFile(
2622
+ path.join(context.targetDir, "packages/backend/src/plugins/auth.ts"),
2623
+ buildAuthPlugin(context)
2624
+ );
2625
+ await writeTextFile(
2626
+ path.join(context.targetDir, "packages/backend/src/lib/auth/auth.ts"),
2627
+ buildAuthConfig(context)
2628
+ );
2629
+ await writeTextFile(
2630
+ path.join(context.targetDir, "packages/backend/src/lib/auth/auth-context.ts"),
2631
+ buildAuthContext()
2632
+ );
2633
+ await writeTextFile(
2634
+ path.join(context.targetDir, "packages/backend/src/db/schema/auth.ts"),
2635
+ buildAuthSchema(context)
2636
+ );
2637
+ }
2638
+
2639
+ if (context.resolvedModules.includes("organizations")) {
2640
+ for (const [relativePath, content] of Object.entries(buildOrganizationFiles())) {
2641
+ await writeTextFile(path.join(context.targetDir, "packages/backend", relativePath), content);
2642
+ }
2643
+ }
2644
+
2645
+ if (context.resolvedModules.includes("stripe")) {
2646
+ for (const [relativePath, content] of Object.entries(buildStripeFiles(context))) {
2647
+ await writeTextFile(path.join(context.targetDir, "packages/backend", relativePath), content);
2648
+ }
2649
+ }
2650
+
2651
+ if (context.resolvedModules.includes("storage")) {
2652
+ for (const [relativePath, content] of Object.entries(buildStorageFiles())) {
2653
+ await writeTextFile(path.join(context.targetDir, "packages/backend", relativePath), content);
2654
+ }
2655
+ }
2656
+
2657
+ if (context.resolvedModules.includes("email")) {
2658
+ for (const [relativePath, content] of Object.entries(buildEmailFiles())) {
2659
+ await writeTextFile(path.join(context.targetDir, "packages/backend", relativePath), content);
2660
+ }
2661
+ }
2662
+
2663
+ if (context.resolvedModules.includes("inngest")) {
2664
+ for (const [relativePath, content] of Object.entries(buildInngestFiles(context))) {
2665
+ await writeTextFile(path.join(context.targetDir, "packages/backend", relativePath), content);
2666
+ }
2667
+ }
2668
+
2669
+ if (context.resolvedModules.includes("observability")) {
2670
+ for (const [relativePath, content] of Object.entries(buildObservabilityFiles(context))) {
2671
+ await writeTextFile(path.join(context.targetDir, "packages/backend", relativePath), content);
2672
+ }
2673
+ }
2674
+
2675
+ if (context.resolvedModules.includes("redis")) {
2676
+ for (const [relativePath, content] of Object.entries(buildRedisFiles())) {
2677
+ await writeTextFile(path.join(context.targetDir, "packages/backend", relativePath), content);
2678
+ }
2679
+ }
2680
+
2681
+ if (context.resolvedModules.includes("storybook")) {
2682
+ for (const [relativePath, content] of Object.entries(buildStorybookFiles())) {
2683
+ await writeTextFile(path.join(context.targetDir, relativePath), content);
2684
+ }
2685
+ }
2686
+ }
2687
+
2688
+ async function writeDynamicFiles(context: GenerateContext) {
2689
+ await ensureDir(path.join(context.targetDir, ".github/workflows"));
2690
+ await ensureDir(path.join(context.targetDir, ".husky"));
2691
+ await ensureDir(path.join(context.targetDir, "docker/postgres"));
2692
+ await ensureDir(path.join(context.targetDir, ".claude"));
2693
+ await ensureDir(path.join(context.targetDir, ".agents"));
2694
+
2695
+ await patchPluginNames(context);
2696
+
2697
+ await writeTextFile(
2698
+ path.join(context.targetDir, "package.json"),
2699
+ toJson(buildRootPackageJson(context))
2700
+ );
2701
+ await writeTextFile(
2702
+ path.join(context.targetDir, "turbo.json"),
2703
+ toJson(buildTurboConfig(context))
2704
+ );
2705
+ await writeTextFile(path.join(context.targetDir, ".gitignore"), buildGitignore());
2706
+ await writeTextFile(
2707
+ path.join(context.targetDir, ".oxlintrc.json"),
2708
+ buildOxlintConfig(context.projectName)
2709
+ );
2710
+ await writeTextFile(
2711
+ path.join(context.targetDir, "commitlint.config.ts"),
2712
+ buildCommitlintConfig()
2713
+ );
2714
+ await writeTextFile(path.join(context.targetDir, "Makefile"), buildMakefile(context));
2715
+ await writeTextFile(
2716
+ path.join(context.targetDir, "docker-compose.yml"),
2717
+ buildDockerCompose(context)
2718
+ );
2719
+ await writeTextFile(
2720
+ path.join(context.targetDir, "docker/postgres/init-test-db.sh"),
2721
+ buildInitTestDbScript(context)
2722
+ );
2723
+ await writeInstructionFiles(context.targetDir, buildClaudeMd(context, separatedClaudeMdBuilder));
2724
+ await writeTextFile(path.join(context.targetDir, ".claude/settings.json"), buildClaudeSettings());
2725
+ await writeTextFile(path.join(context.targetDir, ".github/workflows/ci.yaml"), buildCiWorkflow());
2726
+ await writeTextFile(
2727
+ path.join(context.targetDir, ".husky/pre-commit"),
2728
+ "#!/usr/bin/env sh\nbunx lint-staged\n"
2729
+ );
2730
+ await writeTextFile(
2731
+ path.join(context.targetDir, ".husky/commit-msg"),
2732
+ '#!/usr/bin/env sh\nbunx --no -- commitlint --edit "$1"\n'
2733
+ );
2734
+
2735
+ await writeTextFile(
2736
+ path.join(context.targetDir, "packages/frontend/package.json"),
2737
+ toJson(buildFrontendPackageJson(context))
2738
+ );
2739
+ await writeTextFile(
2740
+ path.join(context.targetDir, "packages/frontend/index.html"),
2741
+ buildFrontendIndexHtml(context)
2742
+ );
2743
+ await writeTextFile(
2744
+ path.join(context.targetDir, "packages/frontend/vitest.config.ts"),
2745
+ buildFrontendVitestConfig(context)
2746
+ );
2747
+ await writeTextFile(
2748
+ path.join(context.targetDir, "packages/frontend/src/main.tsx"),
2749
+ buildFrontendMain()
2750
+ );
2751
+ await writeTextFile(
2752
+ path.join(context.targetDir, "packages/frontend/src/styles.css"),
2753
+ buildFrontendStyles()
2754
+ );
2755
+ await writeTextFile(
2756
+ path.join(context.targetDir, "packages/frontend/src/stores/use-theme-store.ts"),
2757
+ buildFrontendThemeStore(context)
2758
+ );
2759
+ await writeTextFile(
2760
+ path.join(context.targetDir, "packages/frontend/src/components/app-sidebar.tsx"),
2761
+ buildFrontendSidebar(context)
2762
+ );
2763
+ await writeTextFile(
2764
+ path.join(context.targetDir, "packages/frontend/src/routes/_dashboard/index.tsx"),
2765
+ buildFrontendDashboardIndex(context)
2766
+ );
2767
+ await writeTextFile(
2768
+ path.join(context.targetDir, "packages/frontend/src/routes/_dashboard/settings.tsx"),
2769
+ buildFrontendSettings()
2770
+ );
2771
+ await writeTextFile(
2772
+ path.join(context.targetDir, "packages/frontend/src/routeTree.gen.ts"),
2773
+ buildFrontendRouteTree()
2774
+ );
2775
+ await writeTextFile(
2776
+ path.join(context.targetDir, "packages/frontend/src/App.test.tsx"),
2777
+ buildFrontendAppTest(context)
2778
+ );
2779
+
2780
+ await writeTextFile(
2781
+ path.join(context.targetDir, "packages/backend/package.json"),
2782
+ toJson(buildBackendPackageJson(context))
2783
+ );
2784
+ await writeTextFile(
2785
+ path.join(context.targetDir, "packages/backend/.env.example"),
2786
+ buildBackendEnvExample(context)
2787
+ );
2788
+ await writeTextFile(
2789
+ path.join(context.targetDir, "packages/backend/src/index.ts"),
2790
+ buildBackendIndex(context)
2791
+ );
2792
+ await writeTextFile(
2793
+ path.join(context.targetDir, "packages/backend/src/env.ts"),
2794
+ buildBackendEnvTs(context)
2795
+ );
2796
+ await writeTextFile(
2797
+ path.join(context.targetDir, "packages/backend/src/app.ts"),
2798
+ buildBackendApp(context)
2799
+ );
2800
+ await writeTextFile(
2801
+ path.join(context.targetDir, "packages/backend/src/routes/health.ts"),
2802
+ buildBackendHealthRoute(context)
2803
+ );
2804
+ await writeTextFile(
2805
+ path.join(context.targetDir, "packages/backend/src/plugins/index.ts"),
2806
+ buildBackendPluginsIndex(context)
2807
+ );
2808
+ await writeTextFile(
2809
+ path.join(context.targetDir, "packages/backend/src/db/schema/index.ts"),
2810
+ buildBackendSchemaIndex(context)
2811
+ );
2812
+ await writeTextFile(
2813
+ path.join(context.targetDir, "packages/backend/src/db/schema/items.ts"),
2814
+ buildBackendItemsSchema()
2815
+ );
2816
+ await writeTextFile(
2817
+ path.join(context.targetDir, "packages/backend/src/types/index.ts"),
2818
+ buildBackendTypesIndex(context)
2819
+ );
2820
+ await writeTextFile(
2821
+ path.join(context.targetDir, "packages/backend/src/modules/items/index.ts"),
2822
+ buildBackendItemsIndex()
2823
+ );
2824
+ await writeTextFile(
2825
+ path.join(context.targetDir, "packages/backend/src/modules/items/model.ts"),
2826
+ buildBackendItemsModel()
2827
+ );
2828
+ await writeTextFile(
2829
+ path.join(context.targetDir, "packages/backend/src/modules/items/repository.ts"),
2830
+ buildBackendItemsRepository()
2831
+ );
2832
+ await writeTextFile(
2833
+ path.join(context.targetDir, "packages/backend/src/modules/items/usecases.ts"),
2834
+ buildBackendItemsUsecases()
2835
+ );
2836
+ await writeTextFile(
2837
+ path.join(context.targetDir, "packages/backend/src/modules/items/route.ts"),
2838
+ buildBackendItemsRoute()
2839
+ );
2840
+
2841
+ await writeModuleFiles(context);
2842
+ }
2843
+
2844
+ async function generateSeparated(context: GenerateContext) {
2845
+ await copyDirectory(BASE_ROOT_DIR, context.targetDir, context.tokens);
2846
+ await copyDirectory(
2847
+ BASE_FRONTEND_DIR,
2848
+ path.join(context.targetDir, "packages/frontend"),
2849
+ context.tokens
2850
+ );
2851
+ await copyDirectory(
2852
+ BASE_BACKEND_DIR,
2853
+ path.join(context.targetDir, "packages/backend"),
2854
+ context.tokens
2855
+ );
2856
+
2857
+ await copyModuleSkills(context);
2858
+ await copyModuleOverlays(context);
2859
+ await writeDynamicFiles(context);
2860
+ }
2861
+
2862
+ async function copyModuleSkills(context: GenerateContext) {
2863
+ if (!(await pathExists(SKILLS_DIR))) {
2864
+ throw new Error(
2865
+ "Skills submodule not initialized. Run: git submodule update --init --recursive"
2866
+ );
2867
+ }
2868
+
2869
+ const selectedSkills = resolveSkillsForModules(context.resolvedModules, context.stackModel);
2870
+
2871
+ if (selectedSkills.size === 0) {
2872
+ return;
2873
+ }
2874
+
2875
+ await copySkillsToAgentDirs(context.targetDir, selectedSkills, context);
2876
+ }
2877
+
2878
+ async function copyModuleOverlays(context: GenerateContext) {
2879
+ for (const moduleName of context.resolvedModules) {
2880
+ const overlayDir =
2881
+ MODULE_REGISTRY[moduleName].templateDir ?? path.join(TEMPLATES_DIR, "modules", moduleName);
2882
+
2883
+ if (await pathExists(overlayDir)) {
2884
+ await copyDirectory(
2885
+ overlayDir,
2886
+ await resolveModuleOverlayTargetDir(context.targetDir, overlayDir),
2887
+ context.tokens
2888
+ );
2889
+ }
2890
+ }
2891
+ }
2892
+
2893
+ export async function generate(config: GeneratorConfig): Promise<GenerateResult> {
2894
+ const s = spinner();
2895
+ const resolvedModules = resolveSelectedModules(config.selectedModules);
2896
+ const targetDir = resolveTargetDirectory(config.targetDir);
2897
+ const tokens = buildTemplateTokens(config.projectName);
2898
+ const context: GenerateContext = {
2899
+ projectName: config.projectName,
2900
+ stackModel: config.stackModel,
2901
+ resolvedModules,
2902
+ targetDir,
2903
+ tokens,
2904
+ };
2905
+
2906
+ await assertTargetDirectoryIsReady(targetDir);
2907
+
2908
+ s.start("Scaffolding project...");
2909
+ await ensureDir(targetDir);
2910
+
2911
+ switch (config.stackModel) {
2912
+ case "separated":
2913
+ await generateSeparated(context);
2914
+ break;
2915
+ case "tanstack-start":
2916
+ await generateTanStackStart(context);
2917
+ break;
2918
+ }
2919
+
2920
+ s.stop("Project scaffolded.");
2921
+
2922
+ if (config.installDependencies) {
2923
+ s.start("Installing dependencies...");
2924
+ await runCommand("bun", ["install"], targetDir);
2925
+ s.stop("Dependencies installed.");
2926
+ }
2927
+
2928
+ if (config.initGit) {
2929
+ s.start("Initializing git...");
2930
+ await runCommand("git", ["init"], targetDir);
2931
+ await runCommand("git", ["add", "-A"], targetDir);
2932
+ await runCommand(
2933
+ "git",
2934
+ ["commit", "-m", "chore: initial project scaffold via devstack"],
2935
+ targetDir
2936
+ );
2937
+ s.stop("Git initialized.");
2938
+ }
2939
+
2940
+ return {
2941
+ resolvedModules,
2942
+ targetDir,
2943
+ };
2944
+ }
2945
+
2946
+ export const generateProject = generate;