void 1.3.0 → 1.5.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 (451) hide show
  1. package/README.md +1 -1
  2. package/dist/{account-cmd-B4i71m7k.mjs → account-cmd-ChVKPZ-w.mjs} +7 -8
  3. package/dist/{action-key-XZ9HkWAO.mjs → action-key-XtKKbbsi.mjs} +1 -2
  4. package/dist/{agents-CuNtT0D_.mjs → agents-DRo8gzni.mjs} +2 -3
  5. package/dist/{application-analysis-DYdVoMAY.mjs → application-analysis-2vGZrKzg.mjs} +27 -29
  6. package/dist/{application-routing-C8EqRDfv.mjs → application-routing-DnUQoOJD.mjs} +2 -3
  7. package/dist/{ast-CsZ_q_gc.mjs → ast-Cv0JwXqb.mjs} +1 -2
  8. package/dist/{ast-bindings-C3yaPs1y.mjs → ast-bindings-BkivMJIo.mjs} +6 -11
  9. package/dist/{atomic-write-Dq6R0BPN.mjs → atomic-write-DA6eD1Kp.mjs} +1 -2
  10. package/dist/auth-CH4PLAX1.d.mts +68 -0
  11. package/dist/{auth-Cbqi1iVX.mjs → auth-CL-p_rqV.mjs} +1 -1
  12. package/dist/{auth-B6iOCjKI.mjs → auth-Dy8svcqQ.mjs} +6 -7
  13. package/dist/{auth-3sGB0zJ1.mjs → auth-YVjBX5NY.mjs} +1 -2
  14. package/dist/{auth-client-Bawdj38n.d.mts → auth-client-6-Ft9i9T.d.mts} +0 -2
  15. package/dist/{auth-client-BWBT8HLp.mjs → auth-client-DwCdwKbw.mjs} +1 -2
  16. package/dist/{auth-client-react-CMLwT2xI.mjs → auth-client-react-CJdeErvM.mjs} +1 -2
  17. package/dist/{auth-client-react-7GFffu8R.d.mts → auth-client-react-DvQLe5Zb.d.mts} +0 -2
  18. package/dist/{auth-client-solid-UoreJWZG.mjs → auth-client-solid-BRvgvp6h.mjs} +1 -2
  19. package/dist/{auth-client-solid-DyTFL4cq.d.mts → auth-client-solid-P9pEtKGp.d.mts} +0 -2
  20. package/dist/{auth-client-svelte-zetW0KIH.d.mts → auth-client-svelte-B5j8irT6.d.mts} +0 -2
  21. package/dist/{auth-client-svelte-Cv_WvrRk.mjs → auth-client-svelte-BSqUCEed.mjs} +1 -2
  22. package/dist/{auth-client-vue-bChShbQP.d.mts → auth-client-vue-BEiAfavk.d.mts} +0 -2
  23. package/dist/{auth-client-vue-CFk7Xbv3.mjs → auth-client-vue-CPkbRtOO.mjs} +1 -2
  24. package/dist/{auth-link-BKwHPbdv.mjs → auth-link-D4uMdOsw.mjs} +7 -8
  25. package/dist/{auth-migrations-BO27GDNr.mjs → auth-migrations-DDeifS3v.mjs} +1 -2
  26. package/dist/{auth-router-DqLx8E0F.mjs → auth-router-62dna450.mjs} +14 -10
  27. package/dist/{base64-DVrOndmI.mjs → base64-ikl9yBy3.mjs} +1 -2
  28. package/dist/{better-auth-shared-DVk2DkTW.d.mts → better-auth-shared-BJyG2mH0.d.mts} +2 -6
  29. package/dist/{better-auth-shared-7FM3Uk2N.mjs → better-auth-shared-CiclgPde.mjs} +4 -5
  30. package/dist/{build-cmd-Dy4psnt1.mjs → build-cmd-D93K_4Sa.mjs} +7 -8
  31. package/dist/{cache-DV37S6dl.mjs → cache-CiIzEED4.mjs} +7 -8
  32. package/dist/{cancel-deploy-DMPyu1Vt.mjs → cancel-deploy-BNoGfn2e.mjs} +6 -7
  33. package/dist/{cf-access-CWP4avfP.mjs → cf-access-BmBT2h8_.mjs} +3 -4
  34. package/dist/{cf-access-BM9G0lhO.mjs → cf-access-pejlJmuy.mjs} +1 -2
  35. package/dist/{cf-build-output-Bapzc_8Z.mjs → cf-build-output-B1C8U83u.mjs} +60 -317
  36. package/dist/cf-build-output-CmDOcA7K.mjs +1 -0
  37. package/dist/{cf-command-values-ByHk0xg4.mjs → cf-command-values-Ccl-zRhl.mjs} +10 -7
  38. package/dist/cf-config-migrate-Dy8MrKgF.mjs +326 -0
  39. package/dist/{cf-worker-settings-BECvvTVd.mjs → cf-worker-settings-CARs4Wy9.mjs} +14 -10
  40. package/dist/cli/cli.mjs +66 -76
  41. package/dist/cli/cloudflare-operation-process.mjs +21 -19
  42. package/dist/cli/env-schema-probe.d.mts +1 -5
  43. package/dist/cli/env-schema-probe.mjs +4 -5
  44. package/dist/client-DVtAKeUm.mjs +1 -0
  45. package/dist/{client-BEMtySaV.mjs → client-Qayy9xEh.mjs} +10 -12
  46. package/dist/{cloudflare-auth-Byo_0_N9.mjs → cloudflare-auth-CEu-1Ps_.mjs} +3 -4
  47. package/dist/{cloudflare-cmd-BaqIigwI.mjs → cloudflare-cmd-DiFGaLow.mjs} +7 -8
  48. package/dist/{cloudflare-config-DchHxPTo.mjs → cloudflare-config-Chet188_.mjs} +25 -9
  49. package/dist/{cloudflare-connect-pNLQmr_e.mjs → cloudflare-connect-BdgAQBc7.mjs} +5 -6
  50. package/dist/{cloudflare-operations-vP3b5CQf.mjs → cloudflare-operations-CWA24vCh.mjs} +8 -9
  51. package/dist/{cloudflare-operations-PCM4wucv.mjs → cloudflare-operations-D8MoezuN.mjs} +1 -1
  52. package/dist/{cloudflare-process-8jEYIeim.mjs → cloudflare-process-DjJ638A-.mjs} +7 -9
  53. package/dist/{cloudflare-user-output-Q-k0QoNQ.mjs → cloudflare-user-output-zEwuGrEJ.mjs} +1 -2
  54. package/dist/collect-8i0wU63d.mjs +1 -0
  55. package/dist/{collect-Dew86qce.mjs → collect-C6Blu9yw.mjs} +2 -3
  56. package/dist/{config-BU6hMu1W.mjs → config-BszFVhpk.mjs} +1 -1
  57. package/dist/{config-BIaXIkkv.mjs → config-Bt4rw93x.mjs} +5 -6
  58. package/dist/{config-Du88-7Y8.d.mts → config-CzsNzGVH.d.mts} +4 -6
  59. package/dist/{config-DHgSEWT7.mjs → config-DkA9jYF2.mjs} +9 -8
  60. package/dist/config-WlvEcL82.mjs +86 -0
  61. package/dist/config-entry.d.mts +1 -3
  62. package/dist/config-entry.mjs +1 -2
  63. package/dist/{connect-DwVsBvVh.mjs → connect-b9mJbb6X.mjs} +10 -11
  64. package/dist/{create-project-CjzbBlTv.mjs → create-project-eomwm0wa.mjs} +9 -11
  65. package/dist/{create-project-CgrnvzyA.mjs → create-project-rnjum4_V.mjs} +1 -1
  66. package/dist/{database-provider-Cx525bwX.mjs → database-provider-DkZo4VwN.mjs} +1 -2
  67. package/dist/database-provider.d.mts +1 -3
  68. package/dist/database-provider.mjs +1 -1
  69. package/dist/{db-rvo64snS.mjs → db-UPWmiSk1.mjs} +52 -54
  70. package/dist/{db-types-NGxPwnlt.mjs → db-types-C_8amnB0.mjs} +3 -4
  71. package/dist/{delete-DWX6dP4M.mjs → delete-BeeYi1WO.mjs} +7 -8
  72. package/dist/deploy-CfU7CR-b.mjs +2 -0
  73. package/dist/{deploy-hRPvw8ci.mjs → deploy-CwmCcTlq.mjs} +321 -185
  74. package/dist/{deploy-managed-static-CDYA2p3L.mjs → deploy-managed-static-gPDxyp3v.mjs} +46 -46
  75. package/dist/{deploy-transport-JCxw7QDi.mjs → deploy-transport-L6zzPE9T.mjs} +17 -17
  76. package/dist/deploy.d.mts +3 -3
  77. package/dist/deploy.mjs +13 -12
  78. package/dist/{dev-inbox-D0jxye_D.mjs → dev-inbox-CwH5VuZj.mjs} +3 -4
  79. package/dist/discover-D4mQthao.mjs +1 -0
  80. package/dist/{discover-LaV0tbIu.mjs → discover-Dhkzxgdt.mjs} +3 -4
  81. package/dist/{dispatch-OVLeWW8K.mjs → dispatch-CiJ1Xrba.mjs} +13 -16
  82. package/dist/{dist-Cegxq8gs.mjs → dist-B6eN80gc.mjs} +199 -118
  83. package/dist/{dist-D15hFhP0.mjs → dist-BWNkVq50.mjs} +8 -15
  84. package/dist/{dist-Cor9XGoz.mjs → dist-D23AAMxT.mjs} +9 -16
  85. package/dist/{dist-ipQi0Q8y.mjs → dist-DMYe8CZJ.mjs} +1 -2
  86. package/dist/{dist-B1PLt4_8.mjs → dist-eV_Ep60B.mjs} +1 -1
  87. package/dist/{domain-CH5iBD9Y.mjs → domain-3xdH9p2L.mjs} +8 -9
  88. package/dist/{dotenv-CNazY3-w.mjs → dotenv-CEI8hapP.mjs} +1 -2
  89. package/dist/{drizzle-9TubSZvI.mjs → drizzle-C8MPqt5m.mjs} +1 -1
  90. package/dist/{drizzle-BQfyvQKX.mjs → drizzle-lFdzSEa9.mjs} +2 -3
  91. package/dist/{email-B9ayYQEG.mjs → email-BHY72ixO.mjs} +3 -4
  92. package/dist/{email-CbTO1l78.mjs → email-Du3YRnM5.mjs} +14 -15
  93. package/dist/{email-cloudflare-B8-pq_-W.mjs → email-cloudflare-CtD8qE13.mjs} +34 -24
  94. package/dist/{email-protocol-D9nTvhCp.mjs → email-protocol-DTs_TjCS.mjs} +1 -2
  95. package/dist/{entry-BEM8ZuGP.mjs → entry-CBZsCy3O.mjs} +5 -6
  96. package/dist/{env-BBdw236G.mjs → env-Cnvp0pGy.mjs} +10 -11
  97. package/dist/{env-BaMz0j7H.mjs → env-CuzZZyjB.mjs} +3 -4
  98. package/dist/{env-0jrMQJI_.mjs → env-DtKg5G26.mjs} +2 -3
  99. package/dist/{env-helpers--wFmQ_5Q.mjs → env-helpers-Dj_SIwPu.mjs} +1 -2
  100. package/dist/{env-helpers-CyKtOBpj.d.mts → env-helpers-U56xuFgL.d.mts} +1 -3
  101. package/dist/{env-public-6lqiSD2b.d.mts → env-public-CeNeO_AT.d.mts} +2 -4
  102. package/dist/{env-raw-D74P4ebM.mjs → env-raw-e8qgqAzQ.mjs} +1 -2
  103. package/dist/{env-types-BicfKBhV.mjs → env-types-DqzVBKnS.mjs} +4 -5
  104. package/dist/{env-validation-BfBVvBNe.mjs → env-validation-C8Cmvas0.mjs} +1 -1
  105. package/dist/{env-validation-XcukUlFM.mjs → env-validation-GV1oD4EV.mjs} +10 -10
  106. package/dist/error-pages-COVBnzK7.mjs +31 -0
  107. package/dist/{fetch-CUX0tB78.d.mts → fetch-B-gLGYVl.d.mts} +0 -4
  108. package/dist/{fetch-CtESUYWd.mjs → fetch-C8yhLoF3.mjs} +3 -4
  109. package/dist/{fetch-error-Bw0n-IY-.mjs → fetch-error-DmlRM6e4.mjs} +2 -4
  110. package/dist/{fetch-stream-BspOeTAI.mjs → fetch-stream-DafNtVJC.mjs} +4 -5
  111. package/dist/{fetch-stream-DfkAzZf-.d.mts → fetch-stream-DuwxWmBM.d.mts} +1 -3
  112. package/dist/{gen-CCx3t2Ju.mjs → gen-BvVmpZ5f.mjs} +12 -13
  113. package/dist/gen-i61rdQgg.mjs +1 -0
  114. package/dist/{generate-DkEb9rL-.mjs → generate-BOp1g1H_.mjs} +1 -1
  115. package/dist/{generate-B1m4Cm4n.mjs → generate-CWb8aOsm.mjs} +4 -5
  116. package/dist/{generated-wrangler-config-DeWj5F9Y.mjs → generated-wrangler-config-CoDaaFsA.mjs} +1 -2
  117. package/dist/{git-metadata-D-gurjzG.mjs → git-metadata-Cukp5kV5.mjs} +1 -2
  118. package/dist/{github-cmd-BzkRLkbg.mjs → github-cmd-X2GKiLi-.mjs} +8 -9
  119. package/dist/{handler-CQv5YDS0.d.mts → handler-Drm_lyrV.d.mts} +15 -26
  120. package/dist/{handler-BZ1t7-Rv.mjs → handler-xmzz0U38.mjs} +4 -5
  121. package/dist/{head-D2VF4ApL.mjs → head-5XPcnG-j.mjs} +1 -2
  122. package/dist/{head-C8K_iGe6.d.mts → head-MeF_5M_3.d.mts} +0 -2
  123. package/dist/{headers-D522zd0A.mjs → headers-DEUBAM6W.mjs} +4 -5
  124. package/dist/help-BcZDUcTw.mjs +1 -0
  125. package/dist/{help-CKbrhZha.mjs → help-EWDNxST-.mjs} +19 -11
  126. package/dist/{inbound-VrOLqwZY.mjs → inbound-DQfekMtz.mjs} +5 -6
  127. package/dist/{inbound-Da7XsjH3.d.mts → inbound-DSKSHDUj.d.mts} +0 -4
  128. package/dist/index.d.mts +23 -13
  129. package/dist/index.mjs +504 -225
  130. package/dist/{info-oBm8yK8J.mjs → info-jW8_d3VI.mjs} +6 -7
  131. package/dist/{init-CBp_uMve.mjs → init-jDQ5G9QC.mjs} +62 -64
  132. package/dist/{isr-config-fZaJJ8t7.mjs → isr-config-DhBkzCdY.mjs} +5 -9
  133. package/dist/{limits-D0vD1M9A.mjs → limits-CrHLm5Tk.mjs} +1 -2
  134. package/dist/{limits-CFsDKQvU.d.mts → limits-_xIf5z_P.d.mts} +0 -2
  135. package/dist/{link-Dt_QXmM4.mjs → link-DOyxX5Xs.mjs} +8 -9
  136. package/dist/{list-DF6asTdt.mjs → list-C9pTYDtl.mjs} +8 -9
  137. package/dist/{live-CXJ9yC98.d.mts → live-CDBHyYiR.d.mts} +2 -4
  138. package/dist/{live-BcHoTDFe.mjs → live-DF4HUl2m.mjs} +5 -7
  139. package/dist/{load-user-env-DD5qveNU.mjs → load-user-env-CSwdofj0.mjs} +1 -2
  140. package/dist/{local-d1-CUhH3qtj.mjs → local-d1-CKfek6Z4.mjs} +4 -5
  141. package/dist/{log-BMwmN5Ae.mjs → log-D9hwSySP.mjs} +3 -4
  142. package/dist/login-C0MiQrYs.mjs +1 -0
  143. package/dist/{login-BjSyhXlT.mjs → login-koQbjzPd.mjs} +6 -7
  144. package/dist/{logs-DmvBl6xA.mjs → logs-cTU5TsRW.mjs} +8 -9
  145. package/dist/migrate-BG09-KOv.mjs +1 -0
  146. package/dist/{migrate-BXRHpYwR.mjs → migrate-C62pGTfr.mjs} +22 -79
  147. package/dist/{migration-handler-CwlEQUoo.d.mts → migration-handler-D8mDx3Ew.d.mts} +0 -4
  148. package/dist/{migration-handler-Cg0Y4EPu.mjs → migration-handler-DCehTlWs.mjs} +1 -2
  149. package/dist/{mime-BAyHPskU.mjs → mime-DKkO7ZtA.mjs} +2 -3
  150. package/dist/{mysql-migration-sql-BIS5vbNk.mjs → mysql-migration-sql-CI9VTwjt.mjs} +3 -5
  151. package/dist/{neon-DTZr7Bu7.mjs → neon-CJzQSycr.mjs} +2 -3
  152. package/dist/nitro.d.mts +0 -2
  153. package/dist/nitro.mjs +6 -7
  154. package/dist/{node-DtD7ZiPf.mjs → node-BfAt2rz8.mjs} +9 -10
  155. package/dist/{operator-args-BsJIYXaT.mjs → operator-args-D79WQP70.mjs} +2 -3
  156. package/dist/{operator-auth-Cr2zCc-J.mjs → operator-auth-CfDcmzpo.mjs} +2 -3
  157. package/dist/{operator-client-C-ROjk1I.mjs → operator-client-BIY4-N_6.mjs} +3 -4
  158. package/dist/operator-cmd-BhHXIL2G.mjs +1 -0
  159. package/dist/{operator-cmd-DjZKGGgN.mjs → operator-cmd-CnAvSqJ5.mjs} +8 -9
  160. package/dist/{output-BpgYODYx.mjs → output-BCdLioKP.mjs} +4 -5
  161. package/dist/output-E6gecbbV.mjs +1 -0
  162. package/dist/{package-json-BjYqR-So.mjs → package-json-DvS6IFRv.mjs} +2 -3
  163. package/dist/pages/client.d.mts +22 -23
  164. package/dist/pages/client.mjs +51 -31
  165. package/dist/pages/head.d.mts +1 -1
  166. package/dist/pages/head.mjs +1 -1
  167. package/dist/pages/index.d.mts +18 -14
  168. package/dist/pages/index.mjs +99 -10
  169. package/dist/pages/islands-plugin.d.mts +29 -11
  170. package/dist/pages/islands-plugin.mjs +3 -4
  171. package/dist/pages/prefetch.d.mts +1 -1
  172. package/dist/pages/prefetch.mjs +1 -1
  173. package/dist/pages/protocol.d.mts +2 -2
  174. package/dist/pages/protocol.mjs +2 -2
  175. package/dist/pages/serialize.d.mts +1 -1
  176. package/dist/pages/serialize.mjs +1 -1
  177. package/dist/{pg-J2HbZIkX.mjs → pg-DoyPxa_X.mjs} +1 -2
  178. package/dist/{picocolors-BsDfhxIw.mjs → picocolors-D1NxSLw-.mjs} +2 -3
  179. package/dist/{plan-BhLO2p4w.mjs → plan-BOD70XGS.mjs} +1 -2
  180. package/dist/plan-CQ-N4gws.mjs +1 -0
  181. package/dist/{platform-args-BMD2gjc_.mjs → platform-args-Bv9hoLEL.mjs} +4 -7
  182. package/dist/platform-args-C1kqYUen.mjs +1 -0
  183. package/dist/{platform-auth-config-BgnuMbml.mjs → platform-auth-config-CLj0EvnB.mjs} +10 -11
  184. package/dist/{platform-auth-protection-NjRejttU.mjs → platform-auth-protection-DQDSxVhr.mjs} +10 -11
  185. package/dist/{platform-auth-recovery-Ug12d9W5.mjs → platform-auth-recovery-DD3oLerq.mjs} +9 -11
  186. package/dist/{platform-cmd-HByuZAO7.mjs → platform-cmd-PLNLg-2N.mjs} +12 -13
  187. package/dist/{platform-cmd-BYKLMPCn.mjs → platform-cmd-WnOmdLzR.mjs} +1 -1
  188. package/dist/{platform-discovery-CHhNs8Nn.mjs → platform-discovery-B0eZjZ3B.mjs} +2 -3
  189. package/dist/{platform-domain-DLSQ8GF8.mjs → platform-domain-Bnq0vg0q.mjs} +7 -8
  190. package/dist/{platform-lifecycle-3dwFJmnq.mjs → platform-lifecycle-BCsFg1Tl.mjs} +53 -88
  191. package/dist/{platform-lifecycle-BRqcxerG.mjs → platform-lifecycle-BQiN9HN5.mjs} +1 -1
  192. package/dist/{platform-management-ZK6XcbCo.mjs → platform-management-CMJR8Zi-.mjs} +1 -1
  193. package/dist/{platform-management-ZZ6bQM5j.mjs → platform-management-nzCDwtiN.mjs} +7 -9
  194. package/dist/{platform-plans-config-CeydDSj0.mjs → platform-plans-config-Dx1agneU.mjs} +5 -6
  195. package/dist/{platform-recovery-8vNE5dNN.mjs → platform-recovery-DBNoME3I.mjs} +5 -6
  196. package/dist/{platform-registry-B9mWX9LO.mjs → platform-registry-DZ_2Xuqd.mjs} +4 -6
  197. package/dist/{platform-setup-Ca53gtt0.mjs → platform-setup-VEcHu0Vq.mjs} +4 -5
  198. package/dist/{plugin-inference-CeiB6BG5.mjs → plugin-inference-DmwjC3y2.mjs} +16 -24
  199. package/dist/{prefetch-Ce6la4EI.d.mts → prefetch-CG0K6JPd.d.mts} +0 -2
  200. package/dist/{prefetch-Bsc_Pb6c.mjs → prefetch-L93_1Jk7.mjs} +1 -2
  201. package/dist/prepare-BJMmfq3W.mjs +1 -0
  202. package/dist/{prepare-5BR7Splm.mjs → prepare-BPsfLWaW.mjs} +4 -5
  203. package/dist/{prepare-Dseww74N.mjs → prepare-pfl2LIMy.mjs} +17 -14
  204. package/dist/{prerender-render-CaShbHJ3.mjs → prerender-render-RlAj6hh8.mjs} +2 -3
  205. package/dist/prerender-render.d.mts +1 -3
  206. package/dist/prerender-render.mjs +1 -1
  207. package/dist/{project-rqDnVsJN.mjs → project-CLwxcEdq.mjs} +3 -4
  208. package/dist/{project-zdB3fs9G.mjs → project-DVsTAWFh.mjs} +1 -1
  209. package/dist/{project-cmd-CjLNNxwe.mjs → project-cmd-5Izu4Pg3.mjs} +21 -23
  210. package/dist/{project-paths-DGu_QZ_Q.mjs → project-paths-CdGv9Tmi.mjs} +3 -5
  211. package/dist/project-slug-BUy0lmyR.mjs +1 -0
  212. package/dist/{project-slug-23TpquG4.mjs → project-slug-CO6ci9XG.mjs} +0 -1
  213. package/dist/{project-team-DE5drjcl.mjs → project-team-DSUyjZFh.mjs} +7 -8
  214. package/dist/{project-token-XEYEXfiJ.mjs → project-token-wj09YQSB.mjs} +7 -8
  215. package/dist/{project-tsconfig-Itv1f4WC.mjs → project-tsconfig-Cf2NFjlM.mjs} +28 -8
  216. package/dist/{project-zero-trust-6VPU8zmV.mjs → project-zero-trust-BMHf2YF0.mjs} +7 -8
  217. package/dist/{protocol-DimNxVRr.mjs → protocol-0-lp9ZYx.mjs} +6 -7
  218. package/dist/{protocol-BekmFxCI.d.mts → protocol-xdrl-In0.d.mts} +3 -5
  219. package/dist/{providers-BNKRacMr.d.mts → providers-D5P8j_8D.d.mts} +0 -2
  220. package/dist/{providers-BUHwJlmM.mjs → providers-ZARwX2cL.mjs} +1 -2
  221. package/dist/{provision-B7UFrBH7.mjs → provision-CRiNnlfE.mjs} +29 -14
  222. package/dist/{provision-Chq0NRAV.mjs → provision-CxHIGBIZ.mjs} +1 -1
  223. package/dist/{queues-BWKt1Xo4.d.mts → queues-DdM42xXW.d.mts} +0 -2
  224. package/dist/{r2-conditions-B8xUgJRc.mjs → r2-conditions-BqkQNt2n.mjs} +1 -2
  225. package/dist/{requests-CG-Pj8ze.mjs → requests-DicgB5jU.mjs} +6 -7
  226. package/dist/resolve-project-CgfjtOwz.mjs +1 -0
  227. package/dist/{resolve-project-Xoi6eTWY.mjs → resolve-project-D0YNnJfm.mjs} +4 -5
  228. package/dist/{resource-name-C7LVpcRm.mjs → resource-name-DlJ9QXzg.mjs} +1 -2
  229. package/dist/{response-Tn7rU0MV.mjs → response-HmNjB30w.mjs} +1 -2
  230. package/dist/{rollback-CIrm2txZ.mjs → rollback-DrDZOKNE.mjs} +7 -8
  231. package/dist/{rolldown-runtime-3h0WiCiA.mjs → rolldown-runtime-uD8oG6U2.mjs} +1 -2
  232. package/dist/{route-types--PAOzHlH.mjs → route-types-irZc1txT.mjs} +100 -7
  233. package/dist/route-url-BGOiyKNz.d.mts +24 -0
  234. package/dist/route-url-CRDF-I0I.mjs +57 -0
  235. package/dist/routes-stub.d.mts +4 -3
  236. package/dist/routes-stub.mjs +1 -1
  237. package/dist/{routing-assets-DdSFxoLp.mjs → routing-assets-DJIVOrCh.mjs} +1 -2
  238. package/dist/{runner-3uGC-oLF.mjs → runner-5MCSimKx.mjs} +5 -6
  239. package/dist/{runner-WCdfeI0q.mjs → runner-QMeOpScZ.mjs} +1 -1
  240. package/dist/{runner-mysql-BcHnLUuM.mjs → runner-mysql-0zVmB1JW.mjs} +1 -1
  241. package/dist/{runner-mysql-BWmbk5IE.mjs → runner-mysql-Bdmsp_x4.mjs} +3 -4
  242. package/dist/{runner-pg-Cgp-cr_p.mjs → runner-pg-2pjltt0t.mjs} +1 -1
  243. package/dist/{runner-pg-Cr3qrqi4.mjs → runner-pg-mYc75KfH.mjs} +2 -3
  244. package/dist/runtime/ai.d.mts +0 -4
  245. package/dist/runtime/ai.mjs +6 -8
  246. package/dist/runtime/auth-client-react.d.mts +1 -1
  247. package/dist/runtime/auth-client-react.mjs +1 -1
  248. package/dist/runtime/auth-client-solid.d.mts +1 -1
  249. package/dist/runtime/auth-client-solid.mjs +1 -1
  250. package/dist/runtime/auth-client-svelte.d.mts +1 -1
  251. package/dist/runtime/auth-client-svelte.mjs +1 -1
  252. package/dist/runtime/auth-client-vue.d.mts +1 -1
  253. package/dist/runtime/auth-client-vue.mjs +1 -1
  254. package/dist/runtime/auth-client.d.mts +1 -1
  255. package/dist/runtime/auth-client.mjs +1 -1
  256. package/dist/runtime/auth.d.mts +2 -2
  257. package/dist/runtime/auth.mjs +1 -1
  258. package/dist/runtime/better-auth-mysql.d.mts +2 -4
  259. package/dist/runtime/better-auth-mysql.mjs +3 -4
  260. package/dist/runtime/better-auth-pg.d.mts +2 -4
  261. package/dist/runtime/better-auth-pg.mjs +4 -5
  262. package/dist/runtime/better-auth.d.mts +2 -4
  263. package/dist/runtime/better-auth.mjs +3 -4
  264. package/dist/runtime/client-react.d.mts +4 -4
  265. package/dist/runtime/client-react.mjs +4 -4
  266. package/dist/runtime/client-solid.d.mts +4 -4
  267. package/dist/runtime/client-solid.mjs +4 -4
  268. package/dist/runtime/client-svelte.d.mts +4 -4
  269. package/dist/runtime/client-svelte.mjs +4 -4
  270. package/dist/runtime/client-vue.d.mts +4 -4
  271. package/dist/runtime/client-vue.mjs +4 -4
  272. package/dist/runtime/client.d.mts +4 -4
  273. package/dist/runtime/client.mjs +4 -4
  274. package/dist/runtime/db.d.mts +0 -2
  275. package/dist/runtime/db.mjs +2 -3
  276. package/dist/runtime/durable.d.mts +0 -2
  277. package/dist/runtime/durable.mjs +3 -4
  278. package/dist/runtime/email/testing.d.mts +1 -5
  279. package/dist/runtime/email/testing.mjs +5 -6
  280. package/dist/runtime/email-protocol.d.mts +0 -2
  281. package/dist/runtime/email-protocol.mjs +1 -1
  282. package/dist/runtime/email.d.mts +1 -5
  283. package/dist/runtime/email.mjs +6 -7
  284. package/dist/runtime/env-public-client.d.mts +1 -3
  285. package/dist/runtime/env-public-client.mjs +2 -3
  286. package/dist/runtime/env-public.d.mts +2 -2
  287. package/dist/runtime/env-public.mjs +5 -7
  288. package/dist/runtime/env.d.mts +0 -4
  289. package/dist/runtime/env.mjs +1 -1
  290. package/dist/runtime/fetch-server.d.mts +1 -3
  291. package/dist/runtime/fetch-server.mjs +3 -4
  292. package/dist/runtime/fetch-stream.d.mts +2 -2
  293. package/dist/runtime/fetch-stream.mjs +2 -2
  294. package/dist/runtime/fetch.d.mts +1 -1
  295. package/dist/runtime/fetch.mjs +2 -2
  296. package/dist/runtime/handler.d.mts +1 -1
  297. package/dist/runtime/handler.mjs +2 -2
  298. package/dist/runtime/isr.d.mts +1 -3
  299. package/dist/runtime/isr.mjs +2 -3
  300. package/dist/runtime/kv.d.mts +1 -3
  301. package/dist/runtime/kv.mjs +2 -3
  302. package/dist/runtime/limits.d.mts +1 -1
  303. package/dist/runtime/limits.mjs +1 -1
  304. package/dist/runtime/live-client.d.mts +1 -3
  305. package/dist/runtime/live-client.mjs +1 -2
  306. package/dist/runtime/live-server.d.mts +0 -2
  307. package/dist/runtime/live-server.mjs +3 -4
  308. package/dist/runtime/live.d.mts +1 -1
  309. package/dist/runtime/live.mjs +1 -1
  310. package/dist/runtime/log.d.mts +3 -3
  311. package/dist/runtime/log.mjs +26 -18
  312. package/dist/runtime/migration-handler-mysql.d.mts +2 -4
  313. package/dist/runtime/migration-handler-mysql.mjs +2 -3
  314. package/dist/runtime/migration-handler-pg.d.mts +2 -4
  315. package/dist/runtime/migration-handler-pg.mjs +2 -3
  316. package/dist/runtime/migration-handler.d.mts +1 -1
  317. package/dist/runtime/migration-handler.mjs +1 -1
  318. package/dist/runtime/queues.d.mts +1 -1
  319. package/dist/runtime/queues.mjs +2 -3
  320. package/dist/runtime/remote/binding-handler.d.mts +1 -3
  321. package/dist/runtime/remote/binding-handler.mjs +3 -4
  322. package/dist/runtime/remote/index.d.mts +1 -3
  323. package/dist/runtime/remote/index.mjs +8 -13
  324. package/dist/runtime/response.d.mts +1 -3
  325. package/dist/runtime/response.mjs +1 -1
  326. package/dist/runtime/route-url.d.mts +2 -2
  327. package/dist/runtime/route-url.mjs +1 -1
  328. package/dist/runtime/routing.d.mts +10 -12
  329. package/dist/runtime/routing.mjs +27 -88
  330. package/dist/runtime/sandbox-container.d.mts +1 -1
  331. package/dist/runtime/sandbox-container.mjs +1 -1
  332. package/dist/runtime/sandbox.d.mts +2 -2
  333. package/dist/runtime/sandbox.mjs +5 -6
  334. package/dist/runtime/seed.d.mts +0 -2
  335. package/dist/runtime/seed.mjs +1 -2
  336. package/dist/runtime/sse-client.d.mts +1 -3
  337. package/dist/runtime/sse-client.mjs +1 -2
  338. package/dist/runtime/sse.d.mts +1 -3
  339. package/dist/runtime/sse.mjs +1 -1
  340. package/dist/runtime/storage.d.mts +1 -3
  341. package/dist/runtime/storage.mjs +2 -3
  342. package/dist/runtime/validator.d.mts +1 -1
  343. package/dist/runtime/validator.mjs +1 -1
  344. package/dist/runtime/ws-server.d.mts +3 -5
  345. package/dist/runtime/ws-server.mjs +3 -4
  346. package/dist/runtime/ws.d.mts +1 -1
  347. package/dist/runtime/ws.mjs +7 -6
  348. package/dist/{sandbox-q3waMc2T.d.mts → sandbox-DE1WsxuB.d.mts} +2 -4
  349. package/dist/{sandbox-container-a9LRUtii.mjs → sandbox-container-BuxhwCgt.mjs} +1 -2
  350. package/dist/{sandbox-container-ChQRum-j.d.mts → sandbox-container-CZFZdMso.d.mts} +0 -2
  351. package/dist/{scan-N9WzdcAl.mjs → scan-DSQtH3oS.mjs} +31 -25
  352. package/dist/{secret-BL6g7mF5.mjs → secret-C_QtTzJG.mjs} +23 -24
  353. package/dist/{serialize-YHvlcG3Q.mjs → serialize-DUuYuaY3.mjs} +2 -4
  354. package/dist/{serialize-DtR8Vwa_.d.mts → serialize-I4EmS-Wf.d.mts} +0 -2
  355. package/dist/{skills-CrUO3PJ0.mjs → skills-D393E4lB.mjs} +4 -5
  356. package/dist/{sqlite-validation-BzKMWnO4.mjs → sqlite-validation-CLJXXN93.mjs} +1 -2
  357. package/dist/{sse-CMvCgjNk.mjs → sse-CxR30yMF.mjs} +1 -2
  358. package/dist/{standard-schema-Fo_vCAZh.d.mts → standard-schema-CuDawHOC.d.mts} +0 -2
  359. package/dist/{static-asset-marker-Btf-6oCD.mjs → static-asset-marker-NR1XS2z5.mjs} +1 -2
  360. package/dist/{subcommand-prompt-D9OhhbGG.mjs → subcommand-prompt-CxJXporl.mjs} +3 -4
  361. package/dist/sveltekit.d.mts +0 -2
  362. package/dist/sveltekit.mjs +2 -3
  363. package/dist/{terminal-log-text-D9ACPOuG.mjs → terminal-log-text-DNsWJREL.mjs} +1 -2
  364. package/dist/{types-w72dljaA.d.mts → types-agfx0alu.d.mts} +0 -4
  365. package/dist/validate-DY1U9rET.mjs +1 -0
  366. package/dist/{validate-CnZPMq4q.mjs → validate-Ddzl-IwT.mjs} +4 -5
  367. package/dist/{validation-error-Dg9Recn1.mjs → validation-error-rDVbUJet.mjs} +2 -4
  368. package/dist/{validator-BTOu0fB0.mjs → validator-CTfmzZYb.mjs} +2 -5
  369. package/dist/{version-metadata-DmaZNTYW.mjs → version-metadata-Blf5H9BQ.mjs} +5 -6
  370. package/dist/{worker-conditions-AWFRcFxR.mjs → worker-conditions-CBZ0RYsZ.mjs} +1 -2
  371. package/dist/wrangler-CPRX2d9A.mjs +1 -0
  372. package/dist/{wrangler-CDiEBCdS.mjs → wrangler-p-kLCJqF.mjs} +81 -15
  373. package/dist/{wrapper-CEiDeCqD.mjs → wrapper-iejSJDwL.mjs} +18 -15
  374. package/dist/{ws-D1zWiB_P.d.mts → ws-DzBD-NUj.d.mts} +4 -5
  375. package/dist/{yarn-pnp-DLbEFMT0.mjs → yarn-pnp-DgWbE7z5.mjs} +2 -3
  376. package/docs/guide/auth.md +1 -1
  377. package/docs/guide/database.md +4 -4
  378. package/docs/guide/deployment.md +1 -1
  379. package/docs/guide/edge/headers.md +2 -6
  380. package/docs/guide/edge/redirects.md +22 -0
  381. package/docs/guide/edge/static-assets.md +0 -10
  382. package/docs/guide/email/domains.md +3 -1
  383. package/docs/guide/email/receiving.md +3 -3
  384. package/docs/guide/email/sending.md +1 -1
  385. package/docs/guide/pages-routing/actions-and-forms.md +26 -5
  386. package/docs/guide/pages-routing/islands.md +2 -2
  387. package/docs/guide/pages-routing/loaders.md +3 -3
  388. package/docs/guide/pages-routing/markdown.md +6 -6
  389. package/docs/guide/pages-routing/overview.md +34 -27
  390. package/docs/guide/platform/administration/email.md +6 -8
  391. package/docs/guide/platform/installation/credentials.md +6 -6
  392. package/docs/guide/platform/installation/maintenance.md +10 -24
  393. package/docs/guide/platform/installation/prerequisites.md +1 -1
  394. package/docs/guide/platform/installation/setup.md +1 -1
  395. package/docs/guide/platform/installation/uninstall.md +1 -1
  396. package/docs/guide/queues.md +4 -8
  397. package/docs/guide/self-hosted-platform.md +3 -3
  398. package/docs/guide/server-routing.md +8 -6
  399. package/docs/guide/ssg.md +8 -0
  400. package/docs/guide/type-safety.md +42 -0
  401. package/docs/guide/typed-fetch.md +1 -1
  402. package/docs/guide/websockets.md +1 -1
  403. package/docs/integrations/cloudflare.md +17 -8
  404. package/docs/integrations/frameworks/analog.md +1 -1
  405. package/docs/integrations/frameworks/nuxt.md +1 -1
  406. package/docs/integrations/frameworks/sveltekit.md +1 -1
  407. package/docs/integrations/frameworks/tanstack-start.md +1 -1
  408. package/docs/integrations/hono.md +5 -5
  409. package/docs/reference/api/auth.md +6 -2
  410. package/docs/reference/api/deploy.md +15 -11
  411. package/docs/reference/api/pages.md +10 -0
  412. package/docs/reference/api/plugin.md +4 -4
  413. package/docs/reference/api/resources.md +4 -1
  414. package/docs/reference/api/rewrites.md +20 -2
  415. package/docs/reference/api/types.md +41 -0
  416. package/docs/reference/api.md +2 -2
  417. package/docs/reference/cli/database.md +15 -9
  418. package/docs/reference/cli/deploy.md +10 -9
  419. package/docs/reference/cli/email.md +4 -2
  420. package/docs/reference/cli/platform-installation.md +2 -2
  421. package/docs/reference/cli/project.md +2 -2
  422. package/docs/reference/cli/secrets.md +3 -1
  423. package/docs/reference/cli/setup.md +3 -3
  424. package/docs/reference/cli.md +1 -1
  425. package/docs/reference/config.md +12 -2
  426. package/package.json +35 -31
  427. package/sandbox.Dockerfile +1 -1
  428. package/schema.json +4 -0
  429. package/skills/void/SKILL.md +1 -1
  430. package/dist/auth-DkcFflXV.d.mts +0 -42
  431. package/dist/cf-build-output-DlBkWdNU.mjs +0 -1
  432. package/dist/client-DyxPQnF_.mjs +0 -1
  433. package/dist/collect-BWhkgtAn.mjs +0 -1
  434. package/dist/config-BTu1o3Dc.mjs +0 -49
  435. package/dist/deploy-CtHE2A3R.mjs +0 -2
  436. package/dist/discover-D4TPKo57.mjs +0 -1
  437. package/dist/gen-TgXy93Rr.mjs +0 -1
  438. package/dist/help-qOZr3wng.mjs +0 -1
  439. package/dist/login-Cdo8Aco1.mjs +0 -1
  440. package/dist/migrate-COPncCGx.mjs +0 -1
  441. package/dist/operator-cmd-DDiX7Y3f.mjs +0 -1
  442. package/dist/output-BW9uK099.mjs +0 -1
  443. package/dist/plan-CKX_jWnD.mjs +0 -1
  444. package/dist/platform-args-BC8_hsDj.mjs +0 -1
  445. package/dist/prepare-B3VrSF1Z.mjs +0 -1
  446. package/dist/project-slug-6cyz8E7k.mjs +0 -1
  447. package/dist/resolve-project-DD1vu8s9.mjs +0 -1
  448. package/dist/route-url-BgPja1GS.d.mts +0 -5
  449. package/dist/route-url-BjGv_KKY.mjs +0 -28
  450. package/dist/validate-D7Wn8PUX.mjs +0 -1
  451. package/dist/wrangler-DOPr4jyI.mjs +0 -1
@@ -119,7 +119,7 @@ import { getSession, getUser, requireAuth } from 'void/auth';
119
119
  - `getSession()` returns `{ user, session } | null`
120
120
  - `requireAuth(c)` returns the authenticated user or throws `401`
121
121
 
122
- Import `AuthUser` and `AuthSession` from `void/auth` for type annotations. See their fields in the [API reference](../reference/api/auth.md#authuser).
122
+ Import `AuthUser` and `AuthSession` from `void/auth` for type annotations. They include the fields your Better Auth plugins and `user.additionalFields` add, such as `role` from `admin()`. See their fields in the [API reference](../reference/api/auth.md#authuser).
123
123
 
124
124
  ## Behavior
125
125
 
@@ -56,8 +56,8 @@ Define your tables in `db/schema.ts` using column helpers from `void/schema-d1`,
56
56
  ::: code-group
57
57
 
58
58
  ```ts [SQLite (D1)]
59
- import { sql } from 'void/db';
60
59
  // db/schema.ts
60
+ import { sql } from 'void/db';
61
61
  import { sqliteTable, text, integer } from 'void/schema-d1';
62
62
 
63
63
  export const users = sqliteTable('users', {
@@ -314,8 +314,8 @@ export const insertUserSchema = createInsertSchema(users, {
314
314
  ```
315
315
 
316
316
  ```ts [Valibot]
317
- import { pipe, minLength, email } from 'valibot';
318
317
  // db/schema.ts
318
+ import { pipe, minLength, email } from 'valibot';
319
319
  import { createInsertSchema } from 'void/drizzle-valibot';
320
320
 
321
321
  export const insertUserSchema = createInsertSchema(users, {
@@ -325,8 +325,8 @@ export const insertUserSchema = createInsertSchema(users, {
325
325
  ```
326
326
 
327
327
  ```ts [ArkType]
328
- import { type } from 'arktype';
329
328
  // db/schema.ts
329
+ import { type } from 'arktype';
330
330
  import { createInsertSchema } from 'void/drizzle-arktype';
331
331
 
332
332
  export const insertUserSchema = createInsertSchema(users, {
@@ -342,8 +342,8 @@ export const insertUserSchema = createInsertSchema(users, {
342
342
  Use the derived schema in your route handlers with [`withValidator()`](./server-routing.md#validation):
343
343
 
344
344
  ```ts
345
- import { users, insertUserSchema } from '@schema';
346
345
  // routes/api/users/index.ts
346
+ import { users, insertUserSchema } from '@schema';
347
347
  import { defineHandler } from 'void';
348
348
  import { db } from 'void/db';
349
349
 
@@ -35,7 +35,7 @@ void db generate
35
35
 
36
36
  Review and commit the SQL, then deploy again. Rollback does not reverse database migrations. See [Database](./database.md) for the local workflow.
37
37
 
38
- On your own Cloudflare account, deploy saves a D1 [Time Travel](https://developers.cloudflare.com/d1/reference/time-travel/) restore point before it applies pending migrations and prints the [`void db restore`](../reference/cli/database.md#void-db-restore) command for it. If no restore point can be saved, deploy stops before it migrates. If deploy fails after it applied the migrations, for example when the upload fails, it prints the command again. Usually you fix the error and deploy again; restore only if the live version cannot run against the new schema. To recover from a bad migration, roll back the code with `void project rollback` if the new version is live, restore the database, then fix or remove the migration before you deploy again. After a one-off `void deploy --platform cloudflare`, add `--platform cloudflare` to each of these commands. Restoring discards every write made after the restore point. Restore points expire after 7 days on Workers Free and 30 days on Workers Paid; after that, undo a migration with a new one.
38
+ For D1 on your own Cloudflare account, deploy saves a restore point before applying migrations and prints a [`void db restore`](../reference/cli/database.md#void-db-restore) command. Use it to recover from a bad migration, then fix the migration before deploying again. A restore discards writes made after that point; check that your deployed code works with the restored schema. See the command reference for the recovery steps and retention limits.
39
39
 
40
40
  ### Environment variables
41
41
 
@@ -35,13 +35,9 @@ Header rules do not apply to ISR cache responses.
35
35
 
36
36
  ### Cookie headers
37
37
 
38
- On a [Void platform](../deployment.md#deploy-to-a-team-platform), apps usually share an application domain, such as `apps.example.com`. Header rules on a platform deploy change two headers on all hostnames of the app, including custom domains:
38
+ On a [Void platform](../deployment.md#deploy-to-a-team-platform), set cookies in your app's response. Header rules ignore `Set-Cookie`, remove `"cookies"` from `Clear-Site-Data`, and ignore `Clear-Site-Data` rules containing `"*"`. You can use directives such as `"cache"` and `"storage"` in header rules.
39
39
 
40
- - Void ignores `Set-Cookie` in header rules.
41
- - Void removes the `"cookies"` directive from `Clear-Site-Data` in header rules. Other directives, such as `"cache"` and `"storage"`, still apply.
42
- - Void ignores the full value of a `Clear-Site-Data` rule that includes `"*"`. The response then keeps the `Clear-Site-Data` value from your app's response, without `"cookies"`. If that value also includes `"*"`, the response has no `Clear-Site-Data`.
43
-
44
- This stops a header rule from setting or clearing cookies for other apps on the same domain. These limits apply only to header rules. Your app's own response can set cookies and send `Clear-Site-Data`, and on a shared domain those can affect other apps. See [Domains and Resources](../platform/installation/domains.md#adding-a-domain).
40
+ These limits apply on all of your app's hostnames, including custom domains, to protect cookies for other apps on the shared domain. Your app's own cookie headers can still affect those apps, so scope cookies carefully. See [Domains and Resources](../platform/installation/domains.md#adding-a-domain).
45
41
 
46
42
  During local development, with `void deploy --platform cloudflare`, and on [other runtimes](../deployment.md#other-runtimes), header rules apply both headers as written.
47
43
 
@@ -51,6 +51,28 @@ Path-only sources apply to every domain on the project. Host-prefixed sources ap
51
51
 
52
52
  The source must use `https://` and a literal hostname without wildcards or a port. Add the domain to your project with `void domain add` before deploying the rule. A domain awaiting certificate verification starts redirecting once it becomes active.
53
53
 
54
+ ## HTTP to HTTPS
55
+
56
+ Set `routing.alwaysUseHttps` to redirect HTTP requests to HTTPS:
57
+
58
+ ```ts
59
+ import { defineConfig } from 'void/config';
60
+
61
+ export default defineConfig({
62
+ routing: {
63
+ alwaysUseHttps: true,
64
+ },
65
+ });
66
+ ```
67
+
68
+ Void returns a permanent `308` redirect that preserves the path, query string, and request method. The option defaults to `false`. Localhost and loopback addresses stay on HTTP for local development and previews.
69
+
70
+ This option requires the Cloudflare target and works for Void apps and static sites on either deployment platform.
71
+
72
+ For direct Cloudflare deployments, also enable [Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) on your zone to cover assets served directly by Cloudflare.
73
+
74
+ For direct Cloudflare deployments of SvelteKit, Nuxt, Astro, Analog, TanStack Start, React Router, or vinext, configure HTTPS in the framework or your Cloudflare zone. Use `routing.alwaysUseHttps` only for their static builds, deployed with `--dir` or `inference.appType`.
75
+
54
76
  ## Framework `_redirects` files
55
77
 
56
78
  Void reads `_redirects` files produced by supported frameworks. You can also place one in Vite's `publicDir`:
@@ -37,16 +37,6 @@ With `void deploy --platform cloudflare`, generated JavaScript bundles with cont
37
37
 
38
38
  Use [Custom Headers](./headers) to choose a cache policy for other files. Apply immutable caching only to URLs that change whenever their content changes.
39
39
 
40
- Cloudflare serves these fingerprinted JavaScript bundles without starting your Worker, so they do not count as Worker requests, when your app:
41
-
42
- - has no global middleware
43
- - has no header, redirect, rewrite or fallback rules, and no `routing.notFound` setting
44
- - uses the default `base` of `/`
45
- - has no route or page that matches paths in the assets directory (`assets/` by default)
46
- - builds at most 99 fingerprinted bundles
47
-
48
- Otherwise these bundles go through your Worker and keep the same caching.
49
-
50
40
  ## Non-hashed assets
51
41
 
52
42
  Other static files, such as `index.html` and `favicon.ico`, are cached until the next deploy. You do not need to purge them manually.
@@ -16,7 +16,9 @@ void email domain add acme.com
16
16
 
17
17
  `add` opens a Cloudflare API-token template. Restrict the token to the selected account and mail zone before creating it; Workers Scripts permission applies across that account. The CLI accepts a masked paste or a newly copied token and asks you to confirm those restrictions. The platform encrypts the credential for the zone connection, so projects sharing that zone do not need separate ingress Workers.
18
18
 
19
- Platform-managed custom inbound email requires the apex of a Cloudflare zone. Cloudflare’s catch-all only covers that apex, so a subdomain of the selected zone cannot receive arbitrary addresses. `add` refuses to register a new apex that already has MX records, or whose catch-all already routes elsewhere, so it never takes over mail hosted with another provider such as Microsoft 365 or Google Workspace. Use an apex that has no mail yet, or the platform’s shared mail address. To only send from an apex that keeps its current mail provider, ask your platform administrator to register it as [outbound-only](../platform/administration/email.md#sending-from-a-domain-that-already-receives-mail). Running `add` again for a registered apex, for example to renew its token, keeps working. Each custom apex belongs to one project; a project can register more than one apex.
19
+ For inbound mail, use a Cloudflare zone apex with no existing mail service, such as `example.com`. Each apex belongs to one project, and a project can register several. Existing MX records or a catch-all pointing elsewhere block registration to protect your current mail service.
20
+
21
+ To keep receiving mail through another provider, ask your platform administrator to register the domain as [outbound-only](../platform/administration/email.md#sending-from-a-domain-that-already-receives-mail). You can also use the platform's shared mail address.
20
22
 
21
23
  If setup is interrupted, use `void email domain status <domain>` to inspect the saved operation before retrying.
22
24
 
@@ -94,15 +94,15 @@ deployed `email/` handlers without per-project DNS setup once the platform has v
94
94
  handlers once its inbound readiness is `ready`. Use `void email domain status`
95
95
  to check current provider routing and any remaining setup steps.
96
96
 
97
- A project with an [email alias](../../reference/cli/email.md#void-email-alias) also receives at `<alias>+anything@<mail domain>`. Routing ignores which prefix was used: with the slug `acme-store` and the alias `acme`, both `acme-store+support@…` and `acme+support@…` reach `email/support.ts`.
97
+ A project with an [email alias](../../reference/cli/email.md#void-email-alias) also receives at `<alias>+anything@<mail domain>`. For example, both `acme-store+support@…` and its alias `acme+support@…` reach `email/support.ts`.
98
98
 
99
99
  For direct deployments, follow [Your own Cloudflare account](./domains.md#your-own-cloudflare-account) to configure inbound addresses.
100
100
 
101
- The local dev server provides the outbound email inbox but has no inbound email trigger. Test inbound handlers with `createInboundTestHarness` below.
101
+ Test inbound handlers locally with `createInboundTestHarness` below.
102
102
 
103
103
  ## Testing inbound handlers {#testing-inbound-handlers}
104
104
 
105
- Use `createInboundTestHarness` to capture replies, forwards, and rejections. For shared platform mail, pass the full address including the project prefix, such as [`acme+support+abc-123@acme.dev`](mailto:acme+support+abc-123@acme.dev). For direct Cloudflare mail, set `slug: null` and use [`support+abc-123@mail.acme.com`](mailto:support+abc-123@mail.acme.com).
105
+ Use `createInboundTestHarness` to capture replies, forwards, and rejections. For shared platform mail, pass the full address including the project prefix, such as `acme+support+abc-123@acme.dev`. For direct Cloudflare mail, set `slug: null` and use `support+abc-123@mail.acme.com`.
106
106
 
107
107
  ```ts
108
108
  import { describe, it, expect } from 'vitest';
@@ -195,7 +195,7 @@ The inbox keeps the most recent 100 messages through HMR and clears on a full se
195
195
 
196
196
  The dev inbox works in native Void apps, TanStack Start, and React Router. It is unavailable in SvelteKit, Nuxt, Analog, and Astro; sends from those apps return `BINDING_MISSING`. Use `createEmailTestHarness` from `void/email/testing` to capture sends in tests. If a configured inbox cannot be reached, `sendEmail` returns `UPSTREAM_ERROR` without sending.
197
197
 
198
- `sendInDev` is deprecated. During local development it skips the inbox and returns `BINDING_MISSING`, so it never delivers. Remove it, and deploy the app to test real delivery.
198
+ Remove the deprecated `sendInDev` option to use the local inbox. Deploy the app to test real delivery.
199
199
 
200
200
  ## Testing {#testing}
201
201
 
@@ -11,8 +11,8 @@ Use an action to change server data from a form or button. Define it in the page
11
11
  Export `action` from a `.server.ts` file. Use `withValidator()` with a [schema-derived validator](../database.md#schema-derived-validators) to validate the request body:
12
12
 
13
13
  ```ts
14
- import { users, insertUserSchema } from '@schema';
15
14
  // pages/users/index.server.ts
15
+ import { users, insertUserSchema } from '@schema';
16
16
  import { defineHandler } from 'void';
17
17
  import { db } from 'void/db';
18
18
 
@@ -163,7 +163,7 @@ The types are inferred from your action's `withValidator()` schema in the compan
163
163
  | `clearErrors(...fields)` | Clear validation errors. Field names autocomplete. |
164
164
  | `clearError()` | Clear `error`. |
165
165
 
166
- Use `setError()` to display errors from your own client-side validation. Setting an error preserves errors on other fields. Changing a field clears that field's validation error automatically (`setData` in React and Solid, or assigning to `data` in Vue and Svelte).
166
+ Use `setError()` for client-side validation. Editing a field clears its error automatically.
167
167
 
168
168
  For a native React form, use `form.post`, `form.put`, `form.patch`, or `form.delete` as a native form action. For an awaitable mutation, use `action()`. In Vue, Svelte, and Solid, form submissions return `Promise<void>`; catch thrown errors or use your framework's error handling.
169
169
 
@@ -175,15 +175,36 @@ const form = useForm('/users/:id', { name: '' }, { params: { id: '42' } });
175
175
  <Form form={form} method="put">{/* submits to /users/42 */}</Form>
176
176
  ```
177
177
 
178
- Create forms often need empty fields again after a successful save. Either pass `resetOnSuccess: true` in the third argument, or call `form.reset({ initial: true })` when `form.wasSuccessful` becomes `true`.
178
+ To clear a create form after saving, pass `resetOnSuccess: true` in the third argument. Use `form.reset({ initial: true })` to restore the original values manually.
179
+
180
+ ### React submission callbacks
181
+
182
+ In React, pass `onSuccess` and `onError` to `useForm()` to respond to a submission:
183
+
184
+ ```tsx
185
+ const form = useForm(
186
+ '/users',
187
+ { name: '', email: '' },
188
+ {
189
+ onSuccess: () => setDialogOpen(false),
190
+ onError: (error) => {
191
+ console.error(error);
192
+ },
193
+ },
194
+ );
195
+ ```
196
+
197
+ `onError` receives a field-error map or a `VoidActionError`. Callbacks can be async; `form.pending` stays true until they finish, and thrown errors reach the nearest React error boundary. Callbacks run before React commits the updated UI, so use an effect or ref callback to focus an element that appears after submission.
198
+
199
+ Vue, Svelte, and Solid submissions return a promise instead; use `await form.post()` to run work after a submission.
179
200
 
180
201
  ## Named Actions
181
202
 
182
203
  When a page needs multiple mutations, such as updating and deleting a user on the same page, export `actions` (plural) instead of `action`:
183
204
 
184
205
  ```ts
185
- import { users, updateUserSchema } from '@schema';
186
206
  // pages/users/[id].server.ts
207
+ import { users, updateUserSchema } from '@schema';
187
208
  import { defineHandler } from 'void';
188
209
  import { db, eq } from 'void/db';
189
210
 
@@ -203,7 +224,7 @@ export const actions = {
203
224
  };
204
225
  ```
205
226
 
206
- Named actions are dispatched via a `?actionName` suffix on the URL (e.g. `/users/42?update`). The client primitives `useForm` and `action()` handle this automatically. The action key stays out of the page URL. When `POST /users/42?update&tab=profile` renders the page again, `useForm` and `action()` leave the address bar at `/users/42?tab=profile`, and `c.redirect('/users/42')` goes to `/users/42?tab=profile`.
227
+ Named actions use a `?actionName` suffix, such as `/users/42?update`. `useForm` and `action()` handle this automatically. After a POST action renders the page or uses a default `c.redirect()`, the page URL keeps ordinary query parameters: `/users/42?update&tab=profile` becomes `/users/42?tab=profile`. See [redirect query parameters](../../reference/api/rewrites.md#c-rewrite-destination) for redirects that preserve the request method.
207
228
 
208
229
  Use `action` or `actions` in a file, not both.
209
230
 
@@ -135,8 +135,8 @@ let { posts } = $props();
135
135
  ```
136
136
 
137
137
  ```tsx [Solid]
138
- import { For } from 'solid-js';
139
138
  // pages/blog/index.island.tsx
139
+ import { For } from 'solid-js';
140
140
  import Counter from './_Counter' with { island: 'load' };
141
141
  import PostForm from './_PostForm' with { island: 'visible' };
142
142
 
@@ -209,7 +209,7 @@ After a successful action, an island page reloads or redirects through `window.l
209
209
 
210
210
  ## Forms
211
211
 
212
- Island pages cannot use `useForm` because it depends on the Void Router. Use `useIslandForm` instead. It has the same form state, but its submit helpers take the action URL and use `fetch()` directly:
212
+ Use `useIslandForm` for forms in island components. It provides the same form state as `useForm`, and its submit helpers take the action URL:
213
213
 
214
214
  ::: code-group
215
215
 
@@ -11,8 +11,8 @@ A loader fetches the data a page needs. Define it in a companion `.server.ts` fi
11
11
  `loader` runs on GET requests and returns an object that becomes the page's props:
12
12
 
13
13
  ```ts
14
- import { users } from '@schema';
15
14
  // pages/users/index.server.ts
15
+ import { users } from '@schema';
16
16
  import { defineHandler } from 'void';
17
17
  import type { InferProps } from 'void';
18
18
  import { db } from 'void/db';
@@ -79,8 +79,8 @@ defineProps<Props>();
79
79
  ```
80
80
 
81
81
  ```tsx [Solid]
82
- import { For } from 'solid-js';
83
82
  // pages/users/index.tsx
83
+ import { For } from 'solid-js';
84
84
  import type { Props } from './index.server';
85
85
 
86
86
  export default function UsersPage(props: Props) {
@@ -102,8 +102,8 @@ export default function UsersPage(props: Props) {
102
102
  Use `defer()` for slow data. The page renders immediately and receives the result when it is ready:
103
103
 
104
104
  ```ts
105
- import { projects } from '@schema';
106
105
  // pages/dashboard.server.ts
106
+ import { projects } from '@schema';
107
107
  import { defineHandler, defer } from 'void';
108
108
  import type { InferProps } from 'void';
109
109
  import { db } from 'void/db';
@@ -64,9 +64,9 @@ Add the plugin to your Vite config **after** the framework adapter:
64
64
  ::: code-group
65
65
 
66
66
  ```ts [React]
67
+ // vite.config.ts
67
68
  import { voidMarkdown } from '@void/md/plugin';
68
69
  import { voidReact } from '@void/react/plugin';
69
- // vite.config.ts
70
70
  import { defineConfig } from 'vite';
71
71
  import { voidPlugin } from 'void';
72
72
 
@@ -76,9 +76,9 @@ export default defineConfig({
76
76
  ```
77
77
 
78
78
  ```ts [Vue]
79
+ // vite.config.ts
79
80
  import { voidMarkdown } from '@void/md/plugin';
80
81
  import { voidVue } from '@void/vue/plugin';
81
- // vite.config.ts
82
82
  import { defineConfig } from 'vite';
83
83
  import { voidPlugin } from 'void';
84
84
 
@@ -88,9 +88,9 @@ export default defineConfig({
88
88
  ```
89
89
 
90
90
  ```ts [Svelte]
91
+ // vite.config.ts
91
92
  import { voidMarkdown } from '@void/md/plugin';
92
93
  import { voidSvelte } from '@void/svelte/plugin';
93
- // vite.config.ts
94
94
  import { defineConfig } from 'vite';
95
95
  import { voidPlugin } from 'void';
96
96
 
@@ -100,9 +100,9 @@ export default defineConfig({
100
100
  ```
101
101
 
102
102
  ```ts [Solid]
103
+ // vite.config.ts
103
104
  import { voidMarkdown } from '@void/md/plugin';
104
105
  import { voidSolid } from '@void/solid/plugin';
105
- // vite.config.ts
106
106
  import { defineConfig } from 'vite';
107
107
  import { voidPlugin } from 'void';
108
108
 
@@ -230,7 +230,7 @@ export default function DocsLayout(props) {
230
230
 
231
231
  :::
232
232
 
233
- Island components on a Markdown page can call `useFrontmatter()` too. A page with islands includes its frontmatter in the HTML for them to read in the browser. Keep private values out of the frontmatter of those pages.
233
+ Island components can also call `useFrontmatter()`. Keep frontmatter on pages with islands safe to share with the browser.
234
234
 
235
235
  ## Pages Virtual Module
236
236
 
@@ -241,7 +241,7 @@ import pages from '@void/md/pages';
241
241
  // [{ path: "/docs/getting-started", title: "Getting Started", frontmatter: {...}, headings: [...] }, ...]
242
242
  ```
243
243
 
244
- The list holds only the pages for the current [environment](./overview.md#environment-only-pages): `.dev` pages on the dev server, `.prod` pages in builds. The suffix is dropped from `path`: `debug.dev.md` is listed as `/debug`.
244
+ The list follows [page environment suffixes](./overview.md#environment-only-pages): `debug.dev.md` appears as `/debug` during development.
245
245
 
246
246
  Each entry has this shape:
247
247
 
@@ -41,8 +41,8 @@ Add both plugins to your Vite config:
41
41
  ::: code-group
42
42
 
43
43
  ```ts [React]
44
- import { voidReact } from '@void/react/plugin';
45
44
  // vite.config.ts
45
+ import { voidReact } from '@void/react/plugin';
46
46
  import { defineConfig } from 'vite';
47
47
  import { voidPlugin } from 'void';
48
48
 
@@ -52,8 +52,8 @@ export default defineConfig({
52
52
  ```
53
53
 
54
54
  ```ts [Vue]
55
- import { voidVue } from '@void/vue/plugin';
56
55
  // vite.config.ts
56
+ import { voidVue } from '@void/vue/plugin';
57
57
  import { defineConfig } from 'vite';
58
58
  import { voidPlugin } from 'void';
59
59
 
@@ -63,8 +63,8 @@ export default defineConfig({
63
63
  ```
64
64
 
65
65
  ```ts [Svelte]
66
- import { voidSvelte } from '@void/svelte/plugin';
67
66
  // vite.config.ts
67
+ import { voidSvelte } from '@void/svelte/plugin';
68
68
  import { defineConfig } from 'vite';
69
69
  import { voidPlugin } from 'void';
70
70
 
@@ -74,8 +74,8 @@ export default defineConfig({
74
74
  ```
75
75
 
76
76
  ```ts [Solid]
77
- import { voidSolid } from '@void/solid/plugin';
78
77
  // vite.config.ts
78
+ import { voidSolid } from '@void/solid/plugin';
79
79
  import { defineConfig } from 'vite';
80
80
  import { voidPlugin } from 'void';
81
81
 
@@ -94,16 +94,9 @@ Pages can be flat files such as `about.vue` or directory-based routes such as `a
94
94
 
95
95
  <PagesFileTree />
96
96
 
97
- Keep one file per route. Void reports an error when two page files resolve to the same path, such as `about.vue` and `about/index.vue`, or the same page in two route groups.
98
-
99
- Each page can have a companion `.server.ts`, `.server.tsx`, `.server.js`, `.server.jsx`, `.server.mts`, or `.server.mjs` file that runs exclusively on the server. Use `.server.tsx` or `.server.jsx` when the companion contains JSX (see [JSX handlers](../server-routing.md#jsx-handlers) for the JSX runtime). A companion belongs to its matching page and does not create a separate route:
100
-
101
- | File | Role |
102
- | ---------------------- | ------------------------------ |
103
- | `pages/foo.tsx` | Page component at `/foo` |
104
- | `pages/foo.server.tsx` | Server companion for that page |
97
+ Use one page file per URL in each environment.
105
98
 
106
- A companion can export:
99
+ Pair a page with a `.server.ts` file for server code, such as `about.server.ts` for `about.vue`. Companions also support `.js`, `.mts`, `.mjs`, and [JSX](../server-routing.md#jsx-handlers) with `.tsx` or `.jsx`. They can export:
107
100
 
108
101
  - A [**loader**](./loaders), which runs on `GET` and returns the data that becomes the page component's props
109
102
  - [**Actions**](./actions-and-forms), which handle mutations from forms and programmatic calls. Export a single `action` or multiple [named actions](./actions-and-forms#named-actions) when a page has several mutations
@@ -113,7 +106,7 @@ File-based routing rules are the same as [server routing](../server-routing.md):
113
106
 
114
107
  ### Environment-only pages
115
108
 
116
- Add a `.dev` or `.prod` suffix before the extension to include a page in only one environment. The suffix is not part of the URL:
109
+ Add a `.dev` or `.prod` suffix before the extension to choose when a page is available:
117
110
 
118
111
  ```
119
112
  pages/
@@ -126,12 +119,9 @@ pages/
126
119
 
127
120
  `.dev` pages run only on the dev server; `.prod` pages run in builds, deployments, and production previews.
128
121
 
129
- - A `.dev` page and a `.prod` page can share a URL. A plain page and a suffixed page for the same URL is an error wherever both run: `home.tsx` with `home.dev.tsx` fails on the dev server, and `home.tsx` with `home.prod.tsx` fails the build.
130
- - The suffix goes **before** `.island`: `chart.dev.island.tsx` is a development-only island page. `chart.island.dev.tsx` is not an island page.
131
- - A companion repeats the suffix: `home.dev.server.ts` belongs to `home.dev.tsx`.
132
- - Suffixes apply to page files only. Layouts take no suffix.
133
- - A resource used only by `.dev` pages and their companions is not provisioned for production.
134
- - The dev server and builds generate types for their own environment. `void prepare` generates types for both.
122
+ Keep the suffix in companion filenames (`home.dev.server.ts`) and place it before `.island` for island pages (`chart.dev.island.tsx`). Layouts are shared across environments.
123
+
124
+ Production deploys exclude resources used only by `.dev` pages and their companions. Run `void prepare` to generate types for both environments.
135
125
 
136
126
  ## How Navigation Works
137
127
 
@@ -163,42 +153,48 @@ Render and prerender flags combine like this:
163
153
  | Island page + `ssr = false` | Invalid. Island pages already use the island renderer. |
164
154
  | `output: "static"` + `prerender` unset | Auto-prerender pages that have known paths, including client-only shells. |
165
155
 
166
- Use the `Link` component for SPA navigation between pages. It renders an `<a>` tag that intercepts clicks and navigates without a full page reload:
156
+ ### Typed navigation
157
+
158
+ Use the `Link` component for SPA navigation between pages. Build dynamic URLs with [`routeUrl()`](../type-safety.md#typed-urls-and-navigation) to check the route pattern and its parameters:
167
159
 
168
160
  ::: code-group
169
161
 
170
162
  ```tsx [React]
171
163
  import { Link } from "@void/react";
164
+ import { routeUrl } from 'void/routes';
172
165
 
173
166
  <Link href="/users">Users</Link>
174
- <Link href={`/users/${id}`}>View</Link>
167
+ <Link href={routeUrl('/users/:id', { params: { id } })}>View</Link>
175
168
  ```
176
169
 
177
170
  ```vue [Vue]
178
171
  <script setup lang="ts">
179
172
  import { Link } from '@void/vue';
173
+ import { routeUrl } from 'void/routes';
180
174
  </script>
181
175
 
182
176
  <template>
183
177
  <Link href="/users">Users</Link>
184
- <Link :href="`/users/${id}`">View</Link>
178
+ <Link :href="routeUrl('/users/:id', { params: { id } })">View</Link>
185
179
  </template>
186
180
  ```
187
181
 
188
182
  ```svelte [Svelte]
189
183
  <script>
190
184
  import { Link } from "@void/svelte";
185
+ import { routeUrl } from 'void/routes';
191
186
  </script>
192
187
 
193
188
  <Link href="/users">Users</Link>
194
- <Link href={`/users/${id}`}>View</Link>
189
+ <Link href={routeUrl('/users/:id', { params: { id } })}>View</Link>
195
190
  ```
196
191
 
197
192
  ```tsx [Solid]
198
193
  import { Link } from "@void/solid";
194
+ import { routeUrl } from 'void/routes';
199
195
 
200
196
  <Link href="/users">Users</Link>
201
- <Link href={`/users/${id}`}>View</Link>
197
+ <Link href={routeUrl('/users/:id', { params: { id } })}>View</Link>
202
198
  ```
203
199
 
204
200
  :::
@@ -232,17 +228,28 @@ import { Link } from "@void/solid";
232
228
 
233
229
  `prefetch` and `reloadDocument` work only with GET links. GET `data` becomes query parameters; use scalar values or arrays.
234
230
 
235
- For programmatic navigation, use `useRouter()`:
231
+ For programmatic navigation, use `useRouter()`. Pass a typed destination object to `visit()`, `prefetch()`, or `flush()`:
236
232
 
237
233
  ```ts
238
234
  import { useRouter } from '@void/vue'; // or "@void/react", "@void/svelte", "@void/solid"
235
+ import type { RouteDestination } from 'void/routes';
239
236
 
240
237
  const router = useRouter();
241
- router.visit('/users');
238
+ const profile = {
239
+ pathname: '/users/:id',
240
+ params: { id: 42 },
241
+ query: { tab: 'activity' },
242
+ } satisfies RouteDestination;
243
+
244
+ await router.prefetch(profile);
245
+ await router.visit(profile);
246
+ router.flush(profile); // clear its prefetched data
242
247
  router.refresh(); // re-fetch current page props, keeping the same history entry
243
248
  router.visit('/logout', { method: 'POST' }); // non-GET navigation
244
249
  ```
245
250
 
251
+ You can also pass URL strings or `URL` instances to these router methods. See [Typed URLs and Navigation](../type-safety.md#typed-urls-and-navigation) for query values, fragments, and catch-all routes.
252
+
246
253
  `router.visit()` updates the page in place for same-origin URLs. `http(s)` URLs on another origin get a full page load, and other schemes such as `javascript:` are rejected.
247
254
 
248
255
  For dynamic route params, use `useParams()` from the same adapter package:
@@ -10,7 +10,7 @@ These commands apply to a platform that enables email. Every project can send fr
10
10
 
11
11
  Shared inbound mail uses one exact routing rule per receiving project and enables Cloudflare’s per-zone plus addressing. Creating a project or deploying an app that only sends mail consumes no inbound rule. Existing rules and the apex catch-all remain in place. Cloudflare normally allows [200 routing rules per domain](https://developers.cloudflare.com/email-service/platform/limits/); remove unused rules or request a higher limit if the shared domain reaches capacity. An unrelated rule for a project’s base address or a plus address blocks its setup until that conflict is removed.
12
12
 
13
- A project owner can give the shared address one permanent, shorter name with `void email alias <name>`. A receiving project with an alias uses two rules, one for the slug and one for the alias, because the slug address keeps working. Setting an alias is refused while a conflicting rule exists or the domain is at its rule limit, and the alias is released only when the project is deleted.
13
+ A project owner can set a permanent, shorter address with [`void email alias <name>`](../../../reference/cli/email.md#void-email-alias). Receiving mail at both the slug and alias uses two routing rules. Resolve conflicting rules and check the domain's rule limit before adding an alias.
14
14
 
15
15
  If recipient creation is interrupted, inspect its retained intent:
16
16
 
@@ -31,7 +31,7 @@ for the recovery requirements.
31
31
 
32
32
  ### Mail that the platform sends {#platform-sender}
33
33
 
34
- The platform sends its own mail, for example invitations, welcome mail, failed-deploy notices, and error alerts. This mail comes from `noreply@<mail domain>`, and the sender name is the platform's display name. Void sets this sender, so you do not need to configure one. Do not set a different sender on the platform Workers in the Cloudflare dashboard. That change stops the next `upgrade`, `repair`, `enable`, or `rollback` until you let Void replace it. See [Platform Workers changed outside Void](/guide/platform/installation/maintenance#workers-changed-outside-void).
34
+ Platform invitations, welcome mail, and deployment alerts use `noreply@<mail domain>` with the platform's display name. Void configures this sender automatically.
35
35
 
36
36
  Mail to an address that is not verified needs Cloudflare Email Sending onboarding and [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans).
37
37
 
@@ -161,10 +161,8 @@ If an apex already receives mail with another provider, such as Microsoft 365 or
161
161
  void platform email domain-add brand.example --project hr-portal --outbound-only
162
162
  ```
163
163
 
164
- The project can then send from any address on the apex, such as `support@brand.example`. It cannot receive mail there: the MX records, the apex SPF record, and incoming mail stay with the current provider.
164
+ The project can then send from any address on the apex, such as `support@brand.example`. Incoming mail, MX records, and the apex SPF record stay with your current provider.
165
165
 
166
- - Cloudflare Email Sending must be available, which needs Workers Paid. Without it, setup is blocked instead of falling back to verified destinations only. Upgrade, then run `domain-sync`.
167
- - Email Sending adds its own records on `cf-bounce.<domain>` and `_dmarc.<domain>`. If Cloudflare reports that existing records conflict with them, for example several DMARC records, setup is blocked and the error lists each record. Fix them, then run `domain-sync`.
168
- - Only administrators can register an outbound-only domain, and it must be a zone apex. The platform's shared mail zone cannot be outbound-only.
169
- - `domain-rotate-secret` does not apply. `domain-remove` stops sending through the platform and leaves the MX records alone.
170
- - To switch an outbound-only domain to platform-managed inbound mail, or back, remove it first and add it again.
166
+ This requires [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans) and Cloudflare Email Sending onboarding. Email Sending adds records at `cf-bounce.<domain>` and `_dmarc.<domain>`. Resolve any reported DNS conflicts, then run `domain-sync`.
167
+
168
+ Only administrators can register outbound-only domains. Choose a zone apex separate from the platform's shared mail zone. Use `domain-remove` to stop sending through the platform. To change between outbound-only and platform-managed inbound mail, remove the domain and add it again.
@@ -70,7 +70,7 @@ Void checks access before provisioning. If it reports a missing permission, upda
70
70
 
71
71
  Choose a shared sender domain and its Cloudflare zone ID. The mail zone may differ from the application zone, but it must belong to the platform's Cloudflare account.
72
72
 
73
- Before you enable email, enable [Cloudflare Email Routing](https://developers.cloudflare.com/email-service/get-started/route-emails/) for the exact shared sender domain and confirm that its MX records point to Cloudflare. For a subdomain, add that name under the zone's **Email Routing → Settings → Subdomains**. Cloudflare adds the required MX and SPF records. The installer's shared-mail bootstrap verifies those records; it does not add them. Keep existing mail-provider records on other domain names in place.
73
+ Before enabling platform email, configure [Cloudflare Email Routing](https://developers.cloudflare.com/email-service/get-started/route-emails/) for the shared sender domain. For a subdomain, add it under **Email Routing → Settings → Subdomains**. Let Cloudflare add the required MX and SPF records, then confirm that the domain's MX records point to Cloudflare.
74
74
 
75
75
  Enabling email lets administrators [register email domains for projects](/guide/platform/administration/email#registering-email-domains-for-projects) and lets projects register destination addresses through the runtime token. The runtime token needs these permissions:
76
76
 
@@ -86,7 +86,7 @@ The zone permissions must include each zone that will carry mail, including the
86
86
 
87
87
  For a new installation, set `VOID_EMAIL_SENDER_DOMAIN` and `VOID_EMAIL_SHARED_ZONE_ID` before `void platform install`. The runtime-token link then preselects these permissions.
88
88
 
89
- For an existing installation, add the permissions to its runtime token first. Edit the token in the Cloudflare dashboard. The token value stays the same. Or set `VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN` to a new token that has all runtime permissions. Then run:
89
+ For an existing installation, edit its runtime token's permissions in Cloudflare, or supply a replacement with `VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN`. Then run:
90
90
 
91
91
  ```sh
92
92
  VOID_EMAIL_SENDER_DOMAIN=mail.example.com \
@@ -94,13 +94,13 @@ VOID_EMAIL_SHARED_ZONE_ID=your-zone-id \
94
94
  void platform upgrade your-installation-id
95
95
  ```
96
96
 
97
- Void records the domain and zone for later upgrades; an ordinary upgrade cannot replace them.
97
+ Void saves this domain and zone for later upgrades. Choose them for the lifetime of the installation.
98
98
 
99
- Before the CLI changes anything or pauses traffic, it checks that the runtime token can read the mail zone and its Email Routing settings, rules, and addresses. If Cloudflare denies a request, the command stops and names each missing permission. Void keeps a saved runtime token, so you can add the permission to the same token and run the command again. The check cannot confirm Edit access or Email Sending, so select those permissions as the table shows.
99
+ If setup reports a missing permission, add it to the runtime token and rerun the command. Select all permissions in the table, including Edit access and Email Sending.
100
100
 
101
- Without `VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN`, `upgrade`, `repair`, `enable`, and `rollback` check the runtime token saved on this machine. The platform can use a newer token, for example one set from another machine. If Cloudflare does not accept the saved token, the CLI shows a warning and continues without the check. To check the token that the platform uses, set `VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN` to it.
101
+ When maintaining the platform from another machine, set `VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN` to the current runtime token so the CLI checks its permissions.
102
102
 
103
- The installer deploys the email gateway, prepares the shared mail route, and verifies inbound readiness before opening platform traffic. If setup fails, fix the problem that the error names, for example a missing permission, the exact-domain MX records, or a routing conflict. Then run the same install or upgrade command again. A fresh install resumes with `void platform install --resume --name <installation-id>`; it continues the recorded email operation after the configuration is corrected.
103
+ The installer configures the email gateway and shared mail route. If setup fails, fix the reported permission, DNS, or routing problem and rerun the command. Resume a fresh installation with `void platform install --resume --name <installation-id>`.
104
104
 
105
105
  ## R2 Upload Credentials
106
106