@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,137 @@
1
+ // @vitest-environment jsdom
2
+ //
3
+ // `/` — the SPA bill-splitter. A 100% client-side page (`renderMode='spa'`)
4
+ // built from React state + localStorage; no rpc client, no loader, no
5
+ // framework hooks. We assert the config export, that it renders, and — the
6
+ // real observable behavior — that entering a bill + choosing a tip preset +
7
+ // people count updates the computed per-person total.
8
+
9
+ import { afterEach, beforeEach, describe, expect, test } from 'vitest'
10
+ import { act, createElement, type ReactNode } from 'react'
11
+ import { createRoot, type Root } from 'react-dom/client'
12
+ import { I18nProvider } from '@voltro/i18n'
13
+ import enCatalog from '../locales/en'
14
+
15
+ import BillSplitter, { renderMode } from './index'
16
+
17
+ ;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true
18
+
19
+ let container: HTMLDivElement
20
+ let root: Root
21
+
22
+ // The page uses <T>, so it needs an <I18nProvider>. Wrap with the real English
23
+ // catalog (the framework auto-wires this provider in the running app).
24
+ const render = (node: ReactNode): void => {
25
+ container = document.createElement('div')
26
+ document.body.appendChild(container)
27
+ act(() => {
28
+ root = createRoot(container)
29
+ root.render(
30
+ createElement(I18nProvider, { locale: 'en', messages: enCatalog, defaultLocale: 'en', children: node }),
31
+ )
32
+ })
33
+ }
34
+
35
+ // Native value setter so React's onChange sees the programmatic update.
36
+ const setInput = (el: HTMLInputElement, value: string): void => {
37
+ const setter = Object.getOwnPropertyDescriptor(
38
+ window.HTMLInputElement.prototype,
39
+ 'value',
40
+ )!.set!
41
+ act(() => {
42
+ setter.call(el, value)
43
+ el.dispatchEvent(new Event('input', { bubbles: true }))
44
+ })
45
+ }
46
+
47
+ // This Node build's jsdom does not provide localStorage (it needs
48
+ // --localstorage-file). The page talks to the standard Web Storage API, so we
49
+ // install a spec-compliant in-memory Storage — the same surface a browser gives
50
+ // it — and exercise the real persistence path against it.
51
+ let hadLocalStorage: boolean
52
+
53
+ beforeEach(() => {
54
+ hadLocalStorage = typeof window.localStorage !== 'undefined'
55
+ if (!hadLocalStorage) {
56
+ const store = new Map<string, string>()
57
+ const storage: Storage = {
58
+ get length() {
59
+ return store.size
60
+ },
61
+ clear: () => store.clear(),
62
+ getItem: (k) => (store.has(k) ? store.get(k)! : null),
63
+ key: (i) => Array.from(store.keys())[i] ?? null,
64
+ removeItem: (k) => {
65
+ store.delete(k)
66
+ },
67
+ setItem: (k, v) => {
68
+ store.set(k, String(v))
69
+ },
70
+ }
71
+ Object.defineProperty(window, 'localStorage', { configurable: true, value: storage })
72
+ }
73
+ window.localStorage.clear()
74
+ })
75
+
76
+ afterEach(() => {
77
+ if (root) act(() => root.unmount())
78
+ container?.remove()
79
+ document.body.innerHTML = ''
80
+ if (!hadLocalStorage) {
81
+ Reflect.deleteProperty(window, 'localStorage')
82
+ }
83
+ })
84
+
85
+ describe('index — config export', () => {
86
+ test('is a client-only SPA page', () => {
87
+ expect(renderMode).toBe('spa')
88
+ })
89
+ })
90
+
91
+ describe('index — render', () => {
92
+ test('renders the bill-splitter heading and the tip presets', () => {
93
+ render(createElement(BillSplitter))
94
+ expect(container.querySelector('h1')!.textContent).toBe('Bill splitter')
95
+ const presetButtons = Array.from(
96
+ container.querySelectorAll('.presets button'),
97
+ ).map((b) => b.textContent)
98
+ expect(presetButtons).toEqual(['10%', '15%', '18%', '20%'])
99
+ })
100
+ })
101
+
102
+ describe('index — computed split', () => {
103
+ test('computes the per-person total from bill, tip preset, and people', () => {
104
+ render(createElement(BillSplitter))
105
+
106
+ // $100 bill.
107
+ setInput(container.querySelector('#bill') as HTMLInputElement, '100')
108
+
109
+ // Choose the 20% preset.
110
+ const twentyPct = Array.from(container.querySelectorAll('.presets button')).find(
111
+ (b) => b.textContent === '20%',
112
+ ) as HTMLButtonElement
113
+ act(() => { twentyPct.dispatchEvent(new MouseEvent('click', { bubbles: true })) })
114
+
115
+ // 4 people.
116
+ setInput(container.querySelector('#people') as HTMLInputElement, '4')
117
+
118
+ // total = 100 + 20% = 120; per-person = 30.
119
+ const perPerson = container.querySelector('.result .big')!.textContent ?? ''
120
+ expect(perPerson).toContain('30')
121
+ expect(container.textContent).toContain('120') // total tip+bill shown
122
+ })
123
+
124
+ test('persists the chosen tip % to localStorage', () => {
125
+ render(createElement(BillSplitter))
126
+ const tenPct = Array.from(container.querySelectorAll('.presets button')).find(
127
+ (b) => b.textContent === '10%',
128
+ ) as HTMLButtonElement
129
+ act(() => { tenPct.dispatchEvent(new MouseEvent('click', { bubbles: true })) })
130
+ const stored: string[] = []
131
+ for (let i = 0; i < window.localStorage.length; i++) {
132
+ const key = window.localStorage.key(i)
133
+ if (key !== null) stored.push(window.localStorage.getItem(key) ?? '')
134
+ }
135
+ expect(stored).toContain('10')
136
+ })
137
+ })
@@ -0,0 +1,123 @@
1
+ // A pure client-side SPA — a bill splitter.
2
+ //
3
+ // `renderMode = 'spa'` tells `voltro build` NOT to pre-render this page:
4
+ // the client renders it on load. That is the right choice here because the
5
+ // whole page is interactive and its state lives in the browser
6
+ // (localStorage) — an SSR'd first paint would just be discarded on
7
+ // hydration, so rendering it on the server buys nothing.
8
+ //
9
+ // No backend, no rpc client, no loader. Just React + the browser.
10
+
11
+ import type { ReactNode } from 'react'
12
+ import { useEffect, useState } from 'react'
13
+ import type { PageMeta } from '@voltro/web'
14
+ import { T } from '@voltro/i18n'
15
+ import { getCatalog } from '../locales'
16
+
17
+ // Locale-aware tab title: @voltro/web resolves meta({ locale }) from the
18
+ // active locale (the `voltro:lang` cookie in this cookie-i18n app).
19
+ export const meta = ({ locale }: { readonly locale: string }): PageMeta => ({
20
+ title: getCatalog(locale)['meta.home.title'],
21
+ })
22
+
23
+ export const renderMode = 'spa' as const
24
+ // `interactive` defaults to 'full' — every component hydrates. That is
25
+ // correct for an SPA where the whole tree is interactive (don't reach for
26
+ // islands here; islands only help when most of the page is static).
27
+
28
+ const TIP_PRESETS = [10, 15, 18, 20] as const
29
+ const STORAGE_KEY = '{{appName}}:last-tip'
30
+
31
+ const money = (n: number): string =>
32
+ Number.isFinite(n) ? n.toLocaleString(undefined, { style: 'currency', currency: 'USD' }) : '—'
33
+
34
+ export default function BillSplitter(): ReactNode {
35
+ const [bill, setBill] = useState('')
36
+ const [tipPct, setTipPct] = useState(18)
37
+ const [people, setPeople] = useState(2)
38
+
39
+ // Restore the last tip % from localStorage — client-only, so read it in
40
+ // an effect (it never runs on the server).
41
+ useEffect(() => {
42
+ const saved = Number(window.localStorage.getItem(STORAGE_KEY))
43
+ if (Number.isFinite(saved) && saved > 0) setTipPct(saved)
44
+ }, [])
45
+
46
+ useEffect(() => {
47
+ window.localStorage.setItem(STORAGE_KEY, String(tipPct))
48
+ }, [tipPct])
49
+
50
+ const billNum = Math.max(0, Number(bill) || 0)
51
+ const headcount = Math.max(1, people)
52
+ const tip = billNum * (tipPct / 100)
53
+ const total = billNum + tip
54
+ const perPerson = total / headcount
55
+
56
+ return (
57
+ <div className="card">
58
+ <h1><T id="home.heading" /></h1>
59
+ <p className="muted"><T id="home.subtitle" /></p>
60
+
61
+ <label htmlFor="bill"><T id="field.bill" /></label>
62
+ <input
63
+ id="bill"
64
+ type="number"
65
+ inputMode="decimal"
66
+ min="0"
67
+ step="0.01"
68
+ placeholder="0.00"
69
+ value={bill}
70
+ onChange={(e) => setBill(e.target.value)}
71
+ />
72
+
73
+ <label><T id="field.tip" /></label>
74
+ <div className="presets">
75
+ {TIP_PRESETS.map((p) => (
76
+ <button
77
+ key={p}
78
+ type="button"
79
+ className={p === tipPct ? 'active' : ''}
80
+ onClick={() => setTipPct(p)}
81
+ >
82
+ {p}%
83
+ </button>
84
+ ))}
85
+ </div>
86
+
87
+ <div className="row">
88
+ <div>
89
+ <label htmlFor="custom"><T id="field.custom" /></label>
90
+ <input
91
+ id="custom"
92
+ type="number"
93
+ min="0"
94
+ max="100"
95
+ value={tipPct}
96
+ onChange={(e) => setTipPct(Math.max(0, Number(e.target.value) || 0))}
97
+ />
98
+ </div>
99
+ <div>
100
+ <label htmlFor="people"><T id="field.people" /></label>
101
+ <input
102
+ id="people"
103
+ type="number"
104
+ min="1"
105
+ value={people}
106
+ onChange={(e) => setPeople(Math.max(1, Math.floor(Number(e.target.value) || 1)))}
107
+ />
108
+ </div>
109
+ </div>
110
+
111
+ <div className="result">
112
+ <div className="col">
113
+ <span className="line"><span className="muted"><T id="result.tip" /></span><span>{money(tip)}</span></span>
114
+ <span className="line"><span className="muted"><T id="result.total" /></span><span>{money(total)}</span></span>
115
+ </div>
116
+ <div style={{ textAlign: 'right' }}>
117
+ <div className="muted"><T id="result.perPerson" /></div>
118
+ <div className="big">{money(perPerson)}</div>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ )
123
+ }
@@ -0,0 +1,27 @@
1
+ // Root layout — imports globals.css. The SPA renders entirely client-side,
2
+ // so there is no SSR document to worry about here.
3
+ //
4
+ // The app is bilingual (see `locales` in app.config.ts): <LocaleSwitcher>
5
+ // writes the `voltro:lang` cookie + reloads so the framework re-renders in the
6
+ // chosen language.
7
+
8
+ import type { ReactNode } from 'react'
9
+ import { useLocale, useT } from '@voltro/i18n'
10
+ import { LocaleSwitcher } from '@voltro/ui-shadcn'
11
+ import '../globals.css'
12
+
13
+ const LOCALES = [
14
+ { code: 'en', label: 'English' },
15
+ { code: 'de', label: 'Deutsch' },
16
+ ]
17
+
18
+ export default function Layout({ children }: { readonly children: ReactNode }): ReactNode {
19
+ return (
20
+ <>
21
+ <header style={{ display: 'flex', justifyContent: 'flex-end', padding: '12px 16px' }}>
22
+ <LocaleSwitcher locales={LOCALES} current={useLocale()} ariaLabel={useT('lang.label')} />
23
+ </header>
24
+ {children}
25
+ </>
26
+ )
27
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "id": "frontend-spa",
3
+ "kind": "web",
4
+ "summary": "Pure client-rendered SPA (renderMode: 'spa') — a fully interactive standalone tool with NO backend and NO SSR. Shows where a single-page app is the right call: state lives in the browser (localStorage), so server rendering would just be discarded on hydration.",
5
+ "tags": ["web", "frontend", "spa", "client", "interactive", "standalone"]
6
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx",
5
+ "lib": ["ES2024", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "moduleResolution": "Bundler"
8
+ },
9
+ "include": ["src/**/*"],
10
+ "exclude": ["node_modules", "dist", ".framework"]
11
+ }
@@ -0,0 +1,68 @@
1
+ # {{projectName}} / {{appName}}
2
+
3
+ Server-rendered pages (template: **frontend-ssr**) — the **SSR** and **ISR**
4
+ render modes. Unlike a static site, these render on a runtime, so you serve
5
+ them with `voltro start` (or the cloud), NOT a bare CDN.
6
+
7
+ ## Boot
8
+
9
+ ```bash
10
+ pnpm install
11
+ pnpm --filter @{{projectName}}/{{appName}} dev # dev server with HMR
12
+
13
+ # Production behaviour (the SSR/ISR cache only runs here):
14
+ pnpm --filter @{{projectName}}/{{appName}} build
15
+ pnpm --filter @{{projectName}}/{{appName}} start # → voltro start
16
+ ```
17
+
18
+ Then watch the response headers (`curl -i`):
19
+
20
+ ```bash
21
+ curl -i http://localhost:5190/ | grep x-voltro # x-voltro-rendered-by: ssr
22
+ curl -i http://localhost:5190/feed | grep x-voltro # x-voltro-cache: MISS, then HIT
23
+ ```
24
+
25
+ ## What this template demonstrates
26
+
27
+ | Page | Mode | Concept |
28
+ |---|---|---|
29
+ | `/` | `ssr` | Fresh per request; `useServerRequest()` reads cookies + headers server-side |
30
+ | `/feed` | `isr` + `revalidate` + `tenantAware` | Cached HTML, revalidated on a window, per-tenant cache key |
31
+ | `/feed-swr` | `isr` + `staleWhileRevalidate` | Serve stale instantly, refresh in the background |
32
+
33
+ Response headers to look for: `x-voltro-rendered-by`, `x-voltro-cache`
34
+ (`HIT` / `MISS` / `STALE` / `BYPASS`), `x-voltro-cache-age-ms`.
35
+
36
+ ## Pulling fresh data from your api
37
+
38
+ This template is self-contained (loaders compute their own data), so it boots
39
+ with zero infra. To render from YOUR reactive backend, declare an `apis` entry
40
+ in `app.config.ts` and call `ctx.query` in an ssr/isr loader — it runs
41
+ server-side, invokes the api's rpc directly, and forwards the session cookie:
42
+
43
+ ```ts
44
+ // app.config.ts: apis: { app: { package: '@{{projectName}}/api' } }
45
+ export const loader: LoaderFn<Data> = async ({ query }) => ({
46
+ post: await query!('posts.get', { id: '…' }), // `query` is server-only
47
+ })
48
+ ```
49
+
50
+ Scaffold the pair in one command:
51
+
52
+ ```bash
53
+ voltro create-project {{projectName}} --api api-backend --web frontend-ssr
54
+ ```
55
+
56
+ ## Also available: CDC-driven cache invalidation
57
+
58
+ An ISR page can declare `export const cacheInvalidatesOn = ['todos']` — the
59
+ cached HTML drops the instant ANY write to those tables fires (needs an api
60
+ with CDC). It pairs with a long `revalidate` for "reactive cache" semantics:
61
+ cached arbitrarily long, fresh the moment the source data changes.
62
+
63
+ ## Don't ship these to a pure CDN
64
+
65
+ `voltro static deploy` will refuse — SSR/ISR pages need a runtime to render per
66
+ request. That gate is correct; serve them on `voltro start` / a container, and
67
+ push only your `static` pages to a CDN. `voltro deploy plan` tells you which
68
+ tier each page lands in.
@@ -0,0 +1,32 @@
1
+ // Web app for the {{projectName}} project — SERVER-RENDERED pages.
2
+ //
3
+ // Pages here use `renderMode: 'ssr'` (fresh per request) and `'isr'`
4
+ // (cached + revalidated). Unlike a static site, these need a runtime —
5
+ // run them with `voltro start` (NOT a bare CDN). The render-mode gate in
6
+ // `voltro static deploy` will (correctly) refuse to ship them to a pure CDN.
7
+ //
8
+ // Self-contained: no `apis` declared, so it boots with zero infra. To pull
9
+ // fresh data from YOUR reactive backend instead, add an `apis` entry and use
10
+ // `ctx.query(...)` in the loaders (see src/pages/index.tsx).
11
+ import { defineEnv, envVar } from '@voltro/env'
12
+
13
+ export const env = defineEnv({
14
+ VOLTRO_PUBLIC_APP_NAME: envVar.string({ access: 'public', default: '{{capProjectName}}' }),
15
+ })
16
+
17
+ export default {
18
+ type: 'web' as const,
19
+ name: '{{capProjectName}}{{capAppName}}',
20
+ port: {{port}},
21
+ theme: 'system' as const,
22
+ env,
23
+ // Bilingual by default. The framework auto-wires a cookie-driven
24
+ // <I18nProvider> from these codes and loads the matching
25
+ // `src/locales/<code>.ts` catalog — so `<T id="…" />` / `useT()` /
26
+ // `useLocale()` work app-wide (SSR + ISR too) with no manual setup. The
27
+ // <LocaleSwitcher> in the layout writes the `voltro:lang` cookie + reloads.
28
+ // Grow the app to more languages by adding a code here + a
29
+ // `src/locales/<code>.ts`.
30
+ locales: ['en', 'de'] as const,
31
+ defaultLocale: 'en' as const,
32
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@{{projectName}}/{{appName}}",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "voltro dev .",
8
+ "build": "voltro build .",
9
+ "start": "voltro start .",
10
+ "typecheck": "tsc --noEmit",
11
+ "test": "voltro test"
12
+ },
13
+ "dependencies": {
14
+ "@voltro/cli": "0.1.0",
15
+ "@voltro/client": "0.1.0",
16
+ "@voltro/env": "0.1.0",
17
+ "@voltro/i18n": "0.1.0",
18
+ "@voltro/ui-shadcn": "0.1.0",
19
+ "@voltro/web": "0.1.0",
20
+ "react": "^19.0.0",
21
+ "react-dom": "^19.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "@types/react": "^19.0.0",
25
+ "@types/react-dom": "^19.0.0",
26
+ "typescript": "^5.7.0",
27
+ "vitest": "^3.0.0"
28
+ }
29
+ }
@@ -0,0 +1,67 @@
1
+ /* Self-contained styles — plain CSS, no Tailwind / kit dependency. */
2
+
3
+ :root {
4
+ --bg: #ffffff;
5
+ --fg: #18181b;
6
+ --muted: #71717a;
7
+ --accent: #ea580c;
8
+ --border: #e4e4e7;
9
+ --code-bg: #f4f4f5;
10
+ }
11
+
12
+ :root.dark {
13
+ --bg: #0a0a0a;
14
+ --fg: #fafafa;
15
+ --muted: #a1a1aa;
16
+ --accent: #fb923c;
17
+ --border: #27272a;
18
+ --code-bg: #18181b;
19
+ }
20
+
21
+ * { box-sizing: border-box; }
22
+ html, body { margin: 0; min-height: 100vh; }
23
+
24
+ body {
25
+ background: var(--bg);
26
+ color: var(--fg);
27
+ font: 16px/1.6 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
28
+ }
29
+
30
+ main { max-width: 40rem; margin: 0 auto; padding: 2rem 1.25rem 5rem; }
31
+
32
+ nav.top {
33
+ display: flex;
34
+ gap: 1rem;
35
+ padding: 1rem 1.25rem;
36
+ border-bottom: 1px solid var(--border);
37
+ }
38
+ nav.top a { color: var(--muted); text-decoration: none; font-size: 0.95rem; }
39
+ nav.top a:hover { color: var(--accent); }
40
+
41
+ h1 { font-size: 1.6rem; margin: 0 0 0.25rem; }
42
+ .lead { color: var(--muted); margin: 0 0 1.5rem; }
43
+
44
+ .fields { list-style: none; padding: 0; margin: 1.5rem 0; }
45
+ .fields li { display: flex; justify-content: space-between; padding: 0.6rem 0; border-bottom: 1px solid var(--border); gap: 1rem; }
46
+ .fields .k { color: var(--muted); }
47
+ .fields .v { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; text-align: right; word-break: break-all; }
48
+
49
+ code { background: var(--code-bg); padding: 0.1rem 0.35rem; border-radius: 5px; font-size: 0.9em; }
50
+
51
+ .note {
52
+ margin-top: 2rem;
53
+ padding: 1rem;
54
+ border: 1px solid var(--border);
55
+ border-radius: 10px;
56
+ color: var(--muted);
57
+ font-size: 0.9rem;
58
+ }
59
+ .badge {
60
+ display: inline-block;
61
+ padding: 0.15rem 0.5rem;
62
+ border-radius: 999px;
63
+ font-size: 0.75rem;
64
+ font-weight: 600;
65
+ background: var(--accent);
66
+ color: #fff;
67
+ }
@@ -0,0 +1,41 @@
1
+ // German catalog. Mirrors every key in `en.ts` — `defineLocale<typeof en>()`
2
+ // fails the build if a key is missing or misspelled. Translate the prose only;
3
+ // keep ICU placeholders and rich tags (`<code>`) identical to `en.ts`.
4
+
5
+ import { defineLocale } from '@voltro/i18n'
6
+ import en from './en'
7
+
8
+ export default defineLocale<typeof en>()({
9
+ 'meta.ssr.title': '{{capProjectName}} — SSR (frisch pro Anfrage)',
10
+ 'meta.ssr.description': 'Bei jeder Anfrage serverseitig gerendert.',
11
+ 'meta.isr.title': '{{capProjectName}} — ISR (gecacht + revalidiert)',
12
+ 'meta.isr.description': 'Gecachtes HTML, in einem Zeitfenster revalidiert.',
13
+ 'meta.swr.title': '{{capProjectName}} — stale-while-revalidate',
14
+ 'meta.swr.description': 'Sofort veraltet ausliefern, im Hintergrund aktualisieren.',
15
+
16
+ 'nav.ssr': '/ (ssr)',
17
+ 'nav.isr': '/feed (isr)',
18
+ 'nav.swr': '/feed-swr (isr + swr)',
19
+ 'lang.label': 'Sprache',
20
+
21
+ 'field.renderedAt': 'Gerendert am',
22
+ 'field.nonce': 'Nonce',
23
+
24
+ 'ssr.badge': 'renderMode: ssr',
25
+ 'ssr.heading': 'Frisch bei jeder Anfrage',
26
+ 'ssr.lead': 'Aktualisieren — Zeitstempel und Nonce ändern sich jedes Mal.',
27
+ 'ssr.field.acceptLanguage': 'Accept-Language',
28
+ 'ssr.field.themeCookie': 'voltro:theme-Cookie',
29
+ 'ssr.note': 'SSR-Antworten tragen <code>x-voltro-rendered-by: ssr</code> und werden nie gecacht. Diese Seite braucht eine Laufzeit — liefere sie mit <code>voltro start</code> aus, nicht über ein reines CDN.',
30
+
31
+ 'isr.badge': 'renderMode: isr · revalidate 10s',
32
+ 'isr.heading': 'Gecacht, dann revalidiert',
33
+ 'isr.lead': 'Zweimal schnell aktualisieren — gleiche Nonce (Cache-HIT). 10s+ warten, aktualisieren — frische Nonce.',
34
+ 'isr.field.tenant': 'Mandant (aus x-tenant)',
35
+ 'isr.note': 'Beobachte die Response-Header: <code>x-voltro-cache: MISS</code> bei der ersten Anfrage (sie wurde gerendert), dann <code>HIT</code> innerhalb des Fensters, dann wieder <code>MISS</code>, nachdem es abgelaufen ist. Mit <code>tenantAware: true</code> enthält der Cache-Schlüssel <code>x-tenant</code>.',
36
+
37
+ 'swr.badge': 'renderMode: isr · revalidate 5s · swr 30s',
38
+ 'swr.heading': 'Stale-while-revalidate',
39
+ 'swr.lead': 'Zuerst frisch; HIT innerhalb von 5s; STALE (sofort) von 5–35s, während im Hintergrund aktualisiert wird.',
40
+ 'swr.note': 'Der Response-Header verrät, welcher Pfad die Seite ausgeliefert hat: <code>x-voltro-cache: MISS</code> → <code>HIT</code> → <code>STALE</code> (Hintergrund-Aktualisierung) → wieder <code>MISS</code> nach dem SWR-Fenster.',
41
+ })
@@ -0,0 +1,54 @@
1
+ // Base catalog — the source of truth for this app's UI strings. Every key here
2
+ // MUST be mirrored in `de.ts` (and any other locale); `defineLocale<typeof en>()`
3
+ // enforces that parity at build time, so a missing translation fails typecheck
4
+ // rather than silently falling back.
5
+ //
6
+ // Messages use ICU syntax: `{name}` placeholders and rich tags like
7
+ // `<code>…</code>` (rendered by passing a matching function to
8
+ // `<T values={{ code: (c) => <code>{c}</code> }} />`).
9
+
10
+ import { defineCatalog } from '@voltro/i18n'
11
+
12
+ export default defineCatalog({
13
+ // Browser tab titles + descriptions — locale-aware via each page's
14
+ // `meta({ locale })`. These are plain lookups (not ICU-formatted), so the
15
+ // `{{capProjectName}}` scaffold token is fine here.
16
+ 'meta.ssr.title': '{{capProjectName}} — SSR (fresh per request)',
17
+ 'meta.ssr.description': 'Server-rendered on every request.',
18
+ 'meta.isr.title': '{{capProjectName}} — ISR (cached + revalidated)',
19
+ 'meta.isr.description': 'Cached HTML, revalidated on a window.',
20
+ 'meta.swr.title': '{{capProjectName}} — stale-while-revalidate',
21
+ 'meta.swr.description': 'Serve stale instantly, refresh in the background.',
22
+
23
+ // ---- Layout shell (pages/layout.tsx) ----
24
+ // Route + render-mode labels — technical tokens, identical across locales.
25
+ 'nav.ssr': '/ (ssr)',
26
+ 'nav.isr': '/feed (isr)',
27
+ 'nav.swr': '/feed-swr (isr + swr)',
28
+ 'lang.label': 'Language',
29
+
30
+ // ---- Shared field labels ----
31
+ 'field.renderedAt': 'Rendered at',
32
+ 'field.nonce': 'Nonce',
33
+
34
+ // ---- SSR page (pages/index.tsx) ----
35
+ 'ssr.badge': 'renderMode: ssr',
36
+ 'ssr.heading': 'Fresh on every request',
37
+ 'ssr.lead': 'Refresh — the timestamp and nonce change each time.',
38
+ 'ssr.field.acceptLanguage': 'Accept-Language',
39
+ 'ssr.field.themeCookie': 'voltro:theme cookie',
40
+ 'ssr.note': 'SSR responses carry <code>x-voltro-rendered-by: ssr</code> and are never cached. This page needs a runtime — serve it with <code>voltro start</code>, not a bare CDN.',
41
+
42
+ // ---- ISR page (pages/feed.tsx) ----
43
+ 'isr.badge': 'renderMode: isr · revalidate 10s',
44
+ 'isr.heading': 'Cached, then revalidated',
45
+ 'isr.lead': 'Refresh twice fast — same nonce (cache HIT). Wait 10s+, refresh — fresh nonce.',
46
+ 'isr.field.tenant': 'Tenant (from x-tenant)',
47
+ 'isr.note': 'Watch the response headers: <code>x-voltro-cache: MISS</code> on the first request (it rendered), then <code>HIT</code> within the window, then <code>MISS</code> again after it expires. With <code>tenantAware: true</code> the cache key includes <code>x-tenant</code>.',
48
+
49
+ // ---- ISR + stale-while-revalidate page (pages/feed-swr.tsx) ----
50
+ 'swr.badge': 'renderMode: isr · revalidate 5s · swr 30s',
51
+ 'swr.heading': 'Stale-while-revalidate',
52
+ 'swr.lead': 'Fresh first; HIT within 5s; STALE (instant) from 5–35s while a background refresh runs.',
53
+ 'swr.note': 'The response header tells you which path served the page: <code>x-voltro-cache: MISS</code> → <code>HIT</code> → <code>STALE</code> (background refresh) → <code>MISS</code> again after the SWR window.',
54
+ } as const)
@@ -0,0 +1,16 @@
1
+ // Catalog lookup OUTSIDE React — for a page's `meta({ locale })` locale-aware
2
+ // <title> / <meta description>. This app is cookie-i18n (no `/<locale>` URL
3
+ // prefix), so @voltro/web hands `meta` the active locale from the `voltro:lang`
4
+ // cookie. Inside React, use `<T>` / `useT()` via the framework's auto-wired
5
+ // <I18nProvider> instead.
6
+
7
+ import en from './en'
8
+ import de from './de'
9
+
10
+ // Both catalogs share `en`'s keys (defineLocale enforces the mirror), so a
11
+ // known-key lookup returns `string` — not `string | undefined` — which is what
12
+ // `PageMeta.title` requires under exactOptionalPropertyTypes.
13
+ export type Messages = Record<keyof typeof en, string>
14
+
15
+ export const getCatalog = (locale?: string): Messages =>
16
+ (locale === 'de' ? de : en) as Messages