@voltro/cli 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 (626) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/LICENSE +57 -0
  3. package/README.md +26 -0
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +20236 -0
  6. package/bin/voltro.mjs +43 -0
  7. package/dist/bin.d.ts +1 -0
  8. package/dist/bin.js +9 -0
  9. package/dist/commands-CfPH2Wf4.js +18061 -0
  10. package/dist/frameworkInspectState-CX2250XB.js +86 -0
  11. package/dist/index.d.ts +48 -0
  12. package/dist/index.js +5 -0
  13. package/dist/inspectState.d.ts +116 -0
  14. package/dist/inspectState.js +2 -0
  15. package/dist/startup.d.ts +26 -0
  16. package/dist/startup.js +2 -0
  17. package/dist/startupRunner-CRhuUl91.js +71 -0
  18. package/package.json +88 -0
  19. package/templates/AGENTS.core.md +258 -0
  20. package/templates/AGENTS.md +351 -0
  21. package/templates/agent-docs/_index.md +93 -0
  22. package/templates/agent-docs/_manifest.json +655 -0
  23. package/templates/agent-docs/ai.md +1845 -0
  24. package/templates/agent-docs/authentication.md +1788 -0
  25. package/templates/agent-docs/caching.md +624 -0
  26. package/templates/agent-docs/cli.md +1650 -0
  27. package/templates/agent-docs/configuration.md +295 -0
  28. package/templates/agent-docs/data.md +2172 -0
  29. package/templates/agent-docs/database/advancedqueries.md +1583 -0
  30. package/templates/agent-docs/database/columntypes.md +1200 -0
  31. package/templates/agent-docs/database/hosting.md +881 -0
  32. package/templates/agent-docs/database/migrations.md +2938 -0
  33. package/templates/agent-docs/database/misc.md +270 -0
  34. package/templates/agent-docs/database/overview.md +108 -0
  35. package/templates/agent-docs/database/querying.md +1622 -0
  36. package/templates/agent-docs/database/scaling.md +331 -0
  37. package/templates/agent-docs/database/schema.md +1458 -0
  38. package/templates/agent-docs/database/seedsdialects.md +1235 -0
  39. package/templates/agent-docs/database/transactions.md +285 -0
  40. package/templates/agent-docs/deployment.md +999 -0
  41. package/templates/agent-docs/internationalization.md +359 -0
  42. package/templates/agent-docs/introduction.md +438 -0
  43. package/templates/agent-docs/multi-tenancy.md +610 -0
  44. package/templates/agent-docs/observability.md +350 -0
  45. package/templates/agent-docs/plugins.md +1273 -0
  46. package/templates/agent-docs/reference.md +978 -0
  47. package/templates/agent-docs/routing.md +1553 -0
  48. package/templates/agent-docs/scheduling.md +666 -0
  49. package/templates/agent-docs/schema-driven-ui.md +607 -0
  50. package/templates/agent-docs/security.md +42 -0
  51. package/templates/agent-docs/templates/apibackends.md +3214 -0
  52. package/templates/agent-docs/templates/appshells.md +2062 -0
  53. package/templates/agent-docs/templates/custom.md +128 -0
  54. package/templates/agent-docs/templates/overview.md +122 -0
  55. package/templates/agent-docs/templates/serverless.md +315 -0
  56. package/templates/agent-docs/testing.md +376 -0
  57. package/templates/agent-docs/workflows.md +1351 -0
  58. package/templates/apps/api-ai/README.md +105 -0
  59. package/templates/apps/api-ai/actions/summarize.action.server.tsx +32 -0
  60. package/templates/apps/api-ai/actions/summarize.action.ts +33 -0
  61. package/templates/apps/api-ai/agents/support.agent.server.tsx +31 -0
  62. package/templates/apps/api-ai/agents/support.agent.tsx +27 -0
  63. package/templates/apps/api-ai/app.config.ts +57 -0
  64. package/templates/apps/api-ai/database/schema.ts +67 -0
  65. package/templates/apps/api-ai/package.json +27 -0
  66. package/templates/apps/api-ai/seeds/docs.seed.ts +67 -0
  67. package/templates/apps/api-ai/template.json +6 -0
  68. package/templates/apps/api-ai/tests/summarize.test.ts +50 -0
  69. package/templates/apps/api-ai/tools/searchDocs.tool.tsx +60 -0
  70. package/templates/apps/api-ai/tsconfig.json +5 -0
  71. package/templates/apps/api-auth/.env +17 -0
  72. package/templates/apps/api-auth/README.md +109 -0
  73. package/templates/apps/api-auth/actions/me.action.server.ts +20 -0
  74. package/templates/apps/api-auth/actions/me.action.ts +19 -0
  75. package/templates/apps/api-auth/app.config.ts +59 -0
  76. package/templates/apps/api-auth/database/schema.ts +26 -0
  77. package/templates/apps/api-auth/package.json +28 -0
  78. package/templates/apps/api-auth/template.json +6 -0
  79. package/templates/apps/api-auth/tests/me.test.ts +37 -0
  80. package/templates/apps/api-auth/tsconfig.json +5 -0
  81. package/templates/apps/api-backend/README.md +25 -0
  82. package/templates/apps/api-backend/app.config.ts +39 -0
  83. package/templates/apps/api-backend/database/schema.ts +57 -0
  84. package/templates/apps/api-backend/mutations/notes.create.mutation.server.ts +19 -0
  85. package/templates/apps/api-backend/mutations/notes.create.mutation.ts +37 -0
  86. package/templates/apps/api-backend/package.json +28 -0
  87. package/templates/apps/api-backend/queries/notes.query.server.ts +14 -0
  88. package/templates/apps/api-backend/queries/notes.query.ts +20 -0
  89. package/templates/apps/api-backend/template.json +6 -0
  90. package/templates/apps/api-backend/tests/notes.create.test.ts +50 -0
  91. package/templates/apps/api-backend/tsconfig.json +5 -0
  92. package/templates/apps/api-backend-deactivation/README.md +49 -0
  93. package/templates/apps/api-backend-deactivation/actions/users.get.action.server.ts +17 -0
  94. package/templates/apps/api-backend-deactivation/actions/users.get.action.ts +18 -0
  95. package/templates/apps/api-backend-deactivation/app.config.ts +20 -0
  96. package/templates/apps/api-backend-deactivation/database/schema.ts +41 -0
  97. package/templates/apps/api-backend-deactivation/mutations/users.create.mutation.server.ts +6 -0
  98. package/templates/apps/api-backend-deactivation/mutations/users.create.mutation.ts +16 -0
  99. package/templates/apps/api-backend-deactivation/mutations/users.deactivate.mutation.server.ts +10 -0
  100. package/templates/apps/api-backend-deactivation/mutations/users.deactivate.mutation.ts +19 -0
  101. package/templates/apps/api-backend-deactivation/package.json +28 -0
  102. package/templates/apps/api-backend-deactivation/template.json +6 -0
  103. package/templates/apps/api-backend-deactivation/tests/users.deactivate.test.ts +47 -0
  104. package/templates/apps/api-backend-deactivation/tsconfig.json +5 -0
  105. package/templates/apps/api-backend-mail/README.md +39 -0
  106. package/templates/apps/api-backend-mail/actions/sendWelcome.action.server.ts +15 -0
  107. package/templates/apps/api-backend-mail/actions/sendWelcome.action.ts +21 -0
  108. package/templates/apps/api-backend-mail/app.config.ts +34 -0
  109. package/templates/apps/api-backend-mail/database/schema.ts +57 -0
  110. package/templates/apps/api-backend-mail/emails/welcome.email.tsx +106 -0
  111. package/templates/apps/api-backend-mail/mutations/notes.create.mutation.server.ts +19 -0
  112. package/templates/apps/api-backend-mail/mutations/notes.create.mutation.ts +37 -0
  113. package/templates/apps/api-backend-mail/package.json +30 -0
  114. package/templates/apps/api-backend-mail/queries/notes.query.server.ts +14 -0
  115. package/templates/apps/api-backend-mail/queries/notes.query.ts +20 -0
  116. package/templates/apps/api-backend-mail/template.json +6 -0
  117. package/templates/apps/api-backend-mail/tests/notes.create.test.ts +50 -0
  118. package/templates/apps/api-backend-mail/tsconfig.json +5 -0
  119. package/templates/apps/api-backend-mariadb/.env.example +35 -0
  120. package/templates/apps/api-backend-mariadb/README.md +31 -0
  121. package/templates/apps/api-backend-mariadb/app.config.ts +68 -0
  122. package/templates/apps/api-backend-mariadb/database/schema.ts +57 -0
  123. package/templates/apps/api-backend-mariadb/mutations/notes.create.mutation.server.ts +19 -0
  124. package/templates/apps/api-backend-mariadb/mutations/notes.create.mutation.ts +37 -0
  125. package/templates/apps/api-backend-mariadb/package.json +30 -0
  126. package/templates/apps/api-backend-mariadb/queries/notes.query.server.ts +14 -0
  127. package/templates/apps/api-backend-mariadb/queries/notes.query.ts +20 -0
  128. package/templates/apps/api-backend-mariadb/template.json +6 -0
  129. package/templates/apps/api-backend-mariadb/tests/notes.create.test.ts +50 -0
  130. package/templates/apps/api-backend-mariadb/tsconfig.json +5 -0
  131. package/templates/apps/api-backend-storage/README.md +86 -0
  132. package/templates/apps/api-backend-storage/actions/uploadAvatar.action.server.ts +21 -0
  133. package/templates/apps/api-backend-storage/actions/uploadAvatar.action.ts +21 -0
  134. package/templates/apps/api-backend-storage/actions/uploadDocument.action.server.ts +21 -0
  135. package/templates/apps/api-backend-storage/actions/uploadDocument.action.ts +20 -0
  136. package/templates/apps/api-backend-storage/app.config.ts +38 -0
  137. package/templates/apps/api-backend-storage/database/schema.ts +57 -0
  138. package/templates/apps/api-backend-storage/mutations/notes.create.mutation.server.ts +19 -0
  139. package/templates/apps/api-backend-storage/mutations/notes.create.mutation.ts +37 -0
  140. package/templates/apps/api-backend-storage/package.json +27 -0
  141. package/templates/apps/api-backend-storage/queries/notes.query.server.ts +14 -0
  142. package/templates/apps/api-backend-storage/queries/notes.query.ts +20 -0
  143. package/templates/apps/api-backend-storage/template.json +6 -0
  144. package/templates/apps/api-backend-storage/tests/notes.create.test.ts +50 -0
  145. package/templates/apps/api-backend-storage/tsconfig.json +5 -0
  146. package/templates/apps/api-data-advanced/.env +17 -0
  147. package/templates/apps/api-data-advanced/README.md +88 -0
  148. package/templates/apps/api-data-advanced/app.config.ts +56 -0
  149. package/templates/apps/api-data-advanced/database/actors.entity.ts +14 -0
  150. package/templates/apps/api-data-advanced/database/authors.entity.ts +30 -0
  151. package/templates/apps/api-data-advanced/database/authors.relations.ts +15 -0
  152. package/templates/apps/api-data-advanced/database/books.entity.ts +59 -0
  153. package/templates/apps/api-data-advanced/database/books.relations.ts +10 -0
  154. package/templates/apps/api-data-advanced/database/index.ts +23 -0
  155. package/templates/apps/api-data-advanced/database/tenants.entity.ts +11 -0
  156. package/templates/apps/api-data-advanced/package.json +28 -0
  157. package/templates/apps/api-data-advanced/queries/authors.withBooks.query.server.ts +18 -0
  158. package/templates/apps/api-data-advanced/queries/authors.withBooks.query.ts +40 -0
  159. package/templates/apps/api-data-advanced/queries/books.search.query.server.ts +17 -0
  160. package/templates/apps/api-data-advanced/queries/books.search.query.ts +39 -0
  161. package/templates/apps/api-data-advanced/seeds/catalog.seed.ts +101 -0
  162. package/templates/apps/api-data-advanced/template.json +6 -0
  163. package/templates/apps/api-data-advanced/tests/queries.test.ts +124 -0
  164. package/templates/apps/api-data-advanced/tsconfig.json +5 -0
  165. package/templates/apps/api-durable/README.md +81 -0
  166. package/templates/apps/api-durable/aggregates/orderStats.aggregate.ts +49 -0
  167. package/templates/apps/api-durable/app.config.ts +41 -0
  168. package/templates/apps/api-durable/database/schema.ts +65 -0
  169. package/templates/apps/api-durable/mutations/orders.approve.mutation.server.ts +43 -0
  170. package/templates/apps/api-durable/mutations/orders.approve.mutation.ts +23 -0
  171. package/templates/apps/api-durable/mutations/orders.place.mutation.server.ts +45 -0
  172. package/templates/apps/api-durable/mutations/orders.place.mutation.ts +40 -0
  173. package/templates/apps/api-durable/package.json +28 -0
  174. package/templates/apps/api-durable/schedules/nightlyReport.cron.tsx +37 -0
  175. package/templates/apps/api-durable/startup/warm.startup.tsx +33 -0
  176. package/templates/apps/api-durable/subscribers/orderChanges.subscribe.ts +27 -0
  177. package/templates/apps/api-durable/template.json +6 -0
  178. package/templates/apps/api-durable/tests/orders.place.test.ts +91 -0
  179. package/templates/apps/api-durable/triggers/order.placed.trigger.tsx +21 -0
  180. package/templates/apps/api-durable/tsconfig.json +5 -0
  181. package/templates/apps/api-durable/workflows/order.fulfill.workflow.server.tsx +103 -0
  182. package/templates/apps/api-durable/workflows/order.fulfill.workflow.tsx +25 -0
  183. package/templates/apps/api-feature-flags/README.md +63 -0
  184. package/templates/apps/api-feature-flags/actions/notes.export.action.server.ts +11 -0
  185. package/templates/apps/api-feature-flags/actions/notes.export.action.ts +18 -0
  186. package/templates/apps/api-feature-flags/app.config.ts +41 -0
  187. package/templates/apps/api-feature-flags/database/schema.ts +37 -0
  188. package/templates/apps/api-feature-flags/mutations/notes.create.mutation.server.ts +29 -0
  189. package/templates/apps/api-feature-flags/mutations/notes.create.mutation.ts +28 -0
  190. package/templates/apps/api-feature-flags/package.json +29 -0
  191. package/templates/apps/api-feature-flags/template.json +6 -0
  192. package/templates/apps/api-feature-flags/tests/notes.create.test.ts +67 -0
  193. package/templates/apps/api-feature-flags/tsconfig.json +5 -0
  194. package/templates/apps/api-governance/.env +4 -0
  195. package/templates/apps/api-governance/README.md +61 -0
  196. package/templates/apps/api-governance/actions/profiles.get.action.server.ts +17 -0
  197. package/templates/apps/api-governance/actions/profiles.get.action.ts +17 -0
  198. package/templates/apps/api-governance/app.config.ts +35 -0
  199. package/templates/apps/api-governance/database/schema.ts +41 -0
  200. package/templates/apps/api-governance/mutations/profiles.create.mutation.server.ts +17 -0
  201. package/templates/apps/api-governance/mutations/profiles.create.mutation.ts +21 -0
  202. package/templates/apps/api-governance/package.json +29 -0
  203. package/templates/apps/api-governance/template.json +6 -0
  204. package/templates/apps/api-governance/tests/profiles.create.test.ts +59 -0
  205. package/templates/apps/api-governance/tsconfig.json +5 -0
  206. package/templates/apps/api-kv/README.md +100 -0
  207. package/templates/apps/api-kv/actions/sync.pull.action.server.ts +75 -0
  208. package/templates/apps/api-kv/actions/sync.pull.action.ts +25 -0
  209. package/templates/apps/api-kv/actions/sync.reset.action.server.ts +25 -0
  210. package/templates/apps/api-kv/actions/sync.reset.action.ts +22 -0
  211. package/templates/apps/api-kv/actions/sync.status.action.server.ts +28 -0
  212. package/templates/apps/api-kv/actions/sync.status.action.ts +17 -0
  213. package/templates/apps/api-kv/app.config.ts +48 -0
  214. package/templates/apps/api-kv/database/schema.ts +62 -0
  215. package/templates/apps/api-kv/package.json +28 -0
  216. package/templates/apps/api-kv/queries/events.list.query.server.ts +14 -0
  217. package/templates/apps/api-kv/queries/events.list.query.ts +23 -0
  218. package/templates/apps/api-kv/template.json +6 -0
  219. package/templates/apps/api-kv/tests/sync.test.ts +103 -0
  220. package/templates/apps/api-kv/tsconfig.json +5 -0
  221. package/templates/apps/api-moderation/README.md +46 -0
  222. package/templates/apps/api-moderation/app.config.ts +33 -0
  223. package/templates/apps/api-moderation/database/schema.ts +45 -0
  224. package/templates/apps/api-moderation/mutations/comments.create.mutation.server.ts +8 -0
  225. package/templates/apps/api-moderation/mutations/comments.create.mutation.ts +20 -0
  226. package/templates/apps/api-moderation/mutations/posts.create.mutation.server.ts +9 -0
  227. package/templates/apps/api-moderation/mutations/posts.create.mutation.ts +25 -0
  228. package/templates/apps/api-moderation/package.json +29 -0
  229. package/templates/apps/api-moderation/template.json +6 -0
  230. package/templates/apps/api-moderation/tests/posts.create.test.ts +79 -0
  231. package/templates/apps/api-moderation/tsconfig.json +5 -0
  232. package/templates/apps/api-observability/README.md +106 -0
  233. package/templates/apps/api-observability/app.config.ts +32 -0
  234. package/templates/apps/api-observability/database/schema.ts +38 -0
  235. package/templates/apps/api-observability/mutations/notes.create.mutation.server.ts +33 -0
  236. package/templates/apps/api-observability/mutations/notes.create.mutation.ts +15 -0
  237. package/templates/apps/api-observability/package.json +29 -0
  238. package/templates/apps/api-observability/queries/notes.list.query.server.ts +7 -0
  239. package/templates/apps/api-observability/queries/notes.list.query.ts +14 -0
  240. package/templates/apps/api-observability/template.json +6 -0
  241. package/templates/apps/api-observability/tests/notes.create.test.ts +36 -0
  242. package/templates/apps/api-observability/tsconfig.json +5 -0
  243. package/templates/apps/api-ratelimit/README.md +49 -0
  244. package/templates/apps/api-ratelimit/app.config.ts +42 -0
  245. package/templates/apps/api-ratelimit/database/schema.ts +37 -0
  246. package/templates/apps/api-ratelimit/mutations/notes.create.mutation.server.ts +16 -0
  247. package/templates/apps/api-ratelimit/mutations/notes.create.mutation.ts +34 -0
  248. package/templates/apps/api-ratelimit/package.json +29 -0
  249. package/templates/apps/api-ratelimit/template.json +6 -0
  250. package/templates/apps/api-ratelimit/tests/notes.create.test.ts +69 -0
  251. package/templates/apps/api-ratelimit/tsconfig.json +5 -0
  252. package/templates/apps/api-rbac/README.md +59 -0
  253. package/templates/apps/api-rbac/app.config.ts +48 -0
  254. package/templates/apps/api-rbac/database/schema.ts +37 -0
  255. package/templates/apps/api-rbac/mutations/notes.create.mutation.server.ts +22 -0
  256. package/templates/apps/api-rbac/mutations/notes.create.mutation.ts +26 -0
  257. package/templates/apps/api-rbac/package.json +29 -0
  258. package/templates/apps/api-rbac/template.json +6 -0
  259. package/templates/apps/api-rbac/tests/notes.create.test.ts +80 -0
  260. package/templates/apps/api-rbac/tsconfig.json +5 -0
  261. package/templates/apps/api-rest/README.md +85 -0
  262. package/templates/apps/api-rest/app.config.ts +70 -0
  263. package/templates/apps/api-rest/database/schema.ts +52 -0
  264. package/templates/apps/api-rest/lib/product.ts +30 -0
  265. package/templates/apps/api-rest/package.json +27 -0
  266. package/templates/apps/api-rest/routes/v1/products.create.route.tsx +45 -0
  267. package/templates/apps/api-rest/routes/v1/products.delete.route.tsx +25 -0
  268. package/templates/apps/api-rest/routes/v1/products.get.route.tsx +29 -0
  269. package/templates/apps/api-rest/routes/v1/products.list.route.tsx +43 -0
  270. package/templates/apps/api-rest/template.json +6 -0
  271. package/templates/apps/api-rest/tests/products.create.test.ts +53 -0
  272. package/templates/apps/api-rest/tsconfig.json +5 -0
  273. package/templates/apps/api-saas/README.md +106 -0
  274. package/templates/apps/api-saas/app.config.ts +51 -0
  275. package/templates/apps/api-saas/database/schema.ts +50 -0
  276. package/templates/apps/api-saas/mutations/projects.create.mutation.server.ts +52 -0
  277. package/templates/apps/api-saas/mutations/projects.create.mutation.ts +18 -0
  278. package/templates/apps/api-saas/package.json +31 -0
  279. package/templates/apps/api-saas/queries/projects.list.query.server.ts +7 -0
  280. package/templates/apps/api-saas/queries/projects.list.query.ts +18 -0
  281. package/templates/apps/api-saas/template.json +6 -0
  282. package/templates/apps/api-saas/tests/projects.create.test.ts +47 -0
  283. package/templates/apps/api-saas/tsconfig.json +5 -0
  284. package/templates/apps/api-search/README.md +68 -0
  285. package/templates/apps/api-search/app.config.ts +31 -0
  286. package/templates/apps/api-search/database/schema.ts +47 -0
  287. package/templates/apps/api-search/lib/search.ts +27 -0
  288. package/templates/apps/api-search/mutations/articles.create.mutation.server.ts +19 -0
  289. package/templates/apps/api-search/mutations/articles.create.mutation.ts +35 -0
  290. package/templates/apps/api-search/package.json +29 -0
  291. package/templates/apps/api-search/queries/articles.list.query.server.ts +14 -0
  292. package/templates/apps/api-search/queries/articles.list.query.ts +19 -0
  293. package/templates/apps/api-search/seeds/articles.seed.ts +41 -0
  294. package/templates/apps/api-search/startup/searchBackfill.startup.tsx +24 -0
  295. package/templates/apps/api-search/template.json +6 -0
  296. package/templates/apps/api-search/tests/articles.create.test.ts +69 -0
  297. package/templates/apps/api-search/tsconfig.json +5 -0
  298. package/templates/apps/api-versioning/README.md +51 -0
  299. package/templates/apps/api-versioning/actions/documents.asOf.action.server.ts +13 -0
  300. package/templates/apps/api-versioning/actions/documents.asOf.action.ts +14 -0
  301. package/templates/apps/api-versioning/actions/documents.history.action.server.ts +15 -0
  302. package/templates/apps/api-versioning/actions/documents.history.action.ts +17 -0
  303. package/templates/apps/api-versioning/app.config.ts +24 -0
  304. package/templates/apps/api-versioning/database/schema.ts +38 -0
  305. package/templates/apps/api-versioning/mutations/documents.create.mutation.server.ts +8 -0
  306. package/templates/apps/api-versioning/mutations/documents.create.mutation.ts +21 -0
  307. package/templates/apps/api-versioning/mutations/documents.update.mutation.server.ts +9 -0
  308. package/templates/apps/api-versioning/mutations/documents.update.mutation.ts +21 -0
  309. package/templates/apps/api-versioning/package.json +29 -0
  310. package/templates/apps/api-versioning/template.json +6 -0
  311. package/templates/apps/api-versioning/tests/documents.create.test.ts +37 -0
  312. package/templates/apps/api-versioning/tsconfig.json +5 -0
  313. package/templates/apps/api-webhooks/.env +6 -0
  314. package/templates/apps/api-webhooks/README.md +106 -0
  315. package/templates/apps/api-webhooks/app.config.ts +16 -0
  316. package/templates/apps/api-webhooks/database/schema.ts +49 -0
  317. package/templates/apps/api-webhooks/events/order.completed.webhook.tsx +22 -0
  318. package/templates/apps/api-webhooks/mutations/orders.fulfill.mutation.server.ts +37 -0
  319. package/templates/apps/api-webhooks/mutations/orders.fulfill.mutation.ts +15 -0
  320. package/templates/apps/api-webhooks/package.json +28 -0
  321. package/templates/apps/api-webhooks/queries/orders.list.query.server.ts +7 -0
  322. package/templates/apps/api-webhooks/queries/orders.list.query.ts +15 -0
  323. package/templates/apps/api-webhooks/template.json +6 -0
  324. package/templates/apps/api-webhooks/tests/orders.fulfill.test.ts +51 -0
  325. package/templates/apps/api-webhooks/tsconfig.json +5 -0
  326. package/templates/apps/api-webhooks/webhooks/orders.webhook.tsx +35 -0
  327. package/templates/apps/changelog/README.md +77 -0
  328. package/templates/apps/changelog/app.config.ts +27 -0
  329. package/templates/apps/changelog/content/releases/0.1.0.mdx +19 -0
  330. package/templates/apps/changelog/content/releases/0.2.0.mdx +28 -0
  331. package/templates/apps/changelog/package.json +30 -0
  332. package/templates/apps/changelog/scripts/generate-rss.mjs +38 -0
  333. package/templates/apps/changelog/src/globals.css +66 -0
  334. package/templates/apps/changelog/src/globals.d.ts +16 -0
  335. package/templates/apps/changelog/src/lib/locale.test.ts +72 -0
  336. package/templates/apps/changelog/src/lib/locale.ts +55 -0
  337. package/templates/apps/changelog/src/lib/releases.ts +21 -0
  338. package/templates/apps/changelog/src/locales/de.ts +22 -0
  339. package/templates/apps/changelog/src/locales/en.ts +30 -0
  340. package/templates/apps/changelog/src/pages/[locale]/[slug].tsx +24 -0
  341. package/templates/apps/changelog/src/pages/[locale]/index.tsx +13 -0
  342. package/templates/apps/changelog/src/pages/[locale]/mirrors.test.tsx +95 -0
  343. package/templates/apps/changelog/src/pages/[slug].test.tsx +127 -0
  344. package/templates/apps/changelog/src/pages/[slug].tsx +52 -0
  345. package/templates/apps/changelog/src/pages/index.test.tsx +112 -0
  346. package/templates/apps/changelog/src/pages/index.tsx +55 -0
  347. package/templates/apps/changelog/src/pages/layout.tsx +84 -0
  348. package/templates/apps/changelog/template.json +6 -0
  349. package/templates/apps/changelog/tsconfig.json +11 -0
  350. package/templates/apps/edge-functions/README.md +55 -0
  351. package/templates/apps/edge-functions/functions/aiComplete.serverless.ts +58 -0
  352. package/templates/apps/edge-functions/functions/currencyConvert.serverless.ts +47 -0
  353. package/templates/apps/edge-functions/functions/geoGreeting.serverless.ts +44 -0
  354. package/templates/apps/edge-functions/functions/health.serverless.ts +29 -0
  355. package/templates/apps/edge-functions/functions/resolveLink.serverless.ts +32 -0
  356. package/templates/apps/edge-functions/functions/shareLink.serverless.ts +30 -0
  357. package/templates/apps/edge-functions/functions/slackNotify.serverless.ts +40 -0
  358. package/templates/apps/edge-functions/functions/verifySignature.serverless.ts +52 -0
  359. package/templates/apps/edge-functions/package.json +21 -0
  360. package/templates/apps/edge-functions/template.json +6 -0
  361. package/templates/apps/edge-functions/tsconfig.json +10 -0
  362. package/templates/apps/frontend-admin/README.md +40 -0
  363. package/templates/apps/frontend-admin/app.config.ts +37 -0
  364. package/templates/apps/frontend-admin/package.json +30 -0
  365. package/templates/apps/frontend-admin/src/config.ts +8 -0
  366. package/templates/apps/frontend-admin/src/globals.css +76 -0
  367. package/templates/apps/frontend-admin/src/globals.d.ts +6 -0
  368. package/templates/apps/frontend-admin/src/lib/admin.ts +16 -0
  369. package/templates/apps/frontend-admin/src/lib/auth.ts +24 -0
  370. package/templates/apps/frontend-admin/src/locales/de.ts +67 -0
  371. package/templates/apps/frontend-admin/src/locales/en.ts +79 -0
  372. package/templates/apps/frontend-admin/src/locales/index.ts +15 -0
  373. package/templates/apps/frontend-admin/src/pages/(marketing)/index.test.tsx +55 -0
  374. package/templates/apps/frontend-admin/src/pages/(marketing)/index.tsx +32 -0
  375. package/templates/apps/frontend-admin/src/pages/(marketing)/layout.tsx +29 -0
  376. package/templates/apps/frontend-admin/src/pages/(marketing)/login.test.tsx +73 -0
  377. package/templates/apps/frontend-admin/src/pages/(marketing)/login.tsx +35 -0
  378. package/templates/apps/frontend-admin/src/pages/admin/[entity].tsx +121 -0
  379. package/templates/apps/frontend-admin/src/pages/admin/entity.test.tsx +119 -0
  380. package/templates/apps/frontend-admin/src/pages/admin/error.tsx +20 -0
  381. package/templates/apps/frontend-admin/src/pages/admin/fallbacks.test.tsx +68 -0
  382. package/templates/apps/frontend-admin/src/pages/admin/index.test.tsx +88 -0
  383. package/templates/apps/frontend-admin/src/pages/admin/index.tsx +65 -0
  384. package/templates/apps/frontend-admin/src/pages/admin/layout.test.tsx +114 -0
  385. package/templates/apps/frontend-admin/src/pages/admin/layout.tsx +97 -0
  386. package/templates/apps/frontend-admin/src/pages/admin/loading.tsx +15 -0
  387. package/templates/apps/frontend-admin/src/pages/admin/not-found.tsx +15 -0
  388. package/templates/apps/frontend-admin/src/pages/layout.tsx +12 -0
  389. package/templates/apps/frontend-admin/src/pages/layouts.test.tsx +54 -0
  390. package/templates/apps/frontend-admin/template.json +6 -0
  391. package/templates/apps/frontend-admin/tsconfig.json +11 -0
  392. package/templates/apps/frontend-app/README.md +98 -0
  393. package/templates/apps/frontend-app/app.config.ts +43 -0
  394. package/templates/apps/frontend-app/package.json +30 -0
  395. package/templates/apps/frontend-app/src/locales/de.ts +36 -0
  396. package/templates/apps/frontend-app/src/locales/en.ts +43 -0
  397. package/templates/apps/frontend-app/src/locales/index.ts +15 -0
  398. package/templates/apps/frontend-app/src/pages/index.test.tsx +167 -0
  399. package/templates/apps/frontend-app/src/pages/index.tsx +136 -0
  400. package/templates/apps/frontend-app/src/pages/layout.tsx +41 -0
  401. package/templates/apps/frontend-app/src/pages/schema-ui.test.tsx +99 -0
  402. package/templates/apps/frontend-app/src/pages/schema-ui.tsx +74 -0
  403. package/templates/apps/frontend-app/template.json +6 -0
  404. package/templates/apps/frontend-app/tsconfig.json +11 -0
  405. package/templates/apps/frontend-blank/README.md +18 -0
  406. package/templates/apps/frontend-blank/app.config.ts +29 -0
  407. package/templates/apps/frontend-blank/package.json +29 -0
  408. package/templates/apps/frontend-blank/src/locales/de.ts +15 -0
  409. package/templates/apps/frontend-blank/src/locales/en.ts +22 -0
  410. package/templates/apps/frontend-blank/src/locales/index.ts +15 -0
  411. package/templates/apps/frontend-blank/src/pages/index.test.tsx +55 -0
  412. package/templates/apps/frontend-blank/src/pages/index.tsx +27 -0
  413. package/templates/apps/frontend-blank/src/pages/layout.test.tsx +54 -0
  414. package/templates/apps/frontend-blank/src/pages/layout.tsx +35 -0
  415. package/templates/apps/frontend-blank/template.json +6 -0
  416. package/templates/apps/frontend-blank/tsconfig.json +11 -0
  417. package/templates/apps/frontend-contact/README.md +65 -0
  418. package/templates/apps/frontend-contact/app.config.ts +25 -0
  419. package/templates/apps/frontend-contact/functions/sendMessage.serverless.ts +69 -0
  420. package/templates/apps/frontend-contact/package.json +33 -0
  421. package/templates/apps/frontend-contact/src/components/ContactForm.island.test.tsx +142 -0
  422. package/templates/apps/frontend-contact/src/components/ContactForm.island.tsx +104 -0
  423. package/templates/apps/frontend-contact/src/config.ts +12 -0
  424. package/templates/apps/frontend-contact/src/globals.css +84 -0
  425. package/templates/apps/frontend-contact/src/lib/locale.ts +55 -0
  426. package/templates/apps/frontend-contact/src/locales/de.ts +26 -0
  427. package/templates/apps/frontend-contact/src/locales/en.ts +29 -0
  428. package/templates/apps/frontend-contact/src/pages/[locale]/index.tsx +14 -0
  429. package/templates/apps/frontend-contact/src/pages/index.test.tsx +70 -0
  430. package/templates/apps/frontend-contact/src/pages/index.tsx +63 -0
  431. package/templates/apps/frontend-contact/src/pages/layout.tsx +65 -0
  432. package/templates/apps/frontend-contact/template.json +6 -0
  433. package/templates/apps/frontend-contact/tsconfig.json +11 -0
  434. package/templates/apps/frontend-dashboard/README.md +54 -0
  435. package/templates/apps/frontend-dashboard/app.config.ts +39 -0
  436. package/templates/apps/frontend-dashboard/package.json +29 -0
  437. package/templates/apps/frontend-dashboard/src/config.ts +8 -0
  438. package/templates/apps/frontend-dashboard/src/globals.css +72 -0
  439. package/templates/apps/frontend-dashboard/src/globals.d.ts +6 -0
  440. package/templates/apps/frontend-dashboard/src/lib/auth.ts +27 -0
  441. package/templates/apps/frontend-dashboard/src/locales/de.ts +49 -0
  442. package/templates/apps/frontend-dashboard/src/locales/en.ts +60 -0
  443. package/templates/apps/frontend-dashboard/src/locales/index.ts +15 -0
  444. package/templates/apps/frontend-dashboard/src/pages/(marketing)/index.test.tsx +55 -0
  445. package/templates/apps/frontend-dashboard/src/pages/(marketing)/index.tsx +34 -0
  446. package/templates/apps/frontend-dashboard/src/pages/(marketing)/layout.tsx +32 -0
  447. package/templates/apps/frontend-dashboard/src/pages/(marketing)/login.test.tsx +74 -0
  448. package/templates/apps/frontend-dashboard/src/pages/(marketing)/login.tsx +40 -0
  449. package/templates/apps/frontend-dashboard/src/pages/dashboard/error.tsx +21 -0
  450. package/templates/apps/frontend-dashboard/src/pages/dashboard/fallbacks.test.tsx +68 -0
  451. package/templates/apps/frontend-dashboard/src/pages/dashboard/index.test.tsx +55 -0
  452. package/templates/apps/frontend-dashboard/src/pages/dashboard/index.tsx +38 -0
  453. package/templates/apps/frontend-dashboard/src/pages/dashboard/layout.test.tsx +88 -0
  454. package/templates/apps/frontend-dashboard/src/pages/dashboard/layout.tsx +69 -0
  455. package/templates/apps/frontend-dashboard/src/pages/dashboard/loading.tsx +21 -0
  456. package/templates/apps/frontend-dashboard/src/pages/dashboard/not-found.tsx +19 -0
  457. package/templates/apps/frontend-dashboard/src/pages/dashboard/settings.test.tsx +69 -0
  458. package/templates/apps/frontend-dashboard/src/pages/dashboard/settings.tsx +35 -0
  459. package/templates/apps/frontend-dashboard/src/pages/layout.tsx +12 -0
  460. package/templates/apps/frontend-dashboard/src/pages/layouts.test.tsx +54 -0
  461. package/templates/apps/frontend-dashboard/template.json +6 -0
  462. package/templates/apps/frontend-dashboard/tsconfig.json +11 -0
  463. package/templates/apps/frontend-docs/README.md +19 -0
  464. package/templates/apps/frontend-docs/app.config.ts +25 -0
  465. package/templates/apps/frontend-docs/package.json +29 -0
  466. package/templates/apps/frontend-docs/src/globals.css +32 -0
  467. package/templates/apps/frontend-docs/src/lib/locale.test.ts +72 -0
  468. package/templates/apps/frontend-docs/src/lib/locale.ts +56 -0
  469. package/templates/apps/frontend-docs/src/locales/de.ts +24 -0
  470. package/templates/apps/frontend-docs/src/locales/en.ts +28 -0
  471. package/templates/apps/frontend-docs/src/pages/[locale]/docs/[...slug].tsx +18 -0
  472. package/templates/apps/frontend-docs/src/pages/[locale]/index.tsx +13 -0
  473. package/templates/apps/frontend-docs/src/pages/[locale]/mirrors.test.tsx +67 -0
  474. package/templates/apps/frontend-docs/src/pages/docs/[...slug].test.tsx +115 -0
  475. package/templates/apps/frontend-docs/src/pages/docs/[...slug].tsx +82 -0
  476. package/templates/apps/frontend-docs/src/pages/index.test.tsx +90 -0
  477. package/templates/apps/frontend-docs/src/pages/index.tsx +45 -0
  478. package/templates/apps/frontend-docs/src/pages/layout.test.tsx +84 -0
  479. package/templates/apps/frontend-docs/src/pages/layout.tsx +66 -0
  480. package/templates/apps/frontend-docs/template.json +6 -0
  481. package/templates/apps/frontend-docs/tsconfig.json +11 -0
  482. package/templates/apps/frontend-i18n/README.md +61 -0
  483. package/templates/apps/frontend-i18n/app.config.ts +33 -0
  484. package/templates/apps/frontend-i18n/package.json +28 -0
  485. package/templates/apps/frontend-i18n/src/globals.css +46 -0
  486. package/templates/apps/frontend-i18n/src/globals.d.ts +6 -0
  487. package/templates/apps/frontend-i18n/src/lib/locale.test.ts +72 -0
  488. package/templates/apps/frontend-i18n/src/lib/locale.ts +55 -0
  489. package/templates/apps/frontend-i18n/src/locales/de.ts +24 -0
  490. package/templates/apps/frontend-i18n/src/locales/en.ts +25 -0
  491. package/templates/apps/frontend-i18n/src/pages/[locale]/about.tsx +11 -0
  492. package/templates/apps/frontend-i18n/src/pages/[locale]/index.tsx +13 -0
  493. package/templates/apps/frontend-i18n/src/pages/[locale]/mirrors.test.tsx +50 -0
  494. package/templates/apps/frontend-i18n/src/pages/about.test.tsx +75 -0
  495. package/templates/apps/frontend-i18n/src/pages/about.tsx +31 -0
  496. package/templates/apps/frontend-i18n/src/pages/index.test.tsx +102 -0
  497. package/templates/apps/frontend-i18n/src/pages/index.tsx +43 -0
  498. package/templates/apps/frontend-i18n/src/pages/layout.test.tsx +86 -0
  499. package/templates/apps/frontend-i18n/src/pages/layout.tsx +70 -0
  500. package/templates/apps/frontend-i18n/template.json +6 -0
  501. package/templates/apps/frontend-i18n/tsconfig.json +11 -0
  502. package/templates/apps/frontend-landing/README.md +17 -0
  503. package/templates/apps/frontend-landing/app.config.ts +25 -0
  504. package/templates/apps/frontend-landing/package.json +29 -0
  505. package/templates/apps/frontend-landing/src/globals.css +23 -0
  506. package/templates/apps/frontend-landing/src/lib/locale.test.ts +72 -0
  507. package/templates/apps/frontend-landing/src/lib/locale.ts +55 -0
  508. package/templates/apps/frontend-landing/src/locales/de.ts +24 -0
  509. package/templates/apps/frontend-landing/src/locales/en.ts +26 -0
  510. package/templates/apps/frontend-landing/src/pages/[locale]/index.tsx +13 -0
  511. package/templates/apps/frontend-landing/src/pages/[locale]/mirrors.test.tsx +37 -0
  512. package/templates/apps/frontend-landing/src/pages/index.test.tsx +110 -0
  513. package/templates/apps/frontend-landing/src/pages/index.tsx +75 -0
  514. package/templates/apps/frontend-landing/src/pages/layout.test.tsx +84 -0
  515. package/templates/apps/frontend-landing/src/pages/layout.tsx +66 -0
  516. package/templates/apps/frontend-landing/template.json +6 -0
  517. package/templates/apps/frontend-landing/tsconfig.json +11 -0
  518. package/templates/apps/frontend-spa/README.md +45 -0
  519. package/templates/apps/frontend-spa/app.config.ts +27 -0
  520. package/templates/apps/frontend-spa/package.json +29 -0
  521. package/templates/apps/frontend-spa/src/globals.css +84 -0
  522. package/templates/apps/frontend-spa/src/locales/de.ts +22 -0
  523. package/templates/apps/frontend-spa/src/locales/en.ts +29 -0
  524. package/templates/apps/frontend-spa/src/locales/index.ts +15 -0
  525. package/templates/apps/frontend-spa/src/pages/index.test.tsx +137 -0
  526. package/templates/apps/frontend-spa/src/pages/index.tsx +123 -0
  527. package/templates/apps/frontend-spa/src/pages/layout.tsx +27 -0
  528. package/templates/apps/frontend-spa/template.json +6 -0
  529. package/templates/apps/frontend-spa/tsconfig.json +11 -0
  530. package/templates/apps/frontend-ssr/README.md +68 -0
  531. package/templates/apps/frontend-ssr/app.config.ts +32 -0
  532. package/templates/apps/frontend-ssr/package.json +29 -0
  533. package/templates/apps/frontend-ssr/src/globals.css +67 -0
  534. package/templates/apps/frontend-ssr/src/locales/de.ts +41 -0
  535. package/templates/apps/frontend-ssr/src/locales/en.ts +54 -0
  536. package/templates/apps/frontend-ssr/src/locales/index.ts +16 -0
  537. package/templates/apps/frontend-ssr/src/pages/feed-swr.test.tsx +69 -0
  538. package/templates/apps/frontend-ssr/src/pages/feed-swr.tsx +54 -0
  539. package/templates/apps/frontend-ssr/src/pages/feed.test.tsx +73 -0
  540. package/templates/apps/frontend-ssr/src/pages/feed.tsx +64 -0
  541. package/templates/apps/frontend-ssr/src/pages/index.test.tsx +89 -0
  542. package/templates/apps/frontend-ssr/src/pages/index.tsx +72 -0
  543. package/templates/apps/frontend-ssr/src/pages/layout.tsx +37 -0
  544. package/templates/apps/frontend-ssr/template.json +6 -0
  545. package/templates/apps/frontend-ssr/tsconfig.json +11 -0
  546. package/templates/apps/frontend-ssr-api/README.md +50 -0
  547. package/templates/apps/frontend-ssr-api/app.config.ts +43 -0
  548. package/templates/apps/frontend-ssr-api/package.json +30 -0
  549. package/templates/apps/frontend-ssr-api/src/globals.css +38 -0
  550. package/templates/apps/frontend-ssr-api/src/globals.d.ts +6 -0
  551. package/templates/apps/frontend-ssr-api/src/locales/de.ts +20 -0
  552. package/templates/apps/frontend-ssr-api/src/locales/en.ts +31 -0
  553. package/templates/apps/frontend-ssr-api/src/locales/index.ts +16 -0
  554. package/templates/apps/frontend-ssr-api/src/pages/index.test.tsx +105 -0
  555. package/templates/apps/frontend-ssr-api/src/pages/index.tsx +83 -0
  556. package/templates/apps/frontend-ssr-api/src/pages/layout.tsx +28 -0
  557. package/templates/apps/frontend-ssr-api/template.json +6 -0
  558. package/templates/apps/frontend-ssr-api/tsconfig.json +11 -0
  559. package/templates/apps/frontend-static-blog/README.md +49 -0
  560. package/templates/apps/frontend-static-blog/app.config.ts +34 -0
  561. package/templates/apps/frontend-static-blog/package.json +28 -0
  562. package/templates/apps/frontend-static-blog/src/components/ReadingProgress.island.test.tsx +65 -0
  563. package/templates/apps/frontend-static-blog/src/components/ReadingProgress.island.tsx +35 -0
  564. package/templates/apps/frontend-static-blog/src/content/posts.ts +64 -0
  565. package/templates/apps/frontend-static-blog/src/globals.css +75 -0
  566. package/templates/apps/frontend-static-blog/src/lib/locale.test.ts +72 -0
  567. package/templates/apps/frontend-static-blog/src/lib/locale.ts +55 -0
  568. package/templates/apps/frontend-static-blog/src/locales/de.ts +19 -0
  569. package/templates/apps/frontend-static-blog/src/locales/en.ts +26 -0
  570. package/templates/apps/frontend-static-blog/src/pages/[locale]/blog/[slug].tsx +20 -0
  571. package/templates/apps/frontend-static-blog/src/pages/[locale]/index.tsx +13 -0
  572. package/templates/apps/frontend-static-blog/src/pages/[locale]/mirrors.test.tsx +62 -0
  573. package/templates/apps/frontend-static-blog/src/pages/blog/[slug].test.tsx +116 -0
  574. package/templates/apps/frontend-static-blog/src/pages/blog/[slug].tsx +69 -0
  575. package/templates/apps/frontend-static-blog/src/pages/index.test.tsx +100 -0
  576. package/templates/apps/frontend-static-blog/src/pages/index.tsx +58 -0
  577. package/templates/apps/frontend-static-blog/src/pages/layout.tsx +63 -0
  578. package/templates/apps/frontend-static-blog/template.json +6 -0
  579. package/templates/apps/frontend-static-blog/tsconfig.json +11 -0
  580. package/templates/baselines/bare/.env.example +37 -0
  581. package/templates/baselines/bare/README.md +47 -0
  582. package/templates/baselines/bare/baseline.json +31 -0
  583. package/templates/baselines/bare/deploy/README.md +43 -0
  584. package/templates/baselines/bare/deploy/voltro.service.example +36 -0
  585. package/templates/baselines/compose/.env.example +46 -0
  586. package/templates/baselines/compose/README.md +69 -0
  587. package/templates/baselines/compose/baseline.json +51 -0
  588. package/templates/baselines/compose/docker/.dockerignore +38 -0
  589. package/templates/baselines/compose/docker/api.Dockerfile +57 -0
  590. package/templates/baselines/compose/docker/dev.Dockerfile +35 -0
  591. package/templates/baselines/compose/docker/web.Dockerfile +59 -0
  592. package/templates/baselines/compose/docker-compose.dev.yml +89 -0
  593. package/templates/baselines/compose/docker-compose.prod.yml +87 -0
  594. package/templates/baselines/compose/docker-compose.yml +41 -0
  595. package/templates/baselines/compose-mariadb/.env.example +57 -0
  596. package/templates/baselines/compose-mariadb/README.md +78 -0
  597. package/templates/baselines/compose-mariadb/baseline.json +51 -0
  598. package/templates/baselines/compose-mariadb/docker/.dockerignore +38 -0
  599. package/templates/baselines/compose-mariadb/docker/api.Dockerfile +57 -0
  600. package/templates/baselines/compose-mariadb/docker/dev.Dockerfile +35 -0
  601. package/templates/baselines/compose-mariadb/docker/mariadb-init.sql +6 -0
  602. package/templates/baselines/compose-mariadb/docker/web.Dockerfile +59 -0
  603. package/templates/baselines/compose-mariadb/docker-compose.dev.yml +117 -0
  604. package/templates/baselines/compose-mariadb/docker-compose.prod.yml +114 -0
  605. package/templates/baselines/compose-mariadb/docker-compose.yml +79 -0
  606. package/templates/baselines/helm/.env.example +39 -0
  607. package/templates/baselines/helm/README.md +98 -0
  608. package/templates/baselines/helm/baseline.json +53 -0
  609. package/templates/baselines/helm/charts/voltro-app/.helmignore +10 -0
  610. package/templates/baselines/helm/charts/voltro-app/Chart.yaml +10 -0
  611. package/templates/baselines/helm/charts/voltro-app/templates/_helpers.tpl +36 -0
  612. package/templates/baselines/helm/charts/voltro-app/templates/configmap.yaml +13 -0
  613. package/templates/baselines/helm/charts/voltro-app/templates/deployment-api.yaml +120 -0
  614. package/templates/baselines/helm/charts/voltro-app/templates/deployment-web.yaml +45 -0
  615. package/templates/baselines/helm/charts/voltro-app/templates/ingress.yaml +37 -0
  616. package/templates/baselines/helm/charts/voltro-app/templates/postgres-service.yaml +19 -0
  617. package/templates/baselines/helm/charts/voltro-app/templates/postgres-statefulset.yaml +73 -0
  618. package/templates/baselines/helm/charts/voltro-app/templates/secret.yaml +33 -0
  619. package/templates/baselines/helm/charts/voltro-app/templates/service-api.yaml +19 -0
  620. package/templates/baselines/helm/charts/voltro-app/templates/service-web.yaml +19 -0
  621. package/templates/baselines/helm/charts/voltro-app/values-dev.yaml +21 -0
  622. package/templates/baselines/helm/charts/voltro-app/values-prod.yaml +58 -0
  623. package/templates/baselines/helm/charts/voltro-app/values-staging.yaml +25 -0
  624. package/templates/baselines/helm/charts/voltro-app/values.yaml +109 -0
  625. package/templates/baselines/helm/deploy/README.md +94 -0
  626. package/templates/patches/@effect__cluster@0.59.0.patch +262 -0
@@ -0,0 +1,128 @@
1
+ # templates.custom
2
+
3
+ > Add a template the CLI can scaffold from — a directory under voltro-templates/apps/ with a manifest and the files to copy.
4
+
5
+
6
+
7
+ ---
8
+
9
+ <!-- source: en/templates/custom.md -->
10
+ ## Roll your own
11
+
12
+ _Add a template the CLI can scaffold from — a directory under voltro-templates/apps/ with a manifest and the files to copy._
13
+
14
+ Templates aren't magic. Each one is a directory under `voltro-templates/apps/<id>/` with a `template.json` manifest plus the files to scaffold. Drop a new directory and the CLI walks it on the next `voltro list-templates`.
15
+
16
+ The directory NAME is the template id you pass to `--api` / `--web` / `--template`. The id must match `^[a-zA-Z][a-zA-Z0-9-]*$` — kebab-lowercase, no `@` or `/`.
17
+
18
+ ## Minimum viable template
19
+
20
+ ```text
21
+ my-template/
22
+ ├── template.json
23
+ ├── package.json
24
+ ├── app.config.ts
25
+ ├── tsconfig.json
26
+ └── src/
27
+ └── pages/
28
+ └── index.tsx
29
+ ```
30
+
31
+ The `template.json` manifest (`id`, `kind`, `summary`, optional `tags`):
32
+
33
+ ```json
34
+ {
35
+ "id": "acme-internal-tool",
36
+ "kind": "web",
37
+ "summary": "Internal tool starter — our team's auth + table conventions baked in.",
38
+ "tags": ["internal", "tool"]
39
+ }
40
+ ```
41
+
42
+ `kind` is `'api'` or `'web'` — the CLI rejects an api template passed to `--web` (and vice-versa). `id` must equal the directory name, or the loader skips the dir.
43
+
44
+ Now `voltro list-templates` includes it, and `voltro create-project x --web=acme-internal-tool` (web) or `--api=acme-internal-tool` (api) scaffolds it.
45
+
46
+ ## Token substitution
47
+
48
+ Any file's CONTENT can contain placeholders. The scaffolder rewrites them from the app + project names you pass; the kebab form is what's persisted (folders, `package.json` `name`), camel/Pascal/snake are derived per use:
49
+
50
+ | Token | Form | Example (`appName=my-app`, `projectName=acme-cms`) |
51
+ |---|---|---|
52
+ | `{{appName}}` | kebab | `my-app` |
53
+ | `{{projectName}}` | kebab | `acme-cms` |
54
+ | `{{appNameCamel}}` | camelCase | `myApp` |
55
+ | `{{projectNameCamel}}` | camelCase | `acmeCms` |
56
+ | `{{appNamePascal}}` | PascalCase | `MyApp` |
57
+ | `{{projectNamePascal}}` | PascalCase | `AcmeCms` |
58
+ | `{{capAppName}}` | PascalCase alias of `appNamePascal` | `MyApp` |
59
+ | `{{capProjectName}}` | PascalCase alias of `projectNamePascal` | `AcmeCms` |
60
+ | `{{appNameSnake}}` | snake_case (SQL / bucket names) | `my_app` |
61
+ | `{{projectNameSnake}}` | snake_case | `acme_cms` |
62
+ | `{{port}}` | the port allocated from the project's `portRange` (web apps) | `5191` |
63
+
64
+ Example `app.config.ts`:
65
+
66
+ ```ts
67
+ export default {
68
+ type: 'web' as const,
69
+ name: '{{capProjectName}}{{capAppName}}',
70
+ port: {{port}},
71
+ }
72
+ ```
73
+
74
+ Substitution is global across all files (content only — file NAMES aren't templated). The scaffolder also rewrites `package.json`'s `name` field on the fly so the scaffolded app gets a real pnpm-workspace name even if the template forgot to template it.
75
+
76
+ ## Where templates live
77
+
78
+ The CLI loads templates from two places, in order:
79
+
80
+ 1. **Source mode** (dev): walks up from the CLI's own dir looking for a sibling `voltro-templates/apps/`. This is the source of truth in this repo.
81
+ 2. **Bundled fallback** (post-publish): a snapshot of `voltro-templates/apps/` shipped inside the CLI package.
82
+
83
+ To add a template for the framework itself, drop a directory under `voltro-templates/apps/<id>/`. There is no env-var path override and no npm-package fetch — the loader is hardcoded to those two locations.
84
+
85
+ ## What's in a template
86
+
87
+ | File | Purpose |
88
+ |---|---|
89
+ | `template.json` | Manifest with `id`, `kind`, `summary`, optional `tags`. Stripped — never lands in the scaffolded app. |
90
+ | `package.json` | The scaffolded app's deps + scripts. Its `name` is rewritten on scaffold. |
91
+ | `app.config.ts` | The app's framework config (port, name, plugins). |
92
+ | `tsconfig.json` | TypeScript config. Usually extends a workspace base. |
93
+ | `README.md` | Human-readable description; copied verbatim (with tokens substituted). |
94
+ | everything else | Copied into the target app dir with token substitution. |
95
+
96
+ The scaffolder copies every file except `template.json` (and obvious build artefacts — `node_modules/`, `dist/`, `.framework/`). No "templating engine" beyond the token-replacement walker.
97
+
98
+ ## Tips for good templates
99
+
100
+ - **Start small.** A short index page + the right deps beats a 2000-line "everything imaginable".
101
+ - **Inline comments explain the WHY.** Scaffolded code is read by the next dev. The shipped templates' comments are part of the value.
102
+ - **Use the kit primitives.** Don't re-invent a Button when `@voltro/ui-shadcn` ships one.
103
+ - **Leave room.** Show the pattern; don't fill every file with example data. The user will replace it.
104
+ - **Test by scaffolding.** Before relying on it, `voltro create-project --web=my-template` against a clean directory. Boot it. Refine.
105
+
106
+ ## The framework's own templates
107
+
108
+ Read `voltro-templates/apps/*/` for reference. Every shipped template's source is the best example of "what a good template looks like" — short, opinionated, idiomatic Voltro.
109
+
110
+ ## Listing templates
111
+
112
+ ```bash
113
+ voltro list-templates
114
+ voltro list-templates --json
115
+ ```
116
+
117
+ For programmatic use (build + publish a catalogue page):
118
+
119
+ ```ts
120
+ import { listTemplates } from '@voltro/cli'
121
+ const all = await listTemplates()
122
+ // [{ id, kind, summary, tags, path }, …]
123
+ ```
124
+
125
+ ## See also
126
+
127
+ - [Scaffolding CLI](/docs/cli/scaffolding) — the consumer of templates.
128
+ - [App templates overview](/docs/templates/overview) — the shipped catalogue.
@@ -0,0 +1,122 @@
1
+ # Templates
2
+
3
+ > Thirty-four dogfooded starter templates ship with the framework — twenty backend shapes, thirteen frontend shapes, and a serverless function library. Scaffold any of them with one CLI call.
4
+
5
+
6
+
7
+ ---
8
+
9
+ <!-- source: en/templates/overview.md -->
10
+ ## Overview
11
+
12
+ _Thirty-four dogfooded starter templates ship with the framework — twenty backend shapes, thirteen frontend shapes, and a serverless function library. Scaffold any of them with one CLI call._
13
+
14
+ Voltro ships **thirty-four** starter templates across the **three kinds** you actually deploy: **twenty** backends (`api-*`), **thirteen** frontends (`frontend-*` plus `changelog`), and **one** serverless library (`edge-functions`). Each is a small, opinionated, dogfooded reference you scaffold once and then own — no update channel, no lock-in.
15
+
16
+ The CLI loads templates by walking `voltro-templates/apps/<id>/`; the directory name IS the template id you pass to `--api` / `--web` / `--template`. Run `voltro list-templates` to see them live.
17
+
18
+ ```bash
19
+ # A project with a backend + a blank frontend:
20
+ voltro create-project acme --api=api-backend --web=frontend-blank
21
+
22
+ # Add another app to an existing project later:
23
+ voltro add-app marketing --template=frontend-landing --to acme
24
+ ```
25
+
26
+ Each app gets its own port from the project's `portRange`, wired through `pnpm dev`, ready to edit.
27
+
28
+ ## Backend templates (`--api=<id>`)
29
+
30
+ The four `api-backend*` shapes share the same minimal `notes` domain and differ only in the plugin/store wired on top. The other three are **feature showcases** — a cohesive domain that exercises one whole slice of the framework end to end.
31
+
32
+ | Template | Best for |
33
+ |---|---|
34
+ | [`api-backend`](/docs/templates/api-backend) | The minimal Voltro backend: `app.config.ts` + schema + one streaming query + one tenant-guarded mutation. Start here. |
35
+ | [`api-backend-mail`](/docs/templates/api-backend-mail) | `api-backend` + `@voltro/plugin-mail` and a React-Email welcome template you preview/send from the dashboard. |
36
+ | [`api-backend-storage`](/docs/templates/api-backend-storage) | `api-backend` + `@voltro/plugin-storage` — public (CDN-direct) and private (policy + grants) objects with upload examples. |
37
+ | [`api-backend-mariadb`](/docs/templates/api-backend-mariadb) | MariaDB-backed: binlog CDC real-time across replicas + file storage. The dogfooded shape for K8s multi-replica apps. |
38
+ | [`api-durable`](/docs/templates/api-durable) | The whole **durable + reactive** surface in one order-fulfillment domain: a workflow (`step` / `sleep` / `awaitSignal` approval gate), an event trigger that starts it, a signal-injecting mutation, a cron schedule, a table subscriber, a materialized aggregate, and a run-once startup hook. |
39
+ | [`api-ai`](/docs/templates/api-ai) | A **RAG support agent**: a `vectorEmbedding()` docs table, a search tool, a real `defineAgent` / `defineAgentExecutor` model loop, and a `generateObject` action. Boots zero-infra; needs an AI key only to *run* the agent. |
40
+ | [`api-data-advanced`](/docs/templates/api-data-advanced) | The **advanced schema DSL**: the `*.entity.ts` / `*.relations.ts` split with eager `.with()`, full-text search, `dbEnum`, array / generated / encrypted columns, and declarative query caching — a small authors + books catalog. |
41
+ | [`api-kv`](/docs/templates/api-kv) | **Durable `ctx.kv`** on an external-event-sync domain: a sync cursor you can't recompute plus TTL-bounded idempotency markers, contrasted with `ctx.store` (the rows) and `ctx.cache`. Exercises the full KV surface (getOrElse / has / set+TTL / list / delete). |
42
+ | [`api-auth`](/docs/templates/api-auth) | **Real user auth** — `@voltro/plugin-auth` wired turnkey: password sign-up/in/out over HttpOnly session cookies + a strategy that resolves the session to a typed `Subject`. Zero-infra boot. |
43
+ | [`api-rest`](/docs/templates/api-rest) | **Public REST + OpenAPI** — `defineRestRoute` endpoints (query/path/body, scope guards, `Idempotency-Key`) + `@voltro/plugin-openapi` (Swagger UI at `/docs`, generated from the descriptors). Zero-infra boot. |
44
+ | [`api-saas`](/docs/templates/api-saas) | **The SaaS plugin bundle** — billing entitlements (a quota gate), in-app + console notifications, analytics events, and live presence, wired turnkey. One `projects.create` exercises billing + analytics + notifications together. |
45
+ | [`api-observability`](/docs/templates/api-observability) | **Metrics + errors + tests** — `@voltro/plugin-prometheus` (`GET /metrics` + a custom counter), `@voltro/plugin-sentry` (inert without a DSN), tracing, and a `@voltro/testing` unit test. Zero-infra boot. |
46
+ | [`api-webhooks`](/docs/templates/api-webhooks) | **First-class webhooks** — a signature-verified incoming `*.webhook.tsx` receiver (rejects forged traffic before your handler) + an outgoing `defineOutgoingEvent` a mutation emits via a durable signed delivery workflow. Zero-infra boot. |
47
+ | [`api-search`](/docs/templates/api-search) | **Full-text search in sync** — `@voltro/plugin-search` mirrors every table write into an index via the post-commit change tap; the synthesized `search.query` rpc returns tenant-scoped hits. Memory backend (zero infra); one line to Typesense/Meilisearch/Algolia. |
48
+ | [`api-feature-flags`](/docs/templates/api-feature-flags) | **Feature flags as code** — `@voltro/plugin-flags`: kill-switch / %-rollout / targeting, a declarative `gatedBy` map + an in-handler `requireFlag` guard (both fail typed `FlagDisabled`), `useFlag()` on the web. Memory store. |
49
+ | [`api-ratelimit`](/docs/templates/api-ratelimit) | **Per-endpoint rate limiting** — `@voltro/plugin-ratelimit` intercepts rpc: a default + rules (sliding-window / token-bucket, by subject/tenant/…), typed `RateLimited` auto-merged into the error union. Memory store. |
50
+ | [`api-rbac`](/docs/templates/api-rbac) | **Role → scope access control** — `@voltro/plugin-rbac`: a role map, an interceptor resolving roles to scopes, and an in-handler `permission(ctx, 'notes:write')` guard (typed `Forbidden`). `admin:full` bypasses. Config-only. |
51
+ | [`api-moderation`](/docs/templates/api-moderation) | **Pre-commit content moderation** — `@voltro/plugin-moderation` checks fields before the handler: a `block` rule rejects with typed `ContentRejected`, a `flag` rule queues for review. keywordProvider / aiProvider. |
52
+ | [`api-versioning`](/docs/templates/api-versioning) | **Row history + time-travel** — `@voltro/plugin-versioning` snapshots every write via the change tap; `rowHistory()` (every version) + `rowAsOf()` (value at a past instant), read through handlers. Memory store. |
53
+ | [`api-backend-deactivation`](/docs/templates/api-backend-deactivation) | **The `deactivation()` mixin** — lock a user out (`deactivatedAt`) while the row stays VISIBLE/queryable — the deliberate opposite of `softDelete()`'s hide+anonymise. Pure schema. |
54
+ | [`api-governance`](/docs/templates/api-governance) | **Field encryption + GDPR + consent + retention** — `@voltro/plugin-governance`: AES-256-GCM `.encrypted()` columns (plaintext to handlers, ciphertext at rest), admin-gated `governance.export`/`erase`, a consent ledger, retention sweeps. |
55
+
56
+ All twenty are `kind: 'api'`.
57
+
58
+ ## Frontend templates (`--web=<id>`)
59
+
60
+ Thirteen web shapes spanning every render mode — `static`, `spa`, `ssr`, `isr`, selective `islands` hydration — plus the reactive fullstack loop.
61
+
62
+ **Every frontend template is bilingual (en/de) out of the box**, with the i18n strategy matched to its render mode: the hydrated/SSR shells use cookie i18n (`<LocaleSwitcher>`), the static/islands sites use URL-prefix i18n (`/de/…`, one pre-rendered HTML file per locale). `frontend-i18n` remains the dedicated URL-prefix reference. See [URL strategies](/docs/i18n/url-strategies) for why render mode decides.
63
+
64
+ | Template | Render mode | Best for |
65
+ |---|---|---|
66
+ | [`frontend-blank`](/docs/templates/blank) | — | Empty React + Vite shell with a layout and an index page. Start here for any custom UI. |
67
+ | [`frontend-app`](/docs/templates/app) | `full` · reactive | **The reactive end-to-end loop** — a web frontend WIRED to an api (`useSubscription` + `useMutation` + auto-optimistic). The only fullstack template; pairs with `api-backend`. |
68
+ | [`frontend-dashboard`](/docs/templates/dashboard) | `static` + `ssr` | **Auth-gated app shell** — a silent `(marketing)` route group + a `/dashboard` area gated by a nested layout loader that `RedirectError`s to `/login`. Scoped error/loading/not-found. No backend. |
69
+ | [`frontend-admin`](/docs/templates/admin) | `ssr` · reactive | **Auto-admin back-office** — discovers your api's entities at runtime (capability map) and renders a live, permission-gated `<DataTable>` + `<AutoForm>` per entity, with provenance + undo. Editable template code; pairs with any api. |
70
+ | [`frontend-landing`](/docs/templates/landing) | `static` · `islands` | Marketing landing — hero, features grid, CTA. Zero JS by default; flip `interactive: 'islands'` for interactive pieces. |
71
+ | [`frontend-docs`](/docs/templates/docs) | `static` (catch-all SSG) | Documentation site — catch-all `docs/[...slug].tsx`, per-section layout, `getStaticPaths` so every page pre-renders at build. |
72
+ | [`frontend-i18n`](/docs/templates/i18n) | `static` · per-locale SSG | **Bilingual (en/de) URL-prefix i18n** — type-checked catalogs, `[locale]` mirror pages, per-locale `<title>`. Each language is its own crawlable URL. |
73
+ | [`changelog`](/docs/templates/changelog) | `static` | Changelog / release-notes — MDX releases rendered to a list + per-release pages (highlighted code) + an RSS feed, powered by `@voltro/changelog`. |
74
+ | [`frontend-static-blog`](/docs/templates/static-blog) | `static` + `islands` | **SSG from a content source**: dynamic `[slug]` routes pre-rendered via `getStaticPaths`, per-post `meta` from loader data, and ONE island (reading-progress bar) showing selective hydration. |
75
+ | [`frontend-spa`](/docs/templates/spa) | `spa` | A **pure client-rendered** tool — state lives in the browser (`localStorage`), so there's nothing to SSR. Where a single-page app is the right call. |
76
+ | [`frontend-ssr`](/docs/templates/ssr) | `ssr` + `isr` | **Server-rendered pages**: a per-request SSR page (`useServerRequest()` for cookies/headers) + ISR pages (`revalidate`, `staleWhileRevalidate`, tenant-aware caching). Needs a runtime, not a CDN. |
77
+ | [`frontend-ssr-api`](/docs/templates/ssr-api) | `ssr` · fed by api | **SSR from your backend** — an `ssr` loader calls `query('notes.list', {})` over the sibling api's POST /rpc, so real rows are in the first paint + `<title>`; `useSubscription` upgrades to live. Pairs with `api-backend`. |
78
+ | [`frontend-contact`](/docs/templates/contact) | `static` + serverless | **Static page + a serverless email form** — the headline "static frontend, serverless backend" combo. The page ships to a CDN; the function scales to zero. |
79
+
80
+ All thirteen are `kind: 'web'`. The CLI rejects an api template passed to `--web` (and vice-versa) on a kind mismatch.
81
+
82
+ ## Serverless template (`--template=<id>` via `add-app`)
83
+
84
+ | Template | Best for |
85
+ |---|---|
86
+ | [`edge-functions`](/docs/templates/edge-functions) | A **library of `*.serverless.ts` functions** covering the range of edge work — pure compute, request-header/geo, outbound HTTP (fire-and-forget + fetch-and-transform), Web Crypto HMAC verify, an LLM call, and status-controlled errors. Run with `voltro serverless dev`; ship to node / Cloudflare / Scaleway. No long-running server, no port. |
87
+
88
+ `kind: 'serverless'` — added to a project with `voltro add-app <name> --template=edge-functions`.
89
+
90
+ ## Static + serverless combo
91
+
92
+ The most common no-always-on-server shape: **a static page on a CDN + a serverless function for the one dynamic bit.** `frontend-contact` ships it whole — a static page whose island form POSTs to a bundled `*.serverless.ts` that sends mail. Or add `edge-functions` to any static web template and wire the page to whichever function it needs. The function's local dev server sends CORS headers (same as the edge hosts), so the cross-origin form works out of the box.
93
+
94
+ ## Baselines — the deploy layer
95
+
96
+ A **baseline** is orthogonal to the app template: it's the deploy/ops files that say how to run + ship the stack. Pick one at create time with `--baseline=<id>`, or switch later with `voltro baseline set <id>`. Four ship:
97
+
98
+ | Baseline | What it gives you | When to pick it |
99
+ |---|---|---|
100
+ | `bare` | `.env.example` + a sample systemd unit. No Docker, no Helm — you bring your own Postgres. | Solo dev, prototyping, environments where Docker is unavailable. |
101
+ | `compose` | `docker/{api,web}.Dockerfile` + `docker-compose.yml` (Postgres) + dev (HMR) and prod (built images) variants. | Teams without k8s, VPS/self-host, reproducible onboarding. |
102
+ | `compose-mariadb` | Like `compose` but MariaDB (binlog CDC, ROW) + MinIO object storage. The local mirror of the `helm` MariaDB shape. | Apps targeting MariaDB + CDC + file storage locally. |
103
+ | `helm` | `charts/voltro-app/` Helm chart, per-env values (`dev`/`staging`/`prod`), Deployment + Service + Ingress, Postgres StatefulSet OR external MariaDB via a `db.dialect` switch. | k8s shops, GitOps (ArgoCD / Flux), multi-cluster prod. |
104
+
105
+ ```bash
106
+ # Pick the app templates AND the baseline at once:
107
+ voltro create-project acme --api=api-backend --web=frontend-blank --baseline=compose
108
+
109
+ # Wire the Redis cache backend while scaffolding (injects the service into the baseline + .env):
110
+ voltro create-project acme --api=api-backend --web=frontend-blank --baseline=compose --cache=redis
111
+
112
+ # Switch the baseline later (destructive but backed up):
113
+ voltro baseline set helm
114
+ ```
115
+
116
+ Without `--baseline`, the interactive prompt lists the ids; press Enter to skip and add one later. Baseline files apply at the **workspace root** (where `pnpm-workspace.yaml` lives), not inside `apps/<project>/`.
117
+
118
+ ## Where to read next
119
+
120
+ - [App templates reference](/docs/reference/templates) — the full catalogue table, by kind, with combos.
121
+ - [Roll your own template](/docs/templates/custom) — add a template the CLI scaffolds from.
122
+ - [Scaffolding CLI](/docs/cli/scaffolding) — the commands that consume templates.
@@ -0,0 +1,315 @@
1
+ # templates.serverless
2
+
3
+ > A library of standalone *.serverless.ts functions — pure compute, request-header/geo, outbound HTTP, Web Crypto HMAC, an LLM call, status-controlled errors. Run with voltro serverless; ship to node / Cloudflare / Scaleway. No server, no port.
4
+
5
+
6
+
7
+ ---
8
+
9
+ <!-- source: en/templates/edge-functions.md -->
10
+ ## Edge functions
11
+
12
+ _A library of standalone *.serverless.ts functions — pure compute, request-header/geo, outbound HTTP, Web Crypto HMAC, an LLM call, status-controlled errors. Run with voltro serverless; ship to node / Cloudflare / Scaleway. No server, no port._
13
+
14
+ A standalone library of `*.serverless.ts` functions that walks the RANGE of what an edge function actually does: pure compute, reading the request's geo header, outbound HTTP (fire-and-forget AND fetch-and-transform), a Web Crypto HMAC verify, a one-shot LLM call, and status-controlled errors. There is NO long-running api here, no `voltro dev`, no port — each function is bundled + deployed on its own with `voltro serverless`, and scales to zero between requests. Every handler is **edge-safe** (no `node:*`), so the SAME file runs on Cloudflare Workers, Scaleway Functions, and your own node box. Template id: **`edge-functions`**.
15
+
16
+ ## Scaffold
17
+
18
+ `edge-functions` is `kind: 'serverless'` — added to an existing project with `add-app`, not `create-project`:
19
+
20
+ ```bash
21
+ voltro add-app fns --template=edge-functions --to acme
22
+ ```
23
+
24
+ ## What ships
25
+
26
+ ```text
27
+ apps/acme/fns/ # dir named by the app, not the template
28
+ ├── package.json # scripts: list, build, serve, typecheck
29
+ ├── tsconfig.json
30
+ ├── README.md
31
+ └── functions/
32
+ ├── health.serverless.ts # GET · pure Effect.sync diagnostic; ctx.env
33
+ ├── shareLink.serverless.ts # POST · pure compute; runtime hints (memory/timeout/region)
34
+ ├── geoGreeting.serverless.ts # GET · reads ctx.request.headers (edge geo)
35
+ ├── slackNotify.serverless.ts # POST · ctx.waitUntil — background work after the response
36
+ ├── currencyConvert.serverless.ts # POST · outbound HTTP via HttpClient; fetch + transform JSON
37
+ ├── verifySignature.serverless.ts # POST · Web Crypto HMAC; ServerlessHttpError 401
38
+ ├── aiComplete.serverless.ts # POST · an LLM call needing a secret (ctx.env); 502 mapping
39
+ └── resolveLink.serverless.ts # GET · a lookup; 404 via ServerlessHttpError
40
+ ```
41
+
42
+ There is no `app.config.ts`, no `database/`, no `queries/` — a serverless library is not an api. Each function is its own deploy artifact, discovered by filename (`*.serverless.ts`), bundled standalone. The app depends only on `@voltro/serverless` + `@voltro/cli` + `@effect/platform` (for `HttpClient`) + `effect`.
43
+
44
+ ## The shape — `defineServerless({...})`
45
+
46
+ Every function default-exports one `defineServerless({...})` descriptor. The minimal shape is a `name`, an HTTP `method`, an `input`/`output` `effect/Schema`, and a `handler`. The `input` Schema is load-bearing: a malformed request becomes a typed `400` BEFORE your handler runs — you never hand-parse `JSON.parse(body)` and trust it. The handler receives `(input, ctx)` and returns an `Effect` (or a plain value via `Effect.sync`); `ctx` carries `env`, `request`, and `waitUntil`.
47
+
48
+ ```ts
49
+ // functions/health.serverless.ts — the simplest function: a GET diagnostic
50
+ import { Effect, Schema } from 'effect'
51
+ import { defineServerless } from '@voltro/serverless'
52
+
53
+ export default defineServerless({
54
+ name: 'health',
55
+ method: 'GET',
56
+ input: Schema.Struct({}),
57
+ output: Schema.Struct({
58
+ status: Schema.Literal('ok'),
59
+ region: Schema.String,
60
+ now: Schema.String,
61
+ }),
62
+ handler: (_input, ctx) =>
63
+ Effect.sync(() => ({
64
+ status: 'ok' as const,
65
+ // The provider injects region into the env (Scaleway SCW_REGION, your own
66
+ // VOLTRO_REGION on a node host). Cloudflare is global → 'edge'.
67
+ region: ctx.env.VOLTRO_REGION ?? ctx.env.SCW_REGION ?? ctx.env.AWS_REGION ?? 'edge',
68
+ now: new Date().toISOString(),
69
+ })),
70
+ })
71
+ ```
72
+
73
+ `ctx.env` is how a function reads config and secrets — there is no `defineEnv` here, the host injects the env at deploy time. `health` is pure (`Effect.sync`, no I/O), the cheapest thing an edge function can be.
74
+
75
+ ## Pure compute + runtime hints
76
+
77
+ `shareLink` is still pure compute (`Effect.sync`, no I/O) but adds a `runtime` block — the memory/timeout/region hints the deploy targets honour. Pure-compute functions are trivially edge-safe and the fastest to cold-start:
78
+
79
+ ```ts
80
+ // functions/shareLink.serverless.ts — id → short-lived share URL
81
+ export default defineServerless({
82
+ name: 'share-link',
83
+ method: 'POST',
84
+ input: Schema.Struct({
85
+ resourceId: Schema.String.pipe(Schema.minLength(1)),
86
+ ttlMinutes: Schema.Number.pipe(Schema.greaterThan(0)),
87
+ }),
88
+ output: Schema.Struct({ url: Schema.String, expiresAt: Schema.Number }),
89
+ runtime: { memoryMb: 128, timeoutSeconds: 10, region: 'fr-par' },
90
+ handler: ({ resourceId, ttlMinutes }, ctx) =>
91
+ Effect.sync(() => {
92
+ const base = ctx.env.SHARE_BASE_URL ?? 'https://share.example'
93
+ const expiresAt = Date.now() + ttlMinutes * 60_000
94
+ return { url: `${base}/s/${encodeURIComponent(resourceId)}?exp=${expiresAt}`, expiresAt }
95
+ }),
96
+ })
97
+ ```
98
+
99
+ ## Reading the request — edge geo
100
+
101
+ `geoGreeting` reaches past the decoded `input` to the raw request via `ctx.request.headers` — here the geo header the edge host injects. Being close to the user is the whole point of running at the edge, and this reacts to where they are:
102
+
103
+ ```ts
104
+ // functions/geoGreeting.serverless.ts — a localized greeting from the caller's country
105
+ handler: ({ name }, ctx) =>
106
+ Effect.sync(() => {
107
+ // Cloudflare sets `cf-ipcountry`; other proxies use varied headers. We
108
+ // read whatever the host injected — the function code stays the same.
109
+ const country = (
110
+ ctx.request.headers.get('cf-ipcountry') ??
111
+ ctx.request.headers.get('x-vercel-ip-country') ??
112
+ ctx.request.headers.get('x-forwarded-country') ??
113
+ 'XX'
114
+ ).toUpperCase()
115
+ const hello = HELLO[country] ?? 'Hello'
116
+ return { greeting: `${hello}, ${name ?? 'there'}!`, country }
117
+ }),
118
+ ```
119
+
120
+ ## Outbound HTTP — two patterns
121
+
122
+ **Fire-and-forget** — `slackNotify` schedules delivery that OUTLIVES the response with `ctx.waitUntil(...)`. The caller gets `{ queued: true }` immediately; the actual POST runs in the background (on Cloudflare via the real `ExecutionContext.waitUntil`, best-effort elsewhere). A detached background POST needs no `HttpClient` features, so it uses the global `fetch`:
123
+
124
+ ```ts
125
+ // functions/slackNotify.serverless.ts
126
+ handler: ({ text }, ctx) =>
127
+ Effect.gen(function* () {
128
+ const webhook = ctx.env.SLACK_WEBHOOK_URL
129
+ if (!webhook) {
130
+ return yield* Effect.fail(
131
+ new ServerlessHttpError({ status: 503, message: 'slack-not-configured', detail: 'Set SLACK_WEBHOOK_URL.' }),
132
+ )
133
+ }
134
+ // Schedule the delivery in the background and respond NOW.
135
+ ctx.waitUntil(
136
+ fetch(webhook, {
137
+ method: 'POST',
138
+ headers: { 'content-type': 'application/json' },
139
+ body: JSON.stringify({ text }),
140
+ }).catch(() => {
141
+ /* best-effort — a failed notification must not fail the request */
142
+ }),
143
+ )
144
+ return { queued: true }
145
+ }),
146
+ ```
147
+
148
+ **Fetch-and-transform** — `currencyConvert` calls a third-party API with the framework-provided `HttpClient`, reads the JSON response (`yield* response.json`), transforms it, and maps an unanswerable upstream to a typed `422`. It hits a public, no-key FX endpoint so it runs out of the box:
149
+
150
+ ```ts
151
+ // functions/currencyConvert.serverless.ts
152
+ import { HttpClient, HttpClientRequest } from '@effect/platform'
153
+
154
+ handler: ({ from, to, amount }, _ctx) =>
155
+ Effect.gen(function* () {
156
+ const base = from.toUpperCase()
157
+ const quote = to.toUpperCase()
158
+ const http = yield* HttpClient.HttpClient
159
+ const response = yield* http.execute(HttpClientRequest.get(`https://open.er-api.com/v6/latest/${base}`))
160
+ const body = (yield* response.json) as { rates?: Record<string, number> }
161
+ const rate = body.rates?.[quote]
162
+ if (typeof rate !== 'number') {
163
+ return yield* Effect.fail(
164
+ new ServerlessHttpError({ status: 422, message: 'unknown-currency', detail: `no rate ${base}->${quote}` }),
165
+ )
166
+ }
167
+ return { from: base, to: quote, amount, rate, result: Math.round(amount * rate * 100) / 100 }
168
+ }),
169
+ ```
170
+
171
+ ## Web Crypto — HMAC verify
172
+
173
+ `verifySignature` uses the Web Crypto API (`crypto.subtle`) — available on every serverless host (Workers, Scaleway node, your own node) without ANY import — wrapped in `Effect.promise`. There's no `node:crypto` here precisely so the Cloudflare target keeps working. A mismatch is a `401` via `ServerlessHttpError`:
174
+
175
+ ```ts
176
+ // functions/verifySignature.serverless.ts — HMAC-SHA256 verify
177
+ const hmacHex = async (secret: string, payload: string): Promise<string> => {
178
+ const enc = new TextEncoder()
179
+ const key = await crypto.subtle.importKey('raw', enc.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])
180
+ return toHex(await crypto.subtle.sign('HMAC', key, enc.encode(payload)))
181
+ }
182
+
183
+ handler: ({ payload, signature }, ctx) =>
184
+ Effect.gen(function* () {
185
+ const secret = ctx.env.SIGNING_SECRET
186
+ if (!secret) {
187
+ return yield* Effect.fail(
188
+ new ServerlessHttpError({ status: 503, message: 'signing-not-configured', detail: 'Set SIGNING_SECRET.' }),
189
+ )
190
+ }
191
+ const expected = yield* Effect.promise(() => hmacHex(secret, payload))
192
+ if (!safeEqual(expected, signature.toLowerCase())) {
193
+ return yield* Effect.fail(new ServerlessHttpError({ status: 401, message: 'invalid-signature' }))
194
+ }
195
+ return { valid: true as const }
196
+ }),
197
+ ```
198
+
199
+ ## An LLM call needing a secret
200
+
201
+ `aiComplete` calls a third-party API that needs a SECRET — the key lives in `ctx.env`, never in the bundle. It reads the JSON response and maps an upstream failure to a `502`. It uses the OpenAI chat-completions shape but points at any compatible endpoint via `OPENAI_BASE_URL`:
202
+
203
+ ```ts
204
+ // functions/aiComplete.serverless.ts — one-shot LLM completion at the edge
205
+ handler: ({ prompt, system }, ctx) =>
206
+ Effect.gen(function* () {
207
+ const apiKey = ctx.env.OPENAI_API_KEY
208
+ if (!apiKey) {
209
+ return yield* Effect.fail(
210
+ new ServerlessHttpError({ status: 503, message: 'ai-not-configured', detail: 'Set OPENAI_API_KEY.' }),
211
+ )
212
+ }
213
+ const baseUrl = ctx.env.OPENAI_BASE_URL ?? 'https://api.openai.com'
214
+ const model = ctx.env.OPENAI_MODEL ?? 'gpt-4o-mini'
215
+
216
+ const http = yield* HttpClient.HttpClient
217
+ const request = HttpClientRequest.post(`${baseUrl}/v1/chat/completions`).pipe(
218
+ HttpClientRequest.setHeader('authorization', `Bearer ${apiKey}`),
219
+ HttpClientRequest.bodyUnsafeJson({
220
+ model,
221
+ max_tokens: 400,
222
+ messages: [
223
+ ...(system ? [{ role: 'system', content: system }] : []),
224
+ { role: 'user', content: prompt },
225
+ ],
226
+ }),
227
+ )
228
+
229
+ const response = yield* http.execute(request)
230
+ if (response.status >= 400) {
231
+ const detail = yield* response.text
232
+ return yield* Effect.fail(new ServerlessHttpError({ status: 502, message: 'ai-call-failed', detail }))
233
+ }
234
+ const body = (yield* response.json) as { choices?: ReadonlyArray<{ message?: { content?: string } }> }
235
+ return { text: body.choices?.[0]?.message?.content ?? '' }
236
+ }),
237
+ ```
238
+
239
+ ## Status-controlled errors — `ServerlessHttpError`
240
+
241
+ `ServerlessHttpError({ status, message, detail? })` is how a handler controls the HTTP status the caller sees — the throughline of the library. `resolveLink` (the read side of a link shortener) returns a `404` for an unknown code; the same mechanism produces `401` (bad signature), `422` (no FX rate), `502` (upstream LLM failure), and `503` (a secret not wired). Without it, an `Effect.fail` would surface as a generic `500`:
242
+
243
+ ```ts
244
+ // functions/resolveLink.serverless.ts — short code → destination URL
245
+ handler: ({ code }, _ctx) =>
246
+ Effect.gen(function* () {
247
+ const url = LINKS[code.toLowerCase()]
248
+ if (!url) {
249
+ return yield* Effect.fail(new ServerlessHttpError({ status: 404, message: 'unknown-code', detail: code }))
250
+ }
251
+ return { code, url }
252
+ }),
253
+ ```
254
+
255
+ ## Run locally
256
+
257
+ The package scripts are the serverless workflow — there is no `voltro dev`:
258
+
259
+ ```bash
260
+ voltro serverless list . # what functions are here
261
+ voltro serverless dev functions/health.serverless.ts # ONE function on :8910
262
+ curl http://localhost:8910/
263
+
264
+ # functions that need config read it from the env:
265
+ SLACK_WEBHOOK_URL=https://hooks.slack.com/... \
266
+ voltro serverless dev functions/slackNotify.serverless.ts
267
+ ```
268
+
269
+ `voltro serverless serve .` runs ALL of them at once (each mounted at `/<name>`) — handy as a single self-hosted sidecar. The dev runner sends CORS headers — the same headers Cloudflare / Scaleway add at the edge — so a cross-origin browser POST works in dev exactly as it will in prod.
270
+
271
+ ## Deploy targets
272
+
273
+ `voltro serverless build .` bundles every function so you can inspect the output; then ship them to one of three targets:
274
+
275
+ ```bash
276
+ voltro serverless deploy --target node # self-host kit (Dockerfile + README)
277
+ voltro serverless deploy --target cloudflare # Cloudflare Workers
278
+ voltro serverless deploy --target scaleway --namespace-id <id> # Scaleway Functions
279
+ ```
280
+
281
+ Set each function's secrets at deploy time (the host's env / secret store): `SLACK_WEBHOOK_URL`, `SIGNING_SECRET`, `OPENAI_API_KEY`, `SHARE_BASE_URL`, … The function host bills per invocation and idles to zero between requests.
282
+
283
+ ## Add your own
284
+
285
+ Drop a new `functions/<name>.serverless.ts` exporting `export default defineServerless({ … })`. It's discovered automatically — no registry, no config entry.
286
+
287
+ ## `defineAction` (api) vs. `*.serverless.ts` (this) — the decision rule
288
+
289
+ The framework's default for external I/O — an HTTP call, an email, an AI call — is a `defineAction` inside an always-on api. Reach for a `*.serverless.ts` instead ONLY when you specifically want one of:
290
+
291
+ | You want… | Pick |
292
+ |---|---|
293
+ | External I/O as part of a reactive app (it sits next to queries / mutations / a DB) | `defineAction` in an api |
294
+ | **Process isolation** — a function that can't take down your api | `*.serverless.ts` |
295
+ | **Independent scaling** — one endpoint that spikes without scaling the whole api | `*.serverless.ts` |
296
+ | **Independent release** — ship this one function without redeploying the api | `*.serverless.ts` |
297
+ | **Scale-to-zero** for a rarely-hit endpoint (no always-on server) | `*.serverless.ts` |
298
+
299
+ If none of those apply, an action in an api is the simpler, cheaper choice — it's typed end-to-end to the rpc client and shares the api's runtime, auth, and DB.
300
+
301
+ ## Pairs well with
302
+
303
+ - [Serverless functions](/docs/deployment/serverless-functions) — the deploy + runtime model for `*.serverless.ts` (node / Cloudflare / Scaleway).
304
+ - [Scale to zero](/docs/deployment/scale-to-zero) — why these idle to zero and bill per invocation.
305
+ - [Static sites](/docs/deployment/static-sites) — pair a function with a pre-rendered page on a CDN.
306
+ - [`frontend-contact`](/docs/templates/contact) — the static-page + ONE-serverless-backend starter; reach for `edge-functions` when you need MORE than one function.
307
+ - [Actions](/docs/data/actions) — the in-api alternative for external I/O when you DON'T need process isolation / independent scaling.
308
+
309
+ ## Anti-patterns
310
+
311
+ - **Reaching for `node:*` in a function.** The handler is edge-safe by design (it runs on a Cloudflare Worker). Use the framework `HttpClient` (or global `fetch`) for outbound HTTP and `crypto.subtle` (Web Crypto) for hashing — a `node:`-prefixed import breaks the Cloudflare/Scaleway targets.
312
+ - **Skipping the input Schema.** The `defineServerless` `input` is what turns a malformed request into a typed `400` before your handler runs. Don't hand-parse the body and trust it.
313
+ - **Returning a bare `Effect.fail` when you mean a specific status.** That surfaces as a generic `500`. Use `ServerlessHttpError({ status, message })` so the caller gets `401` / `404` / `422` / `502` / `503` — the whole point of the controlled-error functions.
314
+ - **Pretending to succeed when a secret isn't wired.** Every config-dependent function here fails LOUD with a `503 *-not-configured` the caller can render. Don't swap that for a silent `{ ok: true }`.
315
+ - **Treating the library like an api.** A `*.serverless.ts` is standalone — bundled + deployed on its own with `voltro serverless`, never discovered by `voltro dev`. If you find yourself wanting queries, subscriptions, or a database next to it, you want an api template + a `defineAction`, not this.