void 0.22.0 → 0.24.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 (301) hide show
  1. package/AGENTS_TEMPLATE.md +1 -1
  2. package/README.md +5 -1
  3. package/dist/{account-cmd-CjyxcGkM.mjs → account-cmd-vJhh5lrb.mjs} +5 -5
  4. package/dist/{scan-ClYmX3sa.mjs → application-analysis-BVsVqc11.mjs} +135 -18
  5. package/dist/application-routing-B7QEjqSR.mjs +27 -0
  6. package/dist/{auth-DLNN0D3Z.mjs → auth-CQkSDS50.mjs} +26 -96
  7. package/dist/auth-DX3JURcX.mjs +2 -0
  8. package/dist/{auth-link-BLO4ptzo.mjs → auth-link-D75t9wO2.mjs} +5 -5
  9. package/dist/{auth-router-ZUg9MF_U.mjs → auth-router-ClfhL1J7.mjs} +7 -7
  10. package/dist/{better-auth-shared-rsBGBvWJ.mjs → better-auth-shared-hy6RPh9W.mjs} +13 -2
  11. package/dist/{build-cmd-BxR5FROK.mjs → build-cmd-zMi1iFnS.mjs} +21 -9
  12. package/dist/{cache-D0sWhgKI.mjs → cache-ZtQmyxVV.mjs} +5 -5
  13. package/dist/{cancel-deploy-D4NUqFbi.mjs → cancel-deploy-Box0kkEV.mjs} +5 -5
  14. package/dist/{cf-access-P0iZnu0q.mjs → cf-access-BGe5sWXF.mjs} +4 -48
  15. package/dist/{cf-access-DRsQRe6k.mjs → cf-access-TWNzXltp.mjs} +3 -11
  16. package/dist/{cf-build-output-BJ6yGEIS.mjs → cf-build-output-BPqOT964.mjs} +2 -1
  17. package/dist/cf-build-output-_0HNWysu.mjs +2 -0
  18. package/dist/cli/cli.mjs +89 -461
  19. package/dist/cli/{cf-compat.mjs → cloudflare-operation-process.mjs} +454 -424
  20. package/dist/cli/env-schema-probe.d.mts +2 -1
  21. package/dist/cli/env-schema-probe.mjs +4 -4
  22. package/dist/client-B9UBI03V.mjs +2 -0
  23. package/dist/{client-BTZ3XkrB.mjs → client-DKAsFA4X.mjs} +161 -24
  24. package/dist/{cloudflare-auth-DQkqoMYa.mjs → cloudflare-auth-Qdc7tw8F.mjs} +41 -38
  25. package/dist/{cloudflare-cmd-BKlfGHAy.mjs → cloudflare-cmd-CmY8dGkd.mjs} +6 -6
  26. package/dist/cloudflare-config-Bktvwtpf.mjs +182 -0
  27. package/dist/{cloudflare-connect-Ctmrw579.mjs → cloudflare-connect-IiR3ZieC.mjs} +4 -4
  28. package/dist/{cloudflare-operations-BT6OWFBk.mjs → cloudflare-operations-BCdXSsmo.mjs} +1 -1
  29. package/dist/{cloudflare-operations-B9tzgjmf.mjs → cloudflare-operations-DzH-A966.mjs} +116 -172
  30. package/dist/{preset-UHj9ARyP.mjs → cloudflare-process-B-wekeR6.mjs} +93 -6
  31. package/dist/{config-VavjpDnp.d.mts → config-BMHb8RCj.d.mts} +1 -0
  32. package/dist/config-C_XRIPx2.mjs +89 -0
  33. package/dist/config-entry.d.mts +1 -1
  34. package/dist/{connect-Dg-WkW-C.mjs → connect-B-usTnlF.mjs} +9 -9
  35. package/dist/{create-project-l9J7pbtm.mjs → create-project-CYOOAYcn.mjs} +12 -12
  36. package/dist/{create-project-DdoqwFLF.mjs → create-project-FWbf5Olo.mjs} +1 -1
  37. package/dist/{db-gp2sCXyN.mjs → db-Ck2eZ2iB.mjs} +26 -26
  38. package/dist/{delete-TTedbH6B.mjs → delete-sK56qtzZ.mjs} +5 -5
  39. package/dist/{deploy-CH-o2CaZ.mjs → deploy-gCVaiJbS.mjs} +984 -616
  40. package/dist/{deploy-B19L2Bra.mjs → deploy-irP5q0-x.mjs} +1 -1
  41. package/dist/{domain-JRF59P_r.mjs → domain-DFfQE8jg.mjs} +6 -6
  42. package/dist/{email-Bo6G9LOZ.mjs → email-CdnhUHvJ.mjs} +15 -30
  43. package/dist/{env-BYOrWQnv.mjs → env-DmGdHi5i.mjs} +8 -8
  44. package/dist/{env-public-BxU_0yTL.d.mts → env-public-BX_r8HR6.d.mts} +1 -1
  45. package/dist/{env-types-C2_bIk_b.mjs → env-types-D5kds_OZ.mjs} +1 -1
  46. package/dist/{env-validation-BB4GkLxn.mjs → env-validation-C_8tPdhs.mjs} +20 -73
  47. package/dist/{env-validation-BXge7uyK.mjs → env-validation-zZOCcQVZ.mjs} +1 -1
  48. package/dist/{fetch-CXDChK7B.mjs → fetch-BIZJh7vR.mjs} +2 -2
  49. package/dist/{fetch-stream-AOByI7Ki.mjs → fetch-stream-IvCYKyQL.mjs} +24 -4
  50. package/dist/{gen-sCtlCOdA.mjs → gen-CshAkukR.mjs} +4 -4
  51. package/dist/gen-DvQTWzDU.mjs +2 -0
  52. package/dist/{github-cmd-0-7PexDq.mjs → github-cmd-DftuEvIt.mjs} +13 -13
  53. package/dist/{handler-HEcZsaij.d.mts → handler-CZ4nAylQ.d.mts} +1 -1
  54. package/dist/{headers-DWi2IXWx.mjs → headers-2rKda9Y6.mjs} +1 -1
  55. package/dist/{help-GKtwl07I.mjs → help-Dotbf6iz.mjs} +236 -750
  56. package/dist/help-mabuIV98.mjs +2 -0
  57. package/dist/{inbound-aVHEUhKo.mjs → inbound-fRkqcXaC.mjs} +1 -1
  58. package/dist/index.d.mts +1 -1
  59. package/dist/index.mjs +299 -1517
  60. package/dist/info-B97bTX9N.mjs +113 -0
  61. package/dist/{init-FZx3Elvz.mjs → init-BTQEZZGJ.mjs} +61 -27
  62. package/dist/limits-Bq5LG8Id.d.mts +27 -0
  63. package/dist/limits-Cjuk2VPm.mjs +68 -0
  64. package/dist/{link-BrQfb_CU.mjs → link-B46sYH0K.mjs} +6 -6
  65. package/dist/{list-D44jmIAM.mjs → list-BnPrIsU_.mjs} +6 -6
  66. package/dist/{live-CKJlvlNp.d.mts → live-Chw1eIMv.d.mts} +1 -1
  67. package/dist/{local-d1-Bg9OzEEO.mjs → local-d1-2CMnpuW_.mjs} +2 -2
  68. package/dist/log-vqY3pqwI.mjs +29 -0
  69. package/dist/{login-CAsAsQ-_.mjs → login-BuiMyUrx.mjs} +8 -8
  70. package/dist/login-DIy9Sb-U.mjs +2 -0
  71. package/dist/{logs-BjKvFnVM.mjs → logs-CZG9d-ic.mjs} +10 -11
  72. package/dist/migrate-BCiJ8w0f.mjs +2 -0
  73. package/dist/{migrate-BPITvDJN.mjs → migrate-q4_njtaW.mjs} +4 -3
  74. package/dist/{node-Dt7z256D.mjs → node-BkyRWRx8.mjs} +1 -1
  75. package/dist/operator-args-B3BTmSoi.mjs +697 -0
  76. package/dist/{operator-auth-8KnOVXVd.mjs → operator-auth-7erYc6Lt.mjs} +2 -2
  77. package/dist/{operator-client-DUwumHpQ.mjs → operator-client-CpHjTd0t.mjs} +3 -3
  78. package/dist/{operator-cmd-BK5CCiT9.mjs → operator-cmd-DGqPJUD3.mjs} +70 -24
  79. package/dist/{output-Dm_A4Tbv.mjs → output-CbM85T4k.mjs} +18 -10
  80. package/dist/pages/client.d.mts +34 -2
  81. package/dist/pages/client.mjs +59 -3
  82. package/dist/pages/index.d.mts +1 -1
  83. package/dist/pages/index.mjs +2 -2
  84. package/dist/pages/islands-plugin.mjs +1 -1
  85. package/dist/pages/protocol.d.mts +2 -2
  86. package/dist/pages/protocol.mjs +2 -308
  87. package/dist/{parse-filename-DioPHiR9.mjs → parse-filename-CUbj-1MP.mjs} +35 -1
  88. package/dist/plan-D1Q5rf-r.mjs +2 -0
  89. package/dist/plan-NPpwZ_kc.mjs +58 -0
  90. package/dist/platform-args-3k8X9-H_.mjs +514 -0
  91. package/dist/platform-args-DdnM6WIf.mjs +2 -0
  92. package/dist/{platform-auth-config-BlN8xTdD.mjs → platform-auth-config-DDrxUy4m.mjs} +6 -6
  93. package/dist/{platform-auth-protection-7d5aV2Jg.mjs → platform-auth-protection-BLadnnct.mjs} +8 -8
  94. package/dist/{platform-auth-recovery-Dxij8ZbR.mjs → platform-auth-recovery-CmCzX2Fl.mjs} +6 -6
  95. package/dist/{platform-cmd-B3hwKrFK.mjs → platform-cmd-DMDEc9uS.mjs} +29 -8
  96. package/dist/{platform-cmd-E0FuL212.mjs → platform-cmd-pMTRhvYs.mjs} +1 -1
  97. package/dist/{platform-domain-D6Xcy9ZX.mjs → platform-domain-Di6EYrQl.mjs} +5 -5
  98. package/dist/{platform-lifecycle-k0E0xoxx.mjs → platform-lifecycle-BBoNzojY.mjs} +1541 -572
  99. package/dist/{platform-lifecycle-DMh_qrry.mjs → platform-lifecycle-BFdSi9Qt.mjs} +1 -1
  100. package/dist/{platform-management-Brz_BDiT.mjs → platform-management-CWOQOWXm.mjs} +10 -7
  101. package/dist/{platform-management-DOtss0BN.mjs → platform-management-DG47jys8.mjs} +1 -1
  102. package/dist/platform-plans-config-Vl9BP3H4.mjs +359 -0
  103. package/dist/{platform-recovery-BvtcXON5.mjs → platform-recovery-BJnQJEtQ.mjs} +4 -4
  104. package/dist/{platform-registry-QBa4DK32.mjs → platform-registry-DkPPXfp_.mjs} +2 -2
  105. package/dist/{plugin-inference-BMfKRSqE.mjs → plugin-inference-CXWnn79A.mjs} +174 -64
  106. package/dist/{prepare-C-6YZyyg.mjs → prepare-CBLT3CHH.mjs} +3 -3
  107. package/dist/prepare-CnjcTV2s.mjs +2 -0
  108. package/dist/{prepare-CRhJbVrG.mjs → prepare-DnaKBi--.mjs} +5 -21
  109. package/dist/{project-C0Fqu05O.mjs → project-DKG5Ra8p.mjs} +15 -82
  110. package/dist/project-DsblYifa.mjs +2 -0
  111. package/dist/{project-cmd-BZLCqOqw.mjs → project-cmd-DxnXstAq.mjs} +19 -19
  112. package/dist/{project-team-BvgM0WoX.mjs → project-team-BmHcaALJ.mjs} +5 -5
  113. package/dist/{project-token-l5DqK6Az.mjs → project-token-GionZlBI.mjs} +5 -5
  114. package/dist/{project-zero-trust-v6Mvpp8y.mjs → project-zero-trust-JLCjVQA7.mjs} +5 -5
  115. package/dist/prompts-2TGE6oXx.mjs +2 -0
  116. package/dist/prompts-BNUoTiaf.mjs +2044 -0
  117. package/dist/{protocol-BBa6cstI.d.mts → protocol-CjF_iI9X.d.mts} +2 -2
  118. package/dist/protocol-U7bfjHmA.mjs +331 -0
  119. package/dist/{provision-Fr9pRqce.mjs → provision-CVku1JFU.mjs} +1 -1
  120. package/dist/{provision-C4IGqkBf.mjs → provision-CaoxO_U7.mjs} +90 -199
  121. package/dist/{requests-DN-BbNiM.mjs → requests-BOjIVAeF.mjs} +5 -5
  122. package/dist/resource-name-C7LVpcRm.mjs +11 -0
  123. package/dist/{rollback-D7rzSaZM.mjs → rollback-CwR3pLj3.mjs} +6 -6
  124. package/dist/route-url-CG7U-cRN.mjs +15 -0
  125. package/dist/{runner-B8wXwWlo.mjs → runner-CXA9Fh8h.mjs} +1 -1
  126. package/dist/{runner-p-dMs2UN.mjs → runner-Ol0TNjk6.mjs} +2 -2
  127. package/dist/runtime/ai.d.mts +12 -8
  128. package/dist/runtime/ai.mjs +87 -22
  129. package/dist/runtime/better-auth-mysql.mjs +1 -1
  130. package/dist/runtime/better-auth-pg.mjs +1 -1
  131. package/dist/runtime/better-auth.mjs +1 -1
  132. package/dist/runtime/client-react.mjs +2 -2
  133. package/dist/runtime/client-solid.mjs +2 -2
  134. package/dist/runtime/client-svelte.mjs +2 -2
  135. package/dist/runtime/client-vue.mjs +2 -2
  136. package/dist/runtime/client.mjs +2 -2
  137. package/dist/runtime/durable.d.mts +3 -1
  138. package/dist/runtime/durable.mjs +4 -1
  139. package/dist/runtime/email/testing.mjs +2 -2
  140. package/dist/runtime/email.mjs +1 -1
  141. package/dist/runtime/env-public.d.mts +1 -1
  142. package/dist/runtime/fetch-stream.mjs +1 -1
  143. package/dist/runtime/fetch.mjs +1 -1
  144. package/dist/runtime/handler.d.mts +1 -1
  145. package/dist/runtime/kv.mjs +0 -1
  146. package/dist/runtime/limits.d.mts +2 -0
  147. package/dist/runtime/limits.mjs +2 -0
  148. package/dist/runtime/live-client.d.mts +1 -1
  149. package/dist/runtime/live-server.mjs +25 -16
  150. package/dist/runtime/live.d.mts +1 -1
  151. package/dist/runtime/migration-handler.mjs +62 -42
  152. package/dist/runtime/remote/index.mjs +2 -2
  153. package/dist/runtime/route-url.d.mts +4 -0
  154. package/dist/runtime/route-url.mjs +2 -0
  155. package/dist/runtime/routing.d.mts +180 -0
  156. package/dist/runtime/routing.mjs +1082 -0
  157. package/dist/runtime/sandbox-container.d.mts +1 -1
  158. package/dist/runtime/sandbox-container.mjs +1 -1
  159. package/dist/runtime/sandbox.d.mts +3 -3
  160. package/dist/runtime/sandbox.mjs +75 -45
  161. package/dist/runtime/sse.mjs +1 -1
  162. package/dist/runtime/validator.d.mts +1 -1
  163. package/dist/runtime/ws-server.d.mts +4 -2
  164. package/dist/runtime/ws-server.mjs +27 -2
  165. package/dist/runtime/ws.d.mts +2 -2
  166. package/dist/runtime/ws.mjs +8 -6
  167. package/dist/{sandbox-qpNBT8a3.d.mts → sandbox-XZAqzFlG.d.mts} +11 -8
  168. package/dist/{sandbox-container-DdNEBfCc.d.mts → sandbox-container-Bo0eiFKz.d.mts} +2 -1
  169. package/dist/{sandbox-container-4fdqLnyb.mjs → sandbox-container-C6ItmVuN.mjs} +4 -2
  170. package/dist/{scan-4tfN-PSn.mjs → scan-C7okrLyM.mjs} +4 -35
  171. package/dist/{secret-BOtOl_cb.mjs → secret-ByWJWBUG.mjs} +7 -7
  172. package/dist/{skills-D1II1Juz.mjs → skills-C1PlclPt.mjs} +1 -1
  173. package/dist/{sse-BaC1jXko.mjs → sse-CQNaDFFV.mjs} +6 -3
  174. package/dist/{subcommand-prompt-CY1C4fvl.mjs → subcommand-prompt-klFCfcor.mjs} +40 -32
  175. package/dist/validate-Dq_L3s0S.mjs +2 -0
  176. package/dist/{validate-CIUwFpjB.mjs → validate-ctOrgiS3.mjs} +2 -1
  177. package/dist/{wrangler-DQF1vKyf.mjs → wrangler-7K-bW_DL.mjs} +8 -239
  178. package/dist/{ws-BoY7vQML.d.mts → ws-CL1w7GXU.d.mts} +13 -2
  179. package/package.json +16 -10
  180. package/skills/migrate-vite-cloudflare-to-void/SKILL.md +34 -157
  181. package/skills/void/SKILL.md +55 -135
  182. package/skills/void/docs/guide/ai.md +94 -84
  183. package/skills/void/docs/guide/app-types.md +3 -32
  184. package/skills/void/docs/guide/auth.md +12 -116
  185. package/skills/void/docs/guide/database/d1.md +9 -54
  186. package/skills/void/docs/guide/database/mysql.md +1 -1
  187. package/skills/void/docs/guide/database/postgresql.md +5 -26
  188. package/skills/void/docs/guide/database.md +23 -75
  189. package/skills/void/docs/guide/deployment.md +48 -112
  190. package/skills/void/docs/guide/durable-state.md +43 -18
  191. package/skills/void/docs/guide/edge/headers.md +4 -48
  192. package/skills/void/docs/guide/edge/prerendering.md +5 -20
  193. package/skills/void/docs/guide/edge/redirects.md +11 -64
  194. package/skills/void/docs/guide/edge/revalidation.md +5 -18
  195. package/skills/void/docs/guide/edge/rewrites.md +56 -284
  196. package/skills/void/docs/guide/edge/static-assets.md +22 -72
  197. package/skills/void/docs/guide/email/domains.md +116 -0
  198. package/skills/void/docs/guide/email/receiving.md +139 -0
  199. package/skills/void/docs/guide/email/sending.md +231 -0
  200. package/skills/void/docs/guide/email.md +13 -619
  201. package/skills/void/docs/guide/env-migration.md +11 -11
  202. package/skills/void/docs/guide/env-vars.md +9 -29
  203. package/skills/void/docs/guide/index.md +0 -15
  204. package/skills/void/docs/guide/jobs.md +3 -18
  205. package/skills/void/docs/guide/kv.md +5 -11
  206. package/skills/void/docs/guide/live.md +5 -56
  207. package/skills/void/docs/guide/pages-routing/actions-and-forms.md +78 -125
  208. package/skills/void/docs/guide/pages-routing/head.md +10 -10
  209. package/skills/void/docs/guide/pages-routing/islands.md +6 -36
  210. package/skills/void/docs/guide/pages-routing/layouts.md +6 -128
  211. package/skills/void/docs/guide/pages-routing/loaders.md +3 -19
  212. package/skills/void/docs/guide/pages-routing/markdown.md +13 -171
  213. package/skills/void/docs/guide/pages-routing/overview.md +7 -17
  214. package/skills/void/docs/guide/pages-routing/view-transitions.md +1 -1
  215. package/skills/void/docs/guide/platform/administration/access.md +1 -4
  216. package/skills/void/docs/guide/platform/administration/email.md +35 -8
  217. package/skills/void/docs/guide/platform/administration/operations.md +26 -4
  218. package/skills/void/docs/guide/platform/administration/plans.md +126 -0
  219. package/skills/void/docs/guide/platform/administration/projects.md +5 -2
  220. package/skills/void/docs/guide/platform/administration/zero-trust.md +49 -160
  221. package/skills/void/docs/guide/platform/development/runtime.md +3 -13
  222. package/skills/void/docs/guide/platform/development/schema-ci.md +0 -58
  223. package/skills/void/docs/guide/platform/installation/ci.md +1 -1
  224. package/skills/void/docs/guide/platform/installation/credentials.md +15 -6
  225. package/skills/void/docs/guide/platform/installation/domains.md +35 -2
  226. package/skills/void/docs/guide/platform/installation/first-deployment.md +4 -2
  227. package/skills/void/docs/guide/platform/installation/maintenance.md +15 -1
  228. package/skills/void/docs/guide/platform/installation/prerequisites.md +24 -18
  229. package/skills/void/docs/guide/platform/installation/setup.md +88 -14
  230. package/skills/void/docs/guide/platform-administration.md +1 -0
  231. package/skills/void/docs/guide/queues.md +7 -9
  232. package/skills/void/docs/guide/quickstart.md +38 -37
  233. package/skills/void/docs/guide/remote-dev.md +5 -10
  234. package/skills/void/docs/guide/sandboxes.md +29 -21
  235. package/skills/void/docs/guide/server-routing.md +9 -72
  236. package/skills/void/docs/guide/sse.md +4 -18
  237. package/skills/void/docs/guide/ssg.md +3 -15
  238. package/skills/void/docs/guide/ssr.md +14 -62
  239. package/skills/void/docs/guide/storage.md +9 -4
  240. package/skills/void/docs/guide/type-safety.md +3 -14
  241. package/skills/void/docs/guide/typed-fetch.md +3 -7
  242. package/skills/void/docs/guide/websockets.md +68 -40
  243. package/skills/void/docs/integrations/agents.md +3 -3
  244. package/skills/void/docs/integrations/cloudflare.md +85 -316
  245. package/skills/void/docs/integrations/frameworks/analog.md +5 -64
  246. package/skills/void/docs/integrations/frameworks/astro.md +4 -73
  247. package/skills/void/docs/integrations/frameworks/nuxt.md +5 -62
  248. package/skills/void/docs/integrations/frameworks/overview.md +11 -54
  249. package/skills/void/docs/integrations/frameworks/react-router.md +5 -60
  250. package/skills/void/docs/integrations/frameworks/sveltekit.md +6 -65
  251. package/skills/void/docs/integrations/frameworks/tanstack-start.md +4 -62
  252. package/skills/void/docs/integrations/nodejs-bun-deno.md +5 -69
  253. package/skills/void/docs/reference/api/auth.md +156 -0
  254. package/skills/void/docs/reference/api/client.md +87 -0
  255. package/skills/void/docs/reference/api/database.md +95 -0
  256. package/skills/void/docs/reference/api/durable.md +46 -0
  257. package/skills/void/docs/reference/api/env.md +50 -0
  258. package/skills/void/docs/reference/api/handlers.md +254 -0
  259. package/skills/void/docs/reference/api/pages.md +241 -0
  260. package/skills/void/docs/reference/api/plugin.md +39 -0
  261. package/skills/void/docs/reference/api/resources.md +109 -0
  262. package/skills/void/docs/reference/api/rewrites.md +76 -0
  263. package/skills/void/docs/reference/api/types.md +92 -0
  264. package/skills/void/docs/reference/api.md +56 -1218
  265. package/skills/void/docs/reference/cli/auth.md +89 -0
  266. package/skills/void/docs/reference/cli/database.md +128 -0
  267. package/skills/void/docs/reference/cli/deploy.md +105 -0
  268. package/skills/void/docs/reference/cli/domains.md +41 -0
  269. package/skills/void/docs/reference/cli/email.md +129 -0
  270. package/skills/void/docs/reference/cli/generate.md +116 -0
  271. package/skills/void/docs/reference/cli/github.md +189 -0
  272. package/skills/void/docs/reference/cli/platform-config.md +92 -0
  273. package/skills/void/docs/reference/cli/platform-email.md +81 -0
  274. package/skills/void/docs/reference/cli/platform-installation.md +142 -0
  275. package/skills/void/docs/reference/cli/platform-operations.md +90 -0
  276. package/skills/void/docs/reference/cli/platform-users.md +89 -0
  277. package/skills/void/docs/reference/cli/platform-zero-trust.md +59 -0
  278. package/skills/void/docs/reference/cli/platform.md +70 -0
  279. package/skills/void/docs/reference/cli/project.md +214 -0
  280. package/skills/void/docs/reference/cli/secrets.md +76 -0
  281. package/skills/void/docs/reference/cli/setup.md +70 -0
  282. package/skills/void/docs/reference/cli.md +32 -1682
  283. package/skills/void/docs/reference/config.md +12 -18
  284. package/skills/void/docs/reference/resource-inference.md +3 -58
  285. package/skills/void/docs/reference/structure.md +14 -41
  286. package/dist/auth-CZuiVsFh.mjs +0 -2
  287. package/dist/canonical-json-DuDiiUsQ.mjs +0 -13
  288. package/dist/client-Czz8o5jP.mjs +0 -2
  289. package/dist/dist-BuDuKZJv.mjs +0 -2
  290. package/dist/dist-CTBk70IR.mjs +0 -1310
  291. package/dist/gen-CNJ62MM7.mjs +0 -2
  292. package/dist/help-CmZzxUba.mjs +0 -2
  293. package/dist/log-ChfPKsVd.mjs +0 -26
  294. package/dist/login-CGcRKEoi.mjs +0 -2
  295. package/dist/migrate-CYfbKkXh.mjs +0 -2
  296. package/dist/plan-BEZ8VJW0.mjs +0 -256
  297. package/dist/plan-DpuOr14e.mjs +0 -2
  298. package/dist/prepare-Bm3iq-u4.mjs +0 -2
  299. package/dist/project-BuUwfj6f.mjs +0 -2
  300. package/dist/validate-EKmJWxmy.mjs +0 -2
  301. /package/dist/cli/{cf-compat.d.mts → cloudflare-operation-process.d.mts} +0 -0
@@ -56,36 +56,9 @@ Void asks you to choose Vite+ or Vite, a UI framework, a starter, and a deployme
56
56
 
57
57
  With pnpm, you can start with `pnpm create void my-app`. It configures native build permissions before installing Void.
58
58
 
59
- If a manual pnpm install reports blocked build scripts, run `pnpm approve-builds` for `esbuild`, `sharp`, and `workerd`. Set `better-sqlite3: false` in `pnpm-workspace.yaml`'s `allowBuilds`; Void uses its bundled binaries. Setup updates the pnpm lockfile, including in CI. Later installs can use `pnpm install --frozen-lockfile`.
60
-
61
59
  The examples below use `void` for brevity. Outside package scripts, run the local binary with `npx void`, `pnpm void`, `yarn void`, or `bunx void`. Keep Void installed in the project so the CLI and app use the same version.
62
60
 
63
- ## Using with Coding Agents
64
-
65
- `void init` detects your coding agent and installs its instructions and skills. If detection fails, choose an agent when prompted. In agents that support it, load the `/void` skill and describe the app you want to build. See [Coding Agents](../integrations/agents) for setup details.
66
-
67
- ## Meta Frameworks
68
-
69
- Use Void's [Pages routing](./pages-routing/overview) or keep a framework such as TanStack Start, React Router, or SvelteKit. Follow the [framework guides](../integrations/frameworks/overview) for setup.
70
-
71
- ## Adding to an Existing Vite App
72
-
73
- Install Void using the package manager command [above](#start-in-an-empty-directory).
74
-
75
- Enable the plugin in `vite.config.ts`:
76
-
77
- ```ts
78
- import { defineConfig } from 'vite';
79
- import { voidPlugin } from 'void';
80
-
81
- export default defineConfig({
82
- plugins: [voidPlugin()],
83
- });
84
- ```
85
-
86
- Then run `void init` with your package manager to configure the remaining project files. Existing compatibility dates are preserved; new projects use Void's tested Workers compatibility date.
87
-
88
- ## Once You Have a Working App
61
+ ## Run and deploy
89
62
 
90
63
  ### 1. Edit the generated API route
91
64
 
@@ -110,32 +83,60 @@ Then visit:
110
83
  - App: `http://localhost:5173`
111
84
  - API route: `http://localhost:5173/api/hello`
112
85
 
113
- ### 3. Choose where to deploy
86
+ ### 3. Deploy
114
87
 
115
- If you chose a deployment target during setup, you're ready. If you skipped it, run `void init` again or choose Cloudflare for the first deploy:
88
+ If you chose a deployment target during setup, run:
89
+
90
+ ```sh
91
+ void deploy
92
+ ```
93
+
94
+ If you skipped deployment setup, select your Cloudflare account for the first deploy:
116
95
 
117
96
  ```sh
118
97
  void deploy --platform cloudflare
119
98
  ```
120
99
 
121
- Void opens your browser to sign in when needed. To use your team's platform, connect using the API URL from your administrator:
100
+ Void opens your browser to sign in when needed. To use your team's platform, connect using the API URL from your administrator, then link a project and deploy:
122
101
 
123
102
  ```sh
124
103
  void connect https://platform.example.com
125
104
  void project link
105
+ void deploy
126
106
  ```
127
107
 
128
- ### 4. Deploy
108
+ Void builds the app, provisions its resources, applies pending migrations, and prints the deployed URL. If a production secret is missing, [set it](./env-vars.md) and deploy again. Later deploys use the saved target.
129
109
 
130
- With your target configured, run:
110
+ See [Deployment](./deployment.md) for CI setup and rollback.
131
111
 
132
- ```sh
133
- void deploy
112
+ ## Using with Coding Agents
113
+
114
+ `void init` detects your coding agent and installs its instructions and skills. If no agent is detected, use the bundled docs linked in `AGENTS.md`. In agents that support it, load the `/void` skill and describe the app you want to build. See [Coding Agents](../integrations/agents) for setup details.
115
+
116
+ ## Meta Frameworks
117
+
118
+ Use Void's [Pages routing](./pages-routing/overview) or keep a framework such as TanStack Start, React Router, or SvelteKit. Follow the [framework guides](../integrations/frameworks/overview) for setup.
119
+
120
+ ## Adding to an Existing Vite App
121
+
122
+ Install Void using the package manager command [above](#start-in-an-empty-directory).
123
+
124
+ Enable the plugin in `vite.config.ts`:
125
+
126
+ ```ts
127
+ import { defineConfig } from 'vite';
128
+ import { voidPlugin } from 'void';
129
+
130
+ export default defineConfig({
131
+ plugins: [voidPlugin()],
132
+ });
134
133
  ```
135
134
 
136
- Void builds the app, provisions the resources it uses, applies pending migrations, and prints the deployed URL. If it reports a missing production secret, [configure that secret](./env-vars.md) and deploy again.
135
+ Then run `void init` with your package manager to configure the remaining project files.
136
+
137
+ ## Troubleshooting pnpm installs
137
138
 
138
- Subsequent deploys use the same target. See [Deployment](./deployment.md) for CI setup, migrations, and rollback. To generate a supported push-to-deploy workflow, run `void init --github`.
139
+ If a manual pnpm install reports blocked build scripts, run `pnpm approve-builds` for `esbuild`, `sharp`, and `workerd`. Set `better-sqlite3: false` in `pnpm-workspace.yaml`'s `allowBuilds`; Void uses its bundled binaries.
139
140
 
140
141
  ## Next steps
141
142
 
@@ -42,18 +42,14 @@ VOID_REMOTE=1 vite dev
42
42
  | R2 | Local file-backed R2 | Remote R2 bucket |
43
43
  | AI | Always proxied | Always proxied |
44
44
 
45
- AI inference is always routed through the proxy regardless of remote mode. There is no local AI emulation.
45
+ AI requests use your platform’s account and allowance in both local and remote mode. There is no local AI simulator.
46
46
 
47
- ## How It Works
48
-
49
- In remote mode, binding calls go through your platform's proxy, authenticated with your login token. The proxy uses the linked project's configuration to choose the D1 database, KV namespace, or R2 bucket.
50
-
51
- You don't need to change any code. Imports like `import { db } from "void/db"` and direct binding access via `c.env.KV` both work transparently.
47
+ ## Checking Remote Mode
52
48
 
53
49
  When the dev server starts with remote mode active, it prints:
54
50
 
55
51
  ```
56
- ⚡ Remote bindings active (my-project.void.app)
52
+ ⚡ Remote bindings active (my-project.apps.example.com)
57
53
  DB → remote D1
58
54
  KV → remote KV
59
55
  STORAGE → remote R2
@@ -63,7 +59,6 @@ When the dev server starts with remote mode active, it prints:
63
59
 
64
60
  - **Network latency:** each binding call makes a network request, so responses may be slower than local development.
65
61
  - **R2 multipart uploads:** `createMultipartUpload()` and `resumeMultipartUpload()` are not supported in remote mode.
66
- - **R2 conditional writes:** `put(..., { onlyIf })` requires a current Void platform and an active deployment with the native remote-binding handler. Update the platform and redeploy the project if this operation is unavailable. Failed preconditions return `null`; Void never retries a conditional write as an unconditional REST upload.
62
+ - **R2 conditional writes:** `put(..., { onlyIf })` requires a current Void platform and an active deployment with the native remote-binding handler. Update the platform and redeploy the project if this operation is unavailable. Failed preconditions return `null`.
67
63
  - **D1 dump:** `db.dump()` is not supported in remote mode.
68
- - **D1 batch compatibility:** `db.batch()` requires an active deployment with the native remote-binding handler. Void does not split a batch into REST calls because that would lose D1's atomic all-or-nothing behavior.
69
- - **Writes affect real data:** remote mode connects to your actual deployed resources. Inserts, updates, and deletes are real, so use it carefully or point it at a staging project.
64
+ - **D1 batches:** `db.batch()` requires an updated platform and project deployment.
@@ -12,13 +12,13 @@ import { getSandbox } from 'void/sandbox';
12
12
 
13
13
  export const POST = defineHandler(async (c) => {
14
14
  const sandbox = await getSandbox('default');
15
- const process = await sandbox.exec(['node', '--version']);
16
- const result = await process.output();
17
-
18
- return c.json({
19
- exitCode: result.exitCode,
20
- stdout: new TextDecoder().decode(result.stdout),
21
- stderr: new TextDecoder().decode(result.stderr),
15
+ return sandbox.run(['node', '--version']).match({
16
+ ok: (result) =>
17
+ c.json({
18
+ exitCode: result.exitCode,
19
+ stdout: new TextDecoder().decode(result.stdout),
20
+ }),
21
+ limited: (limit) => limit.response({ message: 'Execution is temporarily unavailable.' }),
22
22
  });
23
23
  });
24
24
  ```
@@ -27,7 +27,7 @@ Importing from `void/sandbox` enables the required resources. Local development,
27
27
 
28
28
  ## Configuration
29
29
 
30
- Most apps do not need config. The default binding is `SANDBOX`, the Durable Object class is `SandboxV1`, and the default environment provides Node.js 24 on Debian Trixie. Local development and native deploys build Void's packaged Dockerfile, so Docker must be running. Managed platform deploys use Cloudflare's managed Node.js image.
30
+ The default environment provides Node.js 24 on Debian Trixie. Local development and native deploys need Docker running. Managed platform deploys use Cloudflare's managed Node.js image.
31
31
 
32
32
  Use `void.config.ts` when you need a custom image or container size:
33
33
 
@@ -62,7 +62,7 @@ WORKDIR /workspace
62
62
  CMD ["sleep", "infinity"]
63
63
  ```
64
64
 
65
- For a managed platform, push your custom image to that platform account's Cloudflare registry and set `platformImage` to its digest-pinned reference. If `image` is already a Cloudflare registry reference, it also becomes the default `platformImage`. External registry references and mutable tags are not supported by the new scheduling policy. See [Cloudflare's image management guide](https://developers.cloudflare.com/containers/guides/image-management/#push-images-to-the-cloudflare-registry).
65
+ For a managed platform, push your custom image to that platform account's Cloudflare registry and set `platformImage` to its digest-pinned reference. If `image` is already a Cloudflare registry reference, it also becomes the default `platformImage`. External registries and mutable tags are not supported. See [Cloudflare's image management guide](https://developers.cloudflare.com/containers/guides/image-management/#push-images-to-the-cloudflare-registry).
66
66
 
67
67
  ## Runtime API
68
68
 
@@ -75,37 +75,45 @@ const sandbox = await getSandbox(`user-${user.id}`, {
75
75
  inactivityTimeoutMs: 10 * 60 * 1000,
76
76
  enableInternet: false,
77
77
  });
78
- await sandbox.files.writeFile('/workspace/input.txt', 'hello');
79
- const process = await sandbox.exec(['cat', '/workspace/input.txt'], {
80
- signal: AbortSignal.timeout(5_000),
81
- });
82
- const { stdout, exitCode } = await process.output();
83
- const text = new TextDecoder().decode(stdout);
78
+ const response = await sandbox
79
+ .run(['node', '--version'], {
80
+ signal: AbortSignal.timeout(5_000),
81
+ })
82
+ .match({
83
+ ok: (result) => Response.json({ exitCode: result.exitCode }),
84
+ limited: (limit) => limit.response(),
85
+ });
84
86
  ```
85
87
 
86
88
  Commands take an executable and arguments as an array. For shell syntax, explicitly run `['sh', '-c', command]`. Execution options include `cwd` (default `/workspace`), `env`, `user`, `signal`, `pty`, `stdin`, `stdout`, and `stderr`.
87
89
 
88
- `exec()` returns a process immediately after it starts. Read its `stdout` and `stderr` streams, or call `output()` to collect both as `ArrayBuffer`s together with the exit code. `exitCode` is a promise; `kill(signal?)` and `resize(cols, rows)` are asynchronous. Use `stdin: 'pipe'` to receive a writable `stdin` stream. A process can continue running after a request returns, until it exits or its container stops. When streaming output from a long command, await `process.exitCode` alongside consuming its streams. This keeps an explicit command wait active even while the command produces no output; unattended background commands can stop when the Sandbox becomes idle.
90
+ `run()` collects command output and handles limits throughout execution with one required `.match({ ok, limited })`. Both handlers are required. Other failures still reject.
89
91
 
90
- File operations live under `sandbox.files`: `readFile`, `writeFile`, `stat`, `lstat`, `readDirectory`, `mkdir`, `rename`, and `remove`. `readFile()` returns a streaming `Response`; use `.text()`, `.arrayBuffer()`, or `.body`. `writeFile()` accepts text, binary data, or a byte stream. Relative file paths require an explicit `cwd` option.
92
+ `exec()` returns a lazy operation yielding a process through its `ok` handler. Use `output()` to collect `stdout` and `stderr` as `ArrayBuffer`s with the exit code, or read the streams and match `exitCode`. Both `output()` and `exitCode` require their own `.match({ ok, limited })`. Matching `exitCode` keeps a long command active during pauses in its output; unattended background commands can stop when the Sandbox becomes idle.
91
93
 
92
- To reach a server inside the container, call `sandbox.fetch(port, new Request(url))`. `sandbox.running()` checks whether the container is running; `sandbox.destroy()` stops it.
94
+ Use `stdin: 'pipe'` for a writable input stream. `kill(signal?)` stops a process, and `resize(cols, rows)` resizes its terminal.
95
+
96
+ File operations live under `sandbox.files`: `readFile`, `writeFile`, `stat`, `lstat`, `readDirectory`, `mkdir`, `rename`, and `remove`. Each file operation requires `.match({ ok, limited })`. `readFile()` yields a streaming `Response` to `ok`; use `.text()`, `.arrayBuffer()`, or `.body`. `writeFile()` accepts text, binary data, or a byte stream. Relative file paths require an explicit `cwd` option.
97
+
98
+ To reach a server inside the container, call `sandbox.fetch(port, new Request(url)).match({ ok, limited })`. `sandbox.running()` checks whether the container is running; `sandbox.destroy()` stops it.
93
99
 
94
100
  `getSandbox()` options include `inactivityTimeoutMs` (default ten minutes, maximum six hours), `enableInternet` (default `false`), and string `labels`. Internet access and labels take effect on the next container start. `binding` selects a custom native binding; managed platforms use the configured binding.
95
101
 
96
102
  For code that runs on both deployment targets, use `getSandbox()`. Direct access through `c.env.SANDBOX` is available only on local and native Cloudflare deployments.
97
103
 
104
+ The `limited` handler receives `resource: 'sandbox'`, a `reason` of `concurrency` or `runtime_budget`, and `response({ message })` for a structured HTTP 429. Keep user input available so it can be retried. Resolving a Sandbox, checking `running()`, stopping a process, and `destroy()` do not need a quota handler; cleanup remains available after a limit.
105
+
98
106
  ## State persistence
99
107
 
100
108
  `getSandbox(id)` selects the same Durable Object for that ID within a deployment. Native Cloudflare deployments preserve that namespace across Worker versions. Each managed platform deployment has its own namespace; rolling back to a retained deployment reconnects to that deployment's namespace.
101
109
 
102
- Files, running processes, and listening servers last only as long as the container. It can stop after inactivity, crash, or restart. Save anything you need to keep in your database, KV, or R2. For custom Durable Object implementations, `void/sandbox` also exports the SDK's `Files`, `DirectoryBackup`, `DirectoryBackupGateway`, `S3Mount`, and `S3Gateway` helpers. Deleting a project on a Void platform removes both its Durable Objects and containers.
110
+ Files, running processes, and listening servers last only as long as the container. It can stop after inactivity, crash, or restart. Save anything you need to keep in your database, KV, or R2. Deleting a project on a Void platform removes both its Durable Objects and containers.
103
111
 
104
112
  ## Deployment
105
113
 
106
- Sandboxes require [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans) and Containers access. Void checks this before provisioning or building. A managed platform's runtime token needs Account / Containers: Edit and Account / Cloudchamber: Edit. Applications without Sandbox do not require Containers or perform this entitlement check.
114
+ Sandboxes require [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans) and Containers access. A managed platform's runtime token needs Account / Containers: Edit and Account / Cloudchamber: Edit.
107
115
 
108
- `void deploy --platform cloudflare` builds native images and deploys the Sandbox alongside the application. `void deploy` on a connected Void Platform creates a deployment-scoped Sandbox controller, which enforces concurrency and runtime limits. Upgrade the platform before deploying an application built with this Sandbox API.
116
+ `void deploy --platform cloudflare` builds native images and deploys the Sandbox alongside the application. `void deploy` on a connected Void Platform applies the platform's Sandbox concurrency and runtime limits. Upgrade the platform before deploying an application built with this Sandbox API.
109
117
 
110
118
  ## Moving from Sandbox SDK 0.x
111
119
 
@@ -25,15 +25,9 @@ routes/
25
25
  api/metrics.prod.ts → production only
26
26
  ```
27
27
 
28
- `dev` is the Vite dev server. `prod` is every build, `void deploy`, and `vite preview` — preview serves a production build, so it uses the production routes.
28
+ `.dev` routes run only in development; `.prod` routes run in builds, deployments, and production previews. A resource used only by `.dev` routes is not provisioned for production.
29
29
 
30
- Excluded routes aren't included in the Worker bundle, generated types, or route and WebSocket configuration.
31
-
32
- `void prepare` is the exception: it boots no Vite, so it has no environment to read. It generates types for routes in both environments.
33
-
34
- [Binding inference](../reference/resource-inference.md) follows the suffix for files in `routes/`. For example, a `void/storage` import used only in `api/debug.dev.ts` adds a development R2 binding, but does not provision a production bucket. Imports in other source directories remain available in both environments.
35
-
36
- The suffix applies to files in `routes/` only. It has no effect in `pages/`, `middleware/`, `crons/`, or `queues/`.
30
+ Suffixes apply only in `routes/`, not in `pages/`, `middleware/`, `crons/`, or `queues/`. `void prepare` generates types for both environments.
37
31
 
38
32
  Each file exports named HTTP method constants to handle specific methods:
39
33
 
@@ -65,20 +59,10 @@ export const POST = defineHandler(async (c) => {
65
59
  });
66
60
  ```
67
61
 
68
- The `db` helper provides a typed query API over D1. See [Database](./database.md) for the full API.
62
+ See [Database](./database.md) for queries with D1, PostgreSQL, or MySQL.
69
63
 
70
64
  ## `defineHandler`
71
65
 
72
- `defineHandler` wraps a route handler function:
73
-
74
- ```ts
75
- import { defineHandler } from 'void';
76
-
77
- export const GET = defineHandler((c) => {
78
- return { data: 'hello' };
79
- });
80
- ```
81
-
82
66
  The handler receives a Hono `Context` with typed Cloudflare bindings on `c.env` (see [Cloudflare](../integrations/cloudflare.md)). You can use the full Hono API (`c.json()`, `c.text()`, `c.header()`, etc.).
83
67
 
84
68
  Return values are automatically converted:
@@ -108,23 +92,6 @@ export const POST = defineHandler.withValidator({
108
92
 
109
93
  See [Database: Schema-Derived Validators](./database.md#schema-derived-validators) for how to set up `createInsertSchema` with column refinements.
110
94
 
111
- You can validate the body, query, and route parameters together:
112
-
113
- ```ts
114
- // routes/api/users/[id].ts
115
- import { defineHandler } from 'void';
116
- import { db, eq } from 'void/db';
117
- import { users, updateUserSchema } from '@schema';
118
-
119
- export const PUT = defineHandler.withValidator({
120
- body: updateUserSchema,
121
- })(async (c, { body }) => {
122
- const id = Number(c.req.param('id'));
123
- const [updated] = await db.update(users).set(body).where(eq(users.id, id)).returning();
124
- return updated;
125
- });
126
- ```
127
-
128
95
  ### Manual validators
129
96
 
130
97
  For endpoints that don't map to a database table, you can write validators by hand using any [Standard Schema](https://standardschema.dev/)-compatible library (Valibot, Zod, ArkType, etc.):
@@ -160,7 +127,7 @@ When validation fails, a `400` response is returned with structured error detail
160
127
  }
161
128
  ```
162
129
 
163
- No extra dependencies are required. Void inlines the Standard Schema types, so you only need your chosen schema library.
130
+ Install your chosen validator library; no separate Standard Schema dependency is needed.
164
131
 
165
132
  Validator schemas also power the [typed fetch client](./typed-fetch.md), so `body`, `query`, and `params` types are enforced at the call site.
166
133
 
@@ -208,9 +175,7 @@ export default defineMiddleware(async (c, next) => {
208
175
  });
209
176
  ```
210
177
 
211
- `defineMiddleware` uses Hono middleware semantics: `(c, next) => Promise<void> | void`.
212
-
213
- For a temporary full-site gate, use the built-in `basicAuth()` middleware with credentials from `void/env`. Void internal endpoints under `/__void` are excluded automatically so deploy migrations and dev tooling continue to work. Wrap `void/env` reads in functions so they are resolved per request after Void has bound the runtime env.
178
+ Use `basicAuth()` for a temporary site gate. Void's reserved `/__void` endpoints remain accessible for deployment and development tooling. Read credentials through callbacks:
214
179
 
215
180
  ```ts
216
181
  // env.ts
@@ -238,25 +203,7 @@ Set `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` as local environment variabl
238
203
 
239
204
  For app-specific bypasses such as health checks or public webhooks, compose that logic in your own middleware before calling `basicAuth()`.
240
205
 
241
- Middleware can set typed context variables using `c.set()`. Augment the `CloudContextVariables` interface so downstream handlers get full type safety:
242
-
243
- ```ts
244
- // middleware/01.request-id.ts
245
- import { defineMiddleware } from 'void';
246
-
247
- declare module 'void' {
248
- interface CloudContextVariables {
249
- requestId: string;
250
- }
251
- }
252
-
253
- export default defineMiddleware(async (c, next) => {
254
- c.set('requestId', crypto.randomUUID());
255
- await next();
256
- });
257
- ```
258
-
259
- Now every route handler can call `c.get("requestId")` and get `string` back, with no type assertion needed. See [Type Safety](./type-safety.md#context-variables) for more details.
206
+ Use `c.set()` to share data with downstream handlers. Augment `CloudContextVariables` for typed access with `c.get()`. See [Context variables](./type-safety.md#context-variables).
260
207
 
261
208
  ### Per-route middleware
262
209
 
@@ -273,19 +220,9 @@ Middleware runs in order. Each can short-circuit (return a response without call
273
220
  import { defineHandler } from 'void';
274
221
  import { cors } from 'hono/cors';
275
222
 
276
- const addServerTiming = async (c, next) => {
277
- const start = performance.now();
278
- await next();
279
- c.header('Server-Timing', `app;dur=${Math.round(performance.now() - start)}`);
280
- };
281
-
282
- export const GET = defineHandler(
283
- cors({ origin: 'https://app.example.com' }),
284
- addServerTiming,
285
- (c) => {
286
- return { stats: '...' };
287
- },
288
- );
223
+ export const GET = defineHandler(cors({ origin: 'https://app.example.com' }), (c) => ({
224
+ stats: '...',
225
+ }));
289
226
  ```
290
227
 
291
228
  Up to 5 middleware can be passed before the handler, with full type inference for each position.
@@ -65,11 +65,11 @@ await stream.send({
65
65
  await stream.comment('still connected');
66
66
  ```
67
67
 
68
- `data` may be a string or JSON-serializable value. Strings are sent as-is; other values are serialized with `JSON.stringify()`. Multi-line strings are split into multiple `data:` lines. Binary data is rejected because SSE is text-only.
68
+ `data` accepts strings or JSON-serializable values. SSE is text-only.
69
69
 
70
- Void validates `event`, `id`, and `retry` before writing, so their values can't accidentally introduce extra SSE fields or events. Writing to a closed stream throws `SseStreamClosedError`.
70
+ Writing to a closed stream throws `SseStreamClosedError`.
71
71
 
72
- If you already serialized the payload, use `formatSseText()` for lower-level formatting while keeping the same `id`, `event`, and `retry` validation:
72
+ Use `formatSseText()` to format a payload you have already serialized:
73
73
 
74
74
  ```ts
75
75
  import { formatSseText } from 'void/sse';
@@ -98,8 +98,6 @@ return eventStream(start, {
98
98
  });
99
99
  ```
100
100
 
101
- The interval must be a positive finite number.
102
-
103
101
  ## Last Event ID
104
102
 
105
103
  Browsers send `Last-Event-ID` when reconnecting after an event with an `id` field. Use `getLastEventId()` to resume from your own storage:
@@ -115,8 +113,6 @@ export const GET = defineHandler((c) => {
115
113
  });
116
114
  ```
117
115
 
118
- `void/sse` does not store or replay events. Persist event offsets in your own database, queue, or Durable Object when replay matters.
119
-
120
116
  ## Client
121
117
 
122
118
  Use `connectEventStream()` from the browser-only `void/sse/client` subpath:
@@ -174,14 +170,4 @@ export const GET = defineHandler(async (c) => {
174
170
 
175
171
  Native `EventSource` can send cookies with `withCredentials: true`. For non-cookie auth, generate a short-lived signed URL and validate it in the route handler.
176
172
 
177
- ## When to use SSE
178
-
179
- Plain SSE is enough when the producer belongs to the same request that opened the stream:
180
-
181
- - AI token streaming
182
- - One-off progress updates
183
- - Command output
184
- - Per-request deployment or build logs
185
- - Incremental status for a long-running action
186
-
187
- For shared topics and subscriptions, use [Live Event Streams](./live.md). For rooms with two-way communication, use [WebSockets](./websockets.md). Replay and database change streams need an application-level storage or delivery layer.
173
+ For shared topics and subscriptions, use [Live Event Streams](./live.md). For two-way communication, use [WebSockets](./websockets.md).
@@ -14,15 +14,11 @@ Set `output: "static"` in `void.config.ts` to prerender all pages at build time:
14
14
 
15
15
  When `output` is `"static"`:
16
16
 
17
- - All pages default to `prerender = true` and are written as HTML files to `dist/client/`. A standalone `vite build` renders them during the build; managed `void deploy` renders immediately afterward in its trusted parent process.
17
+ - Pages default to `prerender = true` and are written as HTML files to `dist/client/`.
18
18
  - Use `export const prerender = false` in a page's `.server.ts` to opt out. That page will be server-rendered on request.
19
19
  - Dynamic pages without `getPrerenderPaths()` are implicitly not prerendered (the paths aren't known at build time).
20
20
  - The build output is self-contained and works for direct Cloudflare deployment, self-hosting, or `void deploy`.
21
21
 
22
- ## How it works
23
-
24
- During `vite build`, after both the worker and client bundles are written to disk, Void spins up Miniflare with the built worker and fetches each page. The HTML responses are written to `dist/client/` as static files (e.g. `/about` becomes `dist/client/about.html`).
25
-
26
22
  ## Per-page overrides
27
23
 
28
24
  Individual pages can opt out of prerendering:
@@ -41,8 +37,6 @@ export async function getPrerenderPaths() {
41
37
  }
42
38
  ```
43
39
 
44
- Dynamic pages **without** `getPrerenderPaths()` are not prerendered because the paths are not known at build time. These pages are served dynamically by the worker at runtime.
45
-
46
40
  ## Comparison with edge prerendering
47
41
 
48
42
  | `output` value | Default prerender | Per-page override | Prerender timing |
@@ -50,19 +44,15 @@ Dynamic pages **without** `getPrerenderPaths()` are not prerendered because the
50
44
  | `"server"` (default) | `false` | `export const prerender = true` | Deploy-time (platform ISR) |
51
45
  | `"static"` | `true` | `export const prerender = false` | Build or deploy post-build |
52
46
 
53
- When `output` is omitted or set to `"server"`, behavior is unchanged. `export const prerender = true` opts individual pages into deploy-time [edge prerendering](./edge/prerendering.md).
54
-
55
- Managed deploy keeps its deployment credential out of project-controlled build scripts and Vite plugins. When static rendering needs remote D1, KV, R2, or AI, the trusted deploy process supplies the built worker with a five-minute credential scoped to that project's binding proxy only.
47
+ With the default `output: "server"`, use `export const prerender = true` for deploy-time [edge prerendering](./edge/prerendering.md).
56
48
 
57
49
  ## Deployment behavior
58
50
 
59
- When you run `void deploy` with `output: "static"`, Void inspects the build output to decide the optimal deploy strategy:
51
+ `void deploy` chooses the deployment automatically:
60
52
 
61
53
  - **Fully static:** if every page is prerendered and there are no API routes, middleware, cron jobs, or queues, Void deploys as a pure static site with no worker.
62
54
  - **Hybrid:** if any pages are not prerenderable, such as dynamic pages without `getPrerenderPaths()` or pages with `export const prerender = false`, a worker is deployed to handle those routes at runtime. Prerendered pages are still served as static assets.
63
55
 
64
- You do not need to configure this. Void detects it automatically from your pages and project structure.
65
-
66
56
  ## Relationship to `inference.appType: "static"`
67
57
 
68
58
  The `inference.appType` field describes app type (SPA, static, void), while `output` controls rendering strategy:
@@ -72,5 +62,3 @@ The `inference.appType` field describes app type (SPA, static, void), while `out
72
62
  | **What** | Deploy a pre-built static site (no Void plugin) | Prerender a Void app at build time |
73
63
  | **Worker** | None (static assets only) | Only if some pages can't be prerendered |
74
64
  | **Use case** | VitePress, plain HTML, external SSG tools | Void apps with mostly or fully static content |
75
-
76
- When all pages are prerendered and there are no backend features, `output: "static"` produces the same deploy result as `inference.appType: "static"`: pure static assets with no worker. The difference is that `output: "static"` figures this out by analyzing your build output, while `inference.appType: "static"` is a manual declaration for non-Void projects.
@@ -4,18 +4,11 @@ outline: deep
4
4
 
5
5
  # Custom SSR
6
6
 
7
- Void supports framework-agnostic SSR via explicit server and client entries. This is for advanced use cases where you want full control over rendering and hydration.
7
+ Use custom SSR to choose your own router, data loading, HTML shell, and hydration code. If you want Void to handle these for you, use [Pages Routing](./pages-routing/overview).
8
8
 
9
- ::: tip
10
- For most apps, [Pages Routing](./pages-routing/overview) handles SSR automatically. You do not need entry files or hydration code.
11
- :::
9
+ ## Create the app
12
10
 
13
- ## Relationship to Pages Routing
14
-
15
- Custom SSR is separate from Pages Routing. Use Custom SSR when you want to bring
16
- your own root component, router, data loading, HTML shell, and hydration logic.
17
-
18
- The `App` component below is the root of this custom-rendered application:
11
+ Start with a root component. This React example renders a page based on the request path:
19
12
 
20
13
  ```tsx
21
14
  // src/App.tsx
@@ -24,50 +17,21 @@ export default function App({ url }: { url: string }) {
24
17
  }
25
18
  ```
26
19
 
27
- Pages Routing adapters generate their own SSR and hydration entries and compose
28
- `pages/layout.*`, route components, loaders, and actions.
29
-
30
20
  ## Required entries
31
21
 
32
- SSR mode is enabled when both of these exist:
22
+ Create both entry files:
33
23
 
34
24
  - `src/main.ssr.ts` or `src/main.ssr.tsx`
35
25
  - `src/main.client.ts` or `src/main.client.tsx`
36
26
 
37
- Only one server entry and one client entry may exist.
38
- If only one side is present, build/deploy fails with a clear error.
27
+ Use one server entry and one client entry. Both are required.
39
28
 
40
29
  ## Render API
41
30
 
42
- `src/main.ssr.ts(x)` must export either:
43
-
44
- ```ts
45
- render(c: CloudContext, assetTags: RenderAssetTags): Response | Promise<Response>
46
- ```
47
-
48
- or:
49
-
50
- ```ts
51
- export default defineRender((c, assetTags) => Response | Promise<Response>);
52
- ```
53
-
54
- The recommended form is `defineRender(...)` for inferred types.
55
-
56
- `assetTags` contains the HTML tags for your client assets:
57
-
58
- ```ts
59
- {
60
- css: string; // stylesheet links for <head>
61
- preloads: string; // modulepreload/Vite client+preamble tags for <head>
62
- body: string; // main client entry script tag before </body>
63
- }
64
- ```
65
-
66
- If no render export is found, build/deploy fails with a clear error.
67
-
68
- Example:
31
+ Wrap your server renderer with `defineRender()` and return an HTML response. Insert `assetTags.css` and `assetTags.preloads` in `<head>`, and `assetTags.body` before `</body>`:
69
32
 
70
33
  ```tsx
34
+ // src/main.ssr.tsx
71
35
  import { renderToString } from 'react-dom/server';
72
36
  import { defineRender } from 'void';
73
37
  import App from './App';
@@ -89,34 +53,22 @@ export default defineRender(async (c, assetTags) => {
89
53
  });
90
54
  ```
91
55
 
92
- `src/main.client.ts(x)` should hydrate/mount your app:
56
+ You can also export a named `render(c, assetTags)` function with the same signature. See [`defineRender`](../reference/api/handlers.md#definerender-handler) for the types.
57
+
58
+ ## Hydrate in the browser
59
+
60
+ In the client entry, hydrate the same component:
93
61
 
94
62
  ```tsx
63
+ // src/main.client.tsx
95
64
  import { hydrateRoot } from 'react-dom/client';
96
65
  import App from './App';
97
66
 
98
67
  hydrateRoot(document.getElementById('root')!, <App url={window.location.pathname} />);
99
68
  ```
100
69
 
101
- ## Client Asset Injection
102
-
103
- Place the client asset tags in the HTML returned by your `render()` function.
104
-
105
- The `assetTags` values are computed by Void:
106
-
107
- - In production: from `dist/client/.vite/manifest.json` (entry script, CSS, modulepreload)
108
- - In dev: includes Vite HMR client and React refresh preamble (when React plugin is active), plus the client entry script
109
-
110
70
  ## Caching
111
71
 
112
72
  See [Revalidation](./edge/revalidation.md) for stale-while-revalidate caching of SSR pages.
113
73
 
114
- ## Request flow
115
-
116
- With SSR enabled:
117
-
118
- 1. `/api/*` requests go to worker API routes
119
- 2. static asset hits are served from R2
120
- 3. unmatched non-API requests fall back to `render(c, assetTags)`
121
-
122
- Without SSR entries, non-API requests keep SPA static fallback behavior.
74
+ API routes and static files are served before custom rendering. Unmatched non-API requests use `render(c, assetTags)`.
@@ -35,13 +35,14 @@ for (const obj of listed.objects) {
35
35
  const head = await storage.head('uploads/photo.jpg');
36
36
  ```
37
37
 
38
- The `storage` object is a full `R2Bucket`. Every method from the [Cloudflare R2 API](https://developers.cloudflare.com/r2/api/workers/workers-api-reference/) is available directly, with no wrapper layer.
38
+ `storage` supports the full [R2Bucket API](https://developers.cloudflare.com/r2/api/workers/workers-api-reference/).
39
39
 
40
40
  ## Serving Files
41
41
 
42
42
  A common pattern is serving uploaded files from an API route:
43
43
 
44
44
  ```ts
45
+ import { defineHandler } from 'void';
45
46
  import { storage } from 'void/storage';
46
47
 
47
48
  export const GET = defineHandler(async (c) => {
@@ -60,8 +61,12 @@ export const GET = defineHandler(async (c) => {
60
61
  });
61
62
  ```
62
63
 
63
- ## How It Works
64
+ ## Custom bindings
64
65
 
65
- `storage` resolves the `env.STORAGE` binding when you use it. It exposes the R2 API directly, so methods and options work as described in Cloudflare's documentation.
66
+ Use `createStorage(bucket)` with your own R2 binding, or in tests:
66
67
 
67
- The `createStorage()` factory exists for testing and for frameworks that manage their own routing. It accepts an `R2Bucket` and returns it directly.
68
+ ```ts
69
+ import { createStorage } from 'void/storage';
70
+
71
+ const storage = createStorage(env.MY_BUCKET);
72
+ ```