void 1.4.0 → 1.6.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 (455) hide show
  1. package/README.md +1 -1
  2. package/dist/{account-cmd-HP8bixYo.mjs → account-cmd-DRhmCWcm.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-DDOQwiXk.mjs → application-analysis-HRFsZOv3.mjs} +18 -24
  6. package/dist/{application-routing-4719u_kf.mjs → application-routing-P4TggvWp.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-g2TQbDLD.d.mts → auth-CH4PLAX1.d.mts} +0 -2
  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-CedYpDCy.mjs → auth-link-CVXP1G6G.mjs} +7 -8
  25. package/dist/{auth-migrations-BO27GDNr.mjs → auth-migrations-DDeifS3v.mjs} +1 -2
  26. package/dist/{auth-router-vafo7x8w.mjs → auth-router-D1pGdbvB.mjs} +6 -7
  27. package/dist/{base64-DVrOndmI.mjs → base64-ikl9yBy3.mjs} +1 -2
  28. package/dist/{better-auth-shared-BHB8kiTE.d.mts → better-auth-shared-BJyG2mH0.d.mts} +2 -6
  29. package/dist/{better-auth-shared-7FM3Uk2N.mjs → better-auth-shared-C958aM7W.mjs} +31 -7
  30. package/dist/{build-cmd-9vUAQ1_V.mjs → build-cmd-DmjbuT6d.mjs} +7 -8
  31. package/dist/{cache-jvwLNb0h.mjs → cache-2khBO1MR.mjs} +7 -8
  32. package/dist/{cancel-deploy-Dw0UmWKO.mjs → cancel-deploy-_itbbvY3.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-XpNR9zoh.mjs → cf-build-output-B1C8U83u.mjs} +41 -314
  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-Dg27RzyT.mjs → cf-worker-settings-CARs4Wy9.mjs} +3 -5
  40. package/dist/cli/cli.mjs +66 -76
  41. package/dist/cli/cloudflare-operation-process.mjs +14 -18
  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-CEtr5UOR.mjs +1 -0
  45. package/dist/{client-B3LnB_bE.mjs → client-CoxPEhJq.mjs} +15 -13
  46. package/dist/{cloudflare-auth-DyD_kVFr.mjs → cloudflare-auth-CEu-1Ps_.mjs} +2 -3
  47. package/dist/{cloudflare-cmd-D-b_u3T4.mjs → cloudflare-cmd-fZ6AMSWk.mjs} +7 -8
  48. package/dist/{cloudflare-config-CH1AylZT.mjs → cloudflare-config-eQunqX6A.mjs} +22 -17
  49. package/dist/{cloudflare-connect-zTJh8UnN.mjs → cloudflare-connect-9OZe4XVQ.mjs} +5 -6
  50. package/dist/{cloudflare-operations-Bc-7fN44.mjs → cloudflare-operations-CrskD4_O.mjs} +8 -9
  51. package/dist/{cloudflare-operations-BtulCNOg.mjs → cloudflare-operations-oLvAd9Nd.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-tqMM6DwY.mjs → config-BBlVXZCU.mjs} +5 -6
  57. package/dist/{config-OFOAimzt.mjs → config-BITKQ3O6.mjs} +5 -5
  58. package/dist/{config-BV2ASlpn.mjs → config-BgysUhnm.mjs} +1 -1
  59. package/dist/{config-CAdZVTLN.d.mts → config-CPxJmt4M.d.mts} +4 -6
  60. package/dist/{config-D-6q7EBH.mjs → config-WlvEcL82.mjs} +3 -4
  61. package/dist/config-entry.d.mts +1 -3
  62. package/dist/config-entry.mjs +1 -2
  63. package/dist/{connect-BOM6zvFX.mjs → connect-CKvmkl2R.mjs} +10 -11
  64. package/dist/{create-project-C2K0DN2O.mjs → create-project-BiMmR5wA.mjs} +1 -1
  65. package/dist/{create-project-Bxd02EHN.mjs → create-project-Bq0M8MtO.mjs} +9 -11
  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-Cdvr3zwG.mjs → db-cq5RW4Vy.mjs} +52 -54
  70. package/dist/{db-types-0eCiqYb1.mjs → db-types-C_8amnB0.mjs} +3 -4
  71. package/dist/{delete-lETE6Tpt.mjs → delete-CY4L8fi2.mjs} +7 -8
  72. package/dist/deploy-B029oHlE.mjs +2 -0
  73. package/dist/{deploy-CdM-LAxX.mjs → deploy-D_gEojD2.mjs} +144 -136
  74. package/dist/{deploy-managed-static-DjeBFG2c.mjs → deploy-managed-static-BHVbB_-A.mjs} +33 -40
  75. package/dist/{deploy-transport-DIq_gFTP.mjs → deploy-transport-DEyOUfac.mjs} +6 -7
  76. package/dist/deploy.d.mts +1 -3
  77. package/dist/deploy.mjs +11 -11
  78. package/dist/{dev-inbox-D0jxye_D.mjs → dev-inbox-CUUS6iUg.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-CLa2LThw.mjs → dispatch-BNLB5_Gm.mjs} +12 -15
  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-DyhNtdYf.mjs → domain-BlH90Ods.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-DM2wDcBN.mjs → email-Bkq8ZL1p.mjs} +14 -15
  93. package/dist/{email-cloudflare-PMbAev9Q.mjs → email-cloudflare-MvJIxrwx.mjs} +18 -123
  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-78hbN-oI.mjs → env-AvuCSeCH.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-BUfFZ6bt.mjs → env-validation-C8Cmvas0.mjs} +1 -1
  105. package/dist/{env-validation-B3VobvXm.mjs → env-validation-GV1oD4EV.mjs} +9 -10
  106. package/dist/{error-pages-CLIJ7aYq.mjs → error-pages-COVBnzK7.mjs} +6 -12
  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-CFmsUsW1.mjs → gen-BD-dfjxY.mjs} +12 -13
  113. package/dist/gen-CIHXh9I8.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-De-_IWbM.mjs → github-cmd-CA-lBdkn.mjs} +8 -9
  119. package/dist/{handler-BHktmuTL.d.mts → handler-BR6Tvjkp.d.mts} +18 -26
  120. package/dist/{handler-BZ1t7-Rv.mjs → handler-CKeTtYID.mjs} +6 -17
  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-CuTEdP9C.mjs +445 -0
  124. package/dist/{help-CKbrhZha.mjs → help-1OCFDsRr.mjs} +28 -12
  125. package/dist/help-Ba8Dq5-r.mjs +1 -0
  126. package/dist/{inbound-Da7XsjH3.d.mts → inbound-BHt4dIlL.d.mts} +16 -9
  127. package/dist/{inbound-VrOLqwZY.mjs → inbound-CdO-qY0w.mjs} +6 -81
  128. package/dist/index.d.mts +23 -13
  129. package/dist/index.mjs +495 -223
  130. package/dist/{info-Yg0-V5Rs.mjs → info-CJxua_db.mjs} +6 -7
  131. package/dist/{init-CDiJQycf.mjs → init-B-4CluYx.mjs} +43 -59
  132. package/dist/{isr-config-fZaJJ8t7.mjs → isr-config-Czzb4mIq.mjs} +5 -55
  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-Dllip08S.mjs → link-DAXOT-G_.mjs} +8 -9
  136. package/dist/{list-BYRP6am0.mjs → list-BYSOo9fm.mjs} +8 -9
  137. package/dist/{live-BllfDuzA.d.mts → live-0xrcVpyq.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-CAwAs9GH.mjs → local-d1-BLgsNUj9.mjs} +4 -5
  141. package/dist/{log-BMwmN5Ae.mjs → log-D9hwSySP.mjs} +3 -4
  142. package/dist/login-BpbYeu-n.mjs +1 -0
  143. package/dist/{login-PcFy5mlC.mjs → login-CJopTWX4.mjs} +6 -7
  144. package/dist/{logs-DmJTBhed.mjs → logs-DE0weBsR.mjs} +19 -18
  145. package/dist/{migrate-B8S2xTcb.mjs → migrate-ChHHZBTi.mjs} +20 -16
  146. package/dist/migrate-HdA6Kh2p.mjs +1 -0
  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-CtP6-qAF.mjs} +145 -18
  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 +5 -6
  154. package/dist/{node-CDOPrGSl.mjs → node-CZ6lGNLn.mjs} +8 -9
  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-DmkmS2wL.mjs → operator-cmd-BUqsdk2K.mjs} +32 -15
  159. package/dist/operator-cmd-wBYyp8iQ.mjs +1 -0
  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 +147 -31
  164. package/dist/pages/client.mjs +199 -43
  165. package/dist/pages/head.d.mts +1 -1
  166. package/dist/pages/head.mjs +1 -1
  167. package/dist/pages/index.d.mts +25 -18
  168. package/dist/pages/index.mjs +24 -12
  169. package/dist/pages/islands-plugin.d.mts +75 -13
  170. package/dist/pages/islands-plugin.mjs +92 -7
  171. package/dist/pages/prefetch.d.mts +2 -2
  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-C7XUw9mw.mjs +1 -0
  182. package/dist/{platform-args-BMD2gjc_.mjs → platform-args-Cx1M-7bq.mjs} +22 -11
  183. package/dist/{platform-auth-config-CImnfohz.mjs → platform-auth-config-K4m_LE8b.mjs} +10 -11
  184. package/dist/{platform-auth-protection-BogLhtHi.mjs → platform-auth-protection-KF5Vo-1I.mjs} +10 -11
  185. package/dist/{platform-auth-recovery-B-mEaWEi.mjs → platform-auth-recovery-BOdFrl7R.mjs} +9 -11
  186. package/dist/{platform-cmd-CV8NxIIn.mjs → platform-cmd-DpCHawGF.mjs} +1 -1
  187. package/dist/{platform-cmd-DZK2ixMl.mjs → platform-cmd-Ds3EAV5t.mjs} +13 -13
  188. package/dist/{platform-discovery-CHhNs8Nn.mjs → platform-discovery-B0eZjZ3B.mjs} +2 -3
  189. package/dist/{platform-domain-CRvelPGE.mjs → platform-domain-rWJshybd.mjs} +7 -8
  190. package/dist/{platform-lifecycle-DwXq7kZt.mjs → platform-lifecycle-BH34I0rh.mjs} +1 -1
  191. package/dist/{platform-lifecycle-CPYY7E9B.mjs → platform-lifecycle-D9RdGub1.mjs} +110 -110
  192. package/dist/{platform-management-BOnGbMSM.mjs → platform-management-BRefdHGD.mjs} +27 -11
  193. package/dist/{platform-management-lXdgGgAM.mjs → platform-management-BfLW0Zlo.mjs} +1 -1
  194. package/dist/{platform-plans-config-CeydDSj0.mjs → platform-plans-config-Dx1agneU.mjs} +5 -6
  195. package/dist/{platform-recovery-noaALXnE.mjs → platform-recovery-DZuZGJtt.mjs} +5 -6
  196. package/dist/{platform-registry-B9mWX9LO.mjs → platform-registry-DZ_2Xuqd.mjs} +4 -6
  197. package/dist/platform-runtime-logs-CdJGnk3f.mjs +68 -0
  198. package/dist/{platform-setup-Ca53gtt0.mjs → platform-setup-Vw1AaUN8.mjs} +19 -7
  199. package/dist/{plugin-inference-CeiB6BG5.mjs → plugin-inference-CdLbxZL_.mjs} +16 -24
  200. package/dist/{prefetch-Bsc_Pb6c.mjs → prefetch-Dx2jIbtg.mjs} +20 -3
  201. package/dist/{prefetch-Ce6la4EI.d.mts → prefetch-NdNeubbH.d.mts} +7 -3
  202. package/dist/{prepare-D604Yiyr.mjs → prepare-BJW-f1f1.mjs} +13 -14
  203. package/dist/{prepare-BuOS18AM.mjs → prepare-BMGeKL16.mjs} +4 -5
  204. package/dist/prepare-BdxJJCMv.mjs +1 -0
  205. package/dist/{prerender-render-CaShbHJ3.mjs → prerender-render-RlAj6hh8.mjs} +2 -3
  206. package/dist/prerender-render.d.mts +1 -3
  207. package/dist/prerender-render.mjs +1 -1
  208. package/dist/{project-rqDnVsJN.mjs → project-CLwxcEdq.mjs} +3 -4
  209. package/dist/{project-zdB3fs9G.mjs → project-DVsTAWFh.mjs} +1 -1
  210. package/dist/{project-cmd-DBYqAIbe.mjs → project-cmd-B_bUyZ3J.mjs} +21 -23
  211. package/dist/{project-paths-DGu_QZ_Q.mjs → project-paths-CdGv9Tmi.mjs} +3 -5
  212. package/dist/project-slug-BUy0lmyR.mjs +1 -0
  213. package/dist/{project-slug-23TpquG4.mjs → project-slug-CO6ci9XG.mjs} +0 -1
  214. package/dist/{project-team-BjCLgTRC.mjs → project-team-MjT5K4rQ.mjs} +7 -8
  215. package/dist/{project-token-BB6PwaA9.mjs → project-token-BKHGwY3k.mjs} +7 -8
  216. package/dist/{project-tsconfig-CVvk6Z_e.mjs → project-tsconfig-Cf2NFjlM.mjs} +4 -6
  217. package/dist/{project-zero-trust-CWDh1P_t.mjs → project-zero-trust-Bzdd05-h.mjs} +7 -8
  218. package/dist/{protocol-DimNxVRr.mjs → protocol-COyySMki.mjs} +135 -113
  219. package/dist/{protocol-D5XDySYu.d.mts → protocol-CkwjASep.d.mts} +4 -6
  220. package/dist/{providers-BNKRacMr.d.mts → providers-D5P8j_8D.d.mts} +0 -2
  221. package/dist/{providers-BUHwJlmM.mjs → providers-ZARwX2cL.mjs} +1 -2
  222. package/dist/{provision-DztLJ97X.mjs → provision-BbCzpbXs.mjs} +6 -7
  223. package/dist/{provision-DfxLCg-d.mjs → provision-DQF6Kw-6.mjs} +1 -1
  224. package/dist/{queues-BWKt1Xo4.d.mts → queues-DdM42xXW.d.mts} +0 -2
  225. package/dist/{r2-conditions-B8xUgJRc.mjs → r2-conditions-BqkQNt2n.mjs} +1 -2
  226. package/dist/{requests-D_pbzDyz.mjs → requests-daJmVpjk.mjs} +6 -7
  227. package/dist/resolve-project-CgfjtOwz.mjs +1 -0
  228. package/dist/{resolve-project-Xoi6eTWY.mjs → resolve-project-D0YNnJfm.mjs} +4 -5
  229. package/dist/{resource-name-C7LVpcRm.mjs → resource-name-DlJ9QXzg.mjs} +1 -2
  230. package/dist/{response-Tn7rU0MV.mjs → response-HmNjB30w.mjs} +1 -2
  231. package/dist/{rollback-CjfIYsJx.mjs → rollback-BgL0wY1J.mjs} +7 -8
  232. package/dist/{rolldown-runtime-3h0WiCiA.mjs → rolldown-runtime-uD8oG6U2.mjs} +1 -2
  233. package/dist/{route-types-DvEGmPif.mjs → route-types-CZc1YXjF.mjs} +80 -9
  234. package/dist/route-url-CRDF-I0I.mjs +57 -0
  235. package/dist/route-url-C_YIH_zO.d.mts +37 -0
  236. package/dist/routes-stub.d.mts +8 -3
  237. package/dist/routes-stub.mjs +1 -1
  238. package/dist/{routing-assets-DdSFxoLp.mjs → routing-assets-DJIVOrCh.mjs} +1 -2
  239. package/dist/{runner-3uGC-oLF.mjs → runner-5MCSimKx.mjs} +5 -6
  240. package/dist/{runner-WCdfeI0q.mjs → runner-QMeOpScZ.mjs} +1 -1
  241. package/dist/{runner-mysql-BcHnLUuM.mjs → runner-mysql-0zVmB1JW.mjs} +1 -1
  242. package/dist/{runner-mysql-BWmbk5IE.mjs → runner-mysql-Bdmsp_x4.mjs} +3 -4
  243. package/dist/{runner-pg-Cgp-cr_p.mjs → runner-pg-2pjltt0t.mjs} +1 -1
  244. package/dist/{runner-pg-Cr3qrqi4.mjs → runner-pg-mYc75KfH.mjs} +2 -3
  245. package/dist/runtime/ai.d.mts +0 -4
  246. package/dist/runtime/ai.mjs +6 -8
  247. package/dist/runtime/auth-client-react.d.mts +1 -1
  248. package/dist/runtime/auth-client-react.mjs +1 -1
  249. package/dist/runtime/auth-client-solid.d.mts +1 -1
  250. package/dist/runtime/auth-client-solid.mjs +1 -1
  251. package/dist/runtime/auth-client-svelte.d.mts +1 -1
  252. package/dist/runtime/auth-client-svelte.mjs +1 -1
  253. package/dist/runtime/auth-client-vue.d.mts +1 -1
  254. package/dist/runtime/auth-client-vue.mjs +1 -1
  255. package/dist/runtime/auth-client.d.mts +1 -1
  256. package/dist/runtime/auth-client.mjs +1 -1
  257. package/dist/runtime/auth.d.mts +1 -1
  258. package/dist/runtime/auth.mjs +1 -1
  259. package/dist/runtime/better-auth-mysql.d.mts +2 -4
  260. package/dist/runtime/better-auth-mysql.mjs +3 -4
  261. package/dist/runtime/better-auth-pg.d.mts +2 -4
  262. package/dist/runtime/better-auth-pg.mjs +4 -5
  263. package/dist/runtime/better-auth.d.mts +2 -4
  264. package/dist/runtime/better-auth.mjs +3 -4
  265. package/dist/runtime/client-react.d.mts +4 -4
  266. package/dist/runtime/client-react.mjs +4 -4
  267. package/dist/runtime/client-solid.d.mts +4 -4
  268. package/dist/runtime/client-solid.mjs +4 -4
  269. package/dist/runtime/client-svelte.d.mts +4 -4
  270. package/dist/runtime/client-svelte.mjs +4 -4
  271. package/dist/runtime/client-vue.d.mts +4 -4
  272. package/dist/runtime/client-vue.mjs +4 -4
  273. package/dist/runtime/client.d.mts +4 -4
  274. package/dist/runtime/client.mjs +4 -4
  275. package/dist/runtime/db.d.mts +0 -2
  276. package/dist/runtime/db.mjs +2 -3
  277. package/dist/runtime/durable.d.mts +0 -2
  278. package/dist/runtime/durable.mjs +3 -4
  279. package/dist/runtime/email/testing.d.mts +1 -5
  280. package/dist/runtime/email/testing.mjs +5 -6
  281. package/dist/runtime/email-protocol.d.mts +0 -2
  282. package/dist/runtime/email-protocol.mjs +1 -1
  283. package/dist/runtime/email.d.mts +1 -5
  284. package/dist/runtime/email.mjs +6 -7
  285. package/dist/runtime/env-public-client.d.mts +1 -3
  286. package/dist/runtime/env-public-client.mjs +2 -3
  287. package/dist/runtime/env-public.d.mts +2 -2
  288. package/dist/runtime/env-public.mjs +5 -7
  289. package/dist/runtime/env.d.mts +0 -4
  290. package/dist/runtime/env.mjs +1 -1
  291. package/dist/runtime/fetch-server.d.mts +1 -3
  292. package/dist/runtime/fetch-server.mjs +3 -4
  293. package/dist/runtime/fetch-stream.d.mts +2 -2
  294. package/dist/runtime/fetch-stream.mjs +2 -2
  295. package/dist/runtime/fetch.d.mts +1 -1
  296. package/dist/runtime/fetch.mjs +2 -2
  297. package/dist/runtime/handler.d.mts +1 -1
  298. package/dist/runtime/handler.mjs +2 -2
  299. package/dist/runtime/isr.d.mts +1 -3
  300. package/dist/runtime/isr.mjs +2 -3
  301. package/dist/runtime/kv.d.mts +1 -3
  302. package/dist/runtime/kv.mjs +2 -3
  303. package/dist/runtime/limits.d.mts +1 -1
  304. package/dist/runtime/limits.mjs +1 -1
  305. package/dist/runtime/live-client.d.mts +1 -3
  306. package/dist/runtime/live-client.mjs +1 -2
  307. package/dist/runtime/live-server.d.mts +0 -2
  308. package/dist/runtime/live-server.mjs +3 -4
  309. package/dist/runtime/live.d.mts +1 -1
  310. package/dist/runtime/live.mjs +1 -1
  311. package/dist/runtime/log.d.mts +3 -3
  312. package/dist/runtime/log.mjs +26 -18
  313. package/dist/runtime/migration-handler-mysql.d.mts +2 -4
  314. package/dist/runtime/migration-handler-mysql.mjs +2 -3
  315. package/dist/runtime/migration-handler-pg.d.mts +2 -4
  316. package/dist/runtime/migration-handler-pg.mjs +2 -3
  317. package/dist/runtime/migration-handler.d.mts +1 -1
  318. package/dist/runtime/migration-handler.mjs +1 -1
  319. package/dist/runtime/queues.d.mts +1 -1
  320. package/dist/runtime/queues.mjs +2 -3
  321. package/dist/runtime/remote/binding-handler.d.mts +1 -3
  322. package/dist/runtime/remote/binding-handler.mjs +3 -4
  323. package/dist/runtime/remote/index.d.mts +1 -3
  324. package/dist/runtime/remote/index.mjs +8 -13
  325. package/dist/runtime/response.d.mts +1 -3
  326. package/dist/runtime/response.mjs +1 -1
  327. package/dist/runtime/route-url.d.mts +2 -2
  328. package/dist/runtime/route-url.mjs +1 -1
  329. package/dist/runtime/routing.d.mts +8 -11
  330. package/dist/runtime/routing.mjs +52 -32
  331. package/dist/runtime/sandbox-container.d.mts +1 -1
  332. package/dist/runtime/sandbox-container.mjs +1 -1
  333. package/dist/runtime/sandbox.d.mts +2 -2
  334. package/dist/runtime/sandbox.mjs +5 -6
  335. package/dist/runtime/seed.d.mts +0 -2
  336. package/dist/runtime/seed.mjs +1 -2
  337. package/dist/runtime/sse-client.d.mts +1 -3
  338. package/dist/runtime/sse-client.mjs +1 -2
  339. package/dist/runtime/sse.d.mts +1 -3
  340. package/dist/runtime/sse.mjs +1 -1
  341. package/dist/runtime/storage.d.mts +1 -3
  342. package/dist/runtime/storage.mjs +2 -3
  343. package/dist/runtime/validator.d.mts +1 -1
  344. package/dist/runtime/validator.mjs +1 -1
  345. package/dist/runtime/ws-server.d.mts +3 -5
  346. package/dist/runtime/ws-server.mjs +3 -4
  347. package/dist/runtime/ws.d.mts +1 -1
  348. package/dist/runtime/ws.mjs +3 -4
  349. package/dist/{sandbox-q3waMc2T.d.mts → sandbox-DE1WsxuB.d.mts} +2 -4
  350. package/dist/{sandbox-container-a9LRUtii.mjs → sandbox-container-BuxhwCgt.mjs} +1 -2
  351. package/dist/{sandbox-container-ChQRum-j.d.mts → sandbox-container-CZFZdMso.d.mts} +0 -2
  352. package/dist/{scan-N9WzdcAl.mjs → scan-X2rDDRNa.mjs} +49 -35
  353. package/dist/{secret-3X0PxmuX.mjs → secret-CPq-B_vp.mjs} +17 -15
  354. package/dist/{serialize-YHvlcG3Q.mjs → serialize-DUuYuaY3.mjs} +2 -4
  355. package/dist/{serialize-DtR8Vwa_.d.mts → serialize-I4EmS-Wf.d.mts} +0 -2
  356. package/dist/{skills-CrUO3PJ0.mjs → skills-D393E4lB.mjs} +4 -5
  357. package/dist/{sqlite-validation-BzKMWnO4.mjs → sqlite-validation-CLJXXN93.mjs} +1 -2
  358. package/dist/{sse-CMvCgjNk.mjs → sse-CxR30yMF.mjs} +1 -2
  359. package/dist/{standard-schema-Fo_vCAZh.d.mts → standard-schema-CuDawHOC.d.mts} +0 -2
  360. package/dist/{static-asset-marker-Btf-6oCD.mjs → static-asset-marker-DsQKz6lt.mjs} +9 -3
  361. package/dist/{subcommand-prompt-D9OhhbGG.mjs → subcommand-prompt-CxJXporl.mjs} +3 -4
  362. package/dist/sveltekit.d.mts +0 -2
  363. package/dist/sveltekit.mjs +2 -3
  364. package/dist/{terminal-log-text-D9ACPOuG.mjs → terminal-log-text-DNsWJREL.mjs} +1 -2
  365. package/dist/{types-w72dljaA.d.mts → types-agfx0alu.d.mts} +0 -4
  366. package/dist/validate-DY1U9rET.mjs +1 -0
  367. package/dist/{validate-CnZPMq4q.mjs → validate-Ddzl-IwT.mjs} +4 -5
  368. package/dist/validation-error-uAAjlsiW.mjs +82 -0
  369. package/dist/{validator-BTOu0fB0.mjs → validator-CTfmzZYb.mjs} +2 -5
  370. package/dist/{version-metadata-D2vfMQzv.mjs → version-metadata-C8hLzQkv.mjs} +4 -6
  371. package/dist/{worker-conditions-AWFRcFxR.mjs → worker-conditions-CBZ0RYsZ.mjs} +1 -2
  372. package/dist/{wrangler-I-scB_1t.mjs → wrangler-DESSbN8L.mjs} +6 -8
  373. package/dist/wrangler-DUB3MGHV.mjs +1 -0
  374. package/dist/{wrapper-BBl1rC32.mjs → wrapper-C9SUxoj7.mjs} +17 -14
  375. package/dist/{ws-B3ClMVDh.d.mts → ws-Dmjg5NH2.d.mts} +3 -5
  376. package/dist/{yarn-pnp-DLbEFMT0.mjs → yarn-pnp-DgWbE7z5.mjs} +2 -3
  377. package/docs/guide/database.md +4 -4
  378. package/docs/guide/deployment.md +1 -1
  379. package/docs/guide/edge/headers.md +4 -6
  380. package/docs/guide/edge/redirects.md +4 -4
  381. package/docs/guide/edge/rewrites.md +1 -1
  382. package/docs/guide/edge/static-assets.md +0 -10
  383. package/docs/guide/email/domains.md +3 -1
  384. package/docs/guide/email/receiving.md +4 -4
  385. package/docs/guide/email/sending.md +43 -13
  386. package/docs/guide/pages-routing/actions-and-forms.md +26 -9
  387. package/docs/guide/pages-routing/islands.md +5 -5
  388. package/docs/guide/pages-routing/layouts.md +16 -2
  389. package/docs/guide/pages-routing/loaders.md +5 -5
  390. package/docs/guide/pages-routing/markdown.md +7 -7
  391. package/docs/guide/pages-routing/overview.md +137 -27
  392. package/docs/guide/platform/administration/connected-apps.md +4 -2
  393. package/docs/guide/platform/administration/email.md +6 -8
  394. package/docs/guide/platform/installation/credentials.md +12 -10
  395. package/docs/guide/platform/installation/maintenance.md +18 -21
  396. package/docs/guide/platform/installation/prerequisites.md +1 -1
  397. package/docs/guide/platform/installation/setup.md +23 -2
  398. package/docs/guide/platform/installation/uninstall.md +1 -1
  399. package/docs/guide/queues.md +4 -8
  400. package/docs/guide/self-hosted-platform.md +3 -3
  401. package/docs/guide/server-routing.md +7 -7
  402. package/docs/guide/ssg.md +3 -3
  403. package/docs/guide/type-safety.md +84 -1
  404. package/docs/guide/typed-fetch.md +1 -1
  405. package/docs/guide/websockets.md +1 -1
  406. package/docs/integrations/cloudflare.md +2 -2
  407. package/docs/integrations/frameworks/analog.md +1 -1
  408. package/docs/integrations/frameworks/astro.md +17 -12
  409. package/docs/integrations/frameworks/nuxt.md +1 -1
  410. package/docs/integrations/frameworks/overview.md +2 -2
  411. package/docs/integrations/frameworks/sveltekit.md +1 -1
  412. package/docs/integrations/frameworks/tanstack-start.md +1 -1
  413. package/docs/integrations/hono.md +5 -5
  414. package/docs/reference/api/auth.md +1 -1
  415. package/docs/reference/api/deploy.md +6 -6
  416. package/docs/reference/api/pages.md +109 -50
  417. package/docs/reference/api/plugin.md +4 -4
  418. package/docs/reference/api/resources.md +4 -1
  419. package/docs/reference/api/rewrites.md +24 -3
  420. package/docs/reference/api/types.md +45 -0
  421. package/docs/reference/api.md +2 -2
  422. package/docs/reference/cli/database.md +15 -9
  423. package/docs/reference/cli/email.md +4 -2
  424. package/docs/reference/cli/platform-installation.md +6 -3
  425. package/docs/reference/cli/project.md +2 -2
  426. package/docs/reference/cli/secrets.md +3 -1
  427. package/docs/reference/cli/setup.md +4 -4
  428. package/docs/reference/cli.md +1 -1
  429. package/docs/reference/config.md +12 -2
  430. package/package.json +36 -32
  431. package/sandbox.Dockerfile +1 -1
  432. package/schema.json +4 -0
  433. package/skills/void/SKILL.md +5 -0
  434. package/dist/cf-build-output-bd8Uwv1P.mjs +0 -1
  435. package/dist/client-BZb9j66F.mjs +0 -1
  436. package/dist/collect-BWhkgtAn.mjs +0 -1
  437. package/dist/deploy-CX94CmKa.mjs +0 -2
  438. package/dist/discover-D4TPKo57.mjs +0 -1
  439. package/dist/gen-BhWBT4iu.mjs +0 -1
  440. package/dist/headers--vaK_chu.mjs +0 -226
  441. package/dist/help-qOZr3wng.mjs +0 -1
  442. package/dist/login-BAPmYnb7.mjs +0 -1
  443. package/dist/migrate-BIYTPQE6.mjs +0 -1
  444. package/dist/operator-cmd-CjazwOyb.mjs +0 -1
  445. package/dist/output-BW9uK099.mjs +0 -1
  446. package/dist/plan-CKX_jWnD.mjs +0 -1
  447. package/dist/platform-args-BC8_hsDj.mjs +0 -1
  448. package/dist/prepare-DU-tOpS5.mjs +0 -1
  449. package/dist/project-slug-6cyz8E7k.mjs +0 -1
  450. package/dist/resolve-project-DD1vu8s9.mjs +0 -1
  451. package/dist/route-url-BgPja1GS.d.mts +0 -5
  452. package/dist/route-url-BjGv_KKY.mjs +0 -28
  453. package/dist/validate-D7Wn8PUX.mjs +0 -1
  454. package/dist/validation-error-Dg9Recn1.mjs +0 -49
  455. package/dist/wrangler-UnwdISay.mjs +0 -1
@@ -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
 
@@ -29,6 +29,8 @@ export const action = defineHandler.withValidator({
29
29
  | Nothing (void) | Re-runs the loader, page re-renders with fresh props. |
30
30
  | `c.redirect('/path')` | Navigates to another page. |
31
31
 
32
+ Middleware does not run again after the action. To change [shared data](./layouts.md#shared-data), update it in the action or redirect.
33
+
32
34
  ## Form
33
35
 
34
36
  Pair `Form` with `useForm` to submit values and display validation and action errors. Inputs stay editable when a submission fails.
@@ -163,7 +165,7 @@ The types are inferred from your action's `withValidator()` schema in the compan
163
165
  | `clearErrors(...fields)` | Clear validation errors. Field names autocomplete. |
164
166
  | `clearError()` | Clear `error`. |
165
167
 
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).
168
+ Use `setError()` for client-side validation. Editing a field clears its error automatically.
167
169
 
168
170
  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
171
 
@@ -175,7 +177,7 @@ const form = useForm('/users/:id', { name: '' }, { params: { id: '42' } });
175
177
  <Form form={form} method="put">{/* submits to /users/42 */}</Form>
176
178
  ```
177
179
 
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`.
180
+ 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
181
 
180
182
  ### React submission callbacks
181
183
 
@@ -188,26 +190,41 @@ const form = useForm(
188
190
  {
189
191
  onSuccess: () => setDialogOpen(false),
190
192
  onError: (error) => {
191
- // A field-error map or VoidActionError for a handled action failure.
192
193
  console.error(error);
193
194
  },
194
195
  },
195
196
  );
196
197
  ```
197
198
 
198
- Each submission uses the callbacks from when it was dispatched. Callbacks run inside the React Action, before the updated UI commits. Use an effect or ref callback to focus an element that appears after submission.
199
+ `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.
199
200
 
200
- Callbacks can return `Promise<void>`. The Action awaits them, and `form.pending` stays true until they complete. Errors thrown or rejected by callbacks reach the nearest React error boundary. Aborted submissions invoke neither callback.
201
+ If a callback awaits `router.visit()` or `router.refresh()`, pass `{ resolveOn: 'data' }` so it can finish before React commits the navigation. See [React navigation completion](../../reference/api/pages.md#react-navigation-completion).
201
202
 
202
203
  Vue, Svelte, and Solid submissions return a promise instead; use `await form.post()` to run work after a submission.
203
204
 
205
+ ### Scroll after submission
206
+
207
+ Actions and forms keep the current scroll position when updating the page in place. Redirects and submissions that open another page scroll to the top, or to the destination's hash target.
208
+
209
+ Pass `preserveScroll: false` to reset scroll after an in-place update, or `true` to keep it even after a redirect:
210
+
211
+ ```ts
212
+ await action('/users/:id?update', {
213
+ params: { id: '42' },
214
+ data: { name: 'Alice' },
215
+ preserveScroll: false,
216
+ });
217
+ ```
218
+
219
+ In React, set `preserveScroll` in the third argument to `useForm()`. In Vue, Svelte, and Solid, pass it to the submit method, such as `form.post({ preserveScroll: false })`.
220
+
204
221
  ## Named Actions
205
222
 
206
223
  When a page needs multiple mutations, such as updating and deleting a user on the same page, export `actions` (plural) instead of `action`:
207
224
 
208
225
  ```ts
209
- import { users, updateUserSchema } from '@schema';
210
226
  // pages/users/[id].server.ts
227
+ import { users, updateUserSchema } from '@schema';
211
228
  import { defineHandler } from 'void';
212
229
  import { db, eq } from 'void/db';
213
230
 
@@ -227,7 +244,7 @@ export const actions = {
227
244
  };
228
245
  ```
229
246
 
230
- 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`.
247
+ 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.
231
248
 
232
249
  Use `action` or `actions` in a file, not both.
233
250
 
@@ -273,7 +290,7 @@ if (!result.ok) {
273
290
 
274
291
  `action()` defaults to `POST`. Pass `data`, `params`, and `method` to set the body, route parameters, or HTTP method.
275
292
 
276
- A successful call returns `{ ok: true, pageData }`. Expected errors, such as validation failures or conflicts, return `{ ok: false, error }`.
293
+ A successful call returns `{ ok: true, pageData }`. Expected errors, such as validation failures or conflicts, return `{ ok: false, error }`. `error.message` is the message of an [`HTTPException`](../../integrations/hono.md#utilities) with a `4xx` status, or the body of another plain-text `4xx` response. For other errors, it is a status summary such as `Action failed with 404 Not Found`.
277
294
 
278
295
  ## Validation Errors
279
296
 
@@ -96,11 +96,11 @@ export default function BlogIndex({ posts }) {
96
96
 
97
97
  ```vue [Vue]
98
98
  <!-- pages/blog/index.island.vue -->
99
- <script setup>
99
+ <script setup lang="ts">
100
100
  import Counter from './_Counter.vue' with { island: 'load' };
101
101
  import PostForm from './_PostForm.vue' with { island: 'visible' };
102
102
 
103
- defineProps({ posts: Array });
103
+ const { posts } = defineProps<{ posts: { slug: string; title: string }[] }>();
104
104
  </script>
105
105
 
106
106
  <template>
@@ -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
 
@@ -249,7 +249,7 @@ export default function PostForm() {
249
249
  ```
250
250
 
251
251
  ```vue [Vue]
252
- <script setup>
252
+ <script setup lang="ts">
253
253
  import { useIslandForm } from '@void/vue';
254
254
 
255
255
  const form = useIslandForm({ title: '', body: '' });
@@ -167,7 +167,7 @@ export default function Page() {
167
167
  ```
168
168
 
169
169
  ```vue [Vue]
170
- <script>
170
+ <script lang="ts">
171
171
  export const layout = 'landing';
172
172
  </script>
173
173
 
@@ -238,4 +238,18 @@ export default defineMiddleware(async (c, next) => {
238
238
  });
239
239
  ```
240
240
 
241
- Call `useShared()` from your framework adapter, as in the layout examples above. Its return type is inferred from `CloudContextVariables`. Shared data comes from middleware; page props come from the loader. See [Context variables](../type-safety.md#context-variables).
241
+ Call `useShared()` from your framework adapter, as in the layout examples above. Its return type is inferred from `CloudContextVariables`. See [Context variables](../type-safety.md#context-variables).
242
+
243
+ Middleware sets the starting value. A loader or action can update it before the page is sent:
244
+
245
+ ```ts
246
+ // pages/profile.server.ts
247
+ import { defineHandler } from 'void';
248
+
249
+ export const action = defineHandler(async (c) => {
250
+ const user = await updateProfile(c);
251
+ c.set('shared', { ...c.get('shared'), auth: { user } });
252
+ });
253
+ ```
254
+
255
+ Middleware runs before the action. If an action changes data that shared data is built from, update shared data in the action, or redirect with `c.redirect()` so middleware runs again on the next page load.
@@ -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';
@@ -51,7 +51,7 @@ export default function UsersPage({ users }: Props) {
51
51
  <!-- pages/users/index.vue -->
52
52
  <script setup lang="ts">
53
53
  import type { Props } from './index.server';
54
- defineProps<Props>();
54
+ const { users } = defineProps<Props>();
55
55
  </script>
56
56
 
57
57
  <template>
@@ -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';
@@ -177,7 +177,7 @@ Check `loading` first, then `error`. TypeScript narrows `value` to `T` in the re
177
177
  ```vue [Vue]
178
178
  <script setup lang="ts">
179
179
  import type { Props } from './dashboard.server';
180
- defineProps<Props>();
180
+ const { projects, usage } = defineProps<Props>();
181
181
  </script>
182
182
 
183
183
  <template>
@@ -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
 
@@ -190,7 +190,7 @@ export default function DocsLayout({ children }) {
190
190
  ```
191
191
 
192
192
  ```vue [Vue]
193
- <script setup>
193
+ <script setup lang="ts">
194
194
  import { useFrontmatter } from '@void/md';
195
195
 
196
196
  const fm = useFrontmatter();
@@ -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.
97
+ Use one page file per URL in each environment.
98
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 |
105
-
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,46 +153,54 @@ 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
  :::
205
201
 
202
+ With [`routing.typedRoutes`](../type-safety.md#checked-url-strings), which apps created with `void init` have on, `href` and the router methods below reject plain strings such as `"/user"` that don't match a route.
203
+
206
204
  `Link` also supports query data, history replacement, full-page navigation, and cancellation:
207
205
 
208
206
  ```tsx
@@ -232,17 +230,28 @@ import { Link } from "@void/solid";
232
230
 
233
231
  `prefetch` and `reloadDocument` work only with GET links. GET `data` becomes query parameters; use scalar values or arrays.
234
232
 
235
- For programmatic navigation, use `useRouter()`:
233
+ For programmatic navigation, use `useRouter()`. Pass a typed destination object to `visit()`, `prefetch()`, or `flush()`:
236
234
 
237
235
  ```ts
238
236
  import { useRouter } from '@void/vue'; // or "@void/react", "@void/svelte", "@void/solid"
237
+ import type { RouteDestination } from 'void/routes';
239
238
 
240
239
  const router = useRouter();
241
- router.visit('/users');
240
+ const profile = {
241
+ pathname: '/users/:id',
242
+ params: { id: 42 },
243
+ query: { tab: 'activity' },
244
+ } satisfies RouteDestination;
245
+
246
+ await router.prefetch(profile);
247
+ await router.visit(profile);
248
+ router.flush(profile); // clear its prefetched data
242
249
  router.refresh(); // re-fetch current page props, keeping the same history entry
243
250
  router.visit('/logout', { method: 'POST' }); // non-GET navigation
244
251
  ```
245
252
 
253
+ 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.
254
+
246
255
  `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
256
 
248
257
  For dynamic route params, use `useParams()` from the same adapter package:
@@ -256,12 +265,113 @@ export default function PostPage() {
256
265
  }
257
266
  ```
258
267
 
268
+ ### Active links
269
+
270
+ `Link` marks the link to the current page with `aria-current="page"` and `data-void-active`. Use them to style navigation:
271
+
272
+ ```css
273
+ nav a[data-void-active] {
274
+ font-weight: 600;
275
+ }
276
+ ```
277
+
278
+ A link is active only on its own path by default. Set `activeMatch="prefix"` to keep it active on nested pages:
279
+
280
+ ::: code-group
281
+
282
+ ```tsx [React]
283
+ <nav>
284
+ <Link href="/">Home</Link>
285
+ <Link href="/users" activeMatch="prefix">
286
+ Users
287
+ </Link>
288
+ </nav>
289
+ ```
290
+
291
+ ```vue [Vue]
292
+ <nav>
293
+ <Link href="/">Home</Link>
294
+ <Link href="/users" active-match="prefix">Users</Link>
295
+ </nav>
296
+ ```
297
+
298
+ ```svelte [Svelte]
299
+ <nav>
300
+ <Link href="/">Home</Link>
301
+ <Link href="/users" activeMatch="prefix">Users</Link>
302
+ </nav>
303
+ ```
304
+
305
+ ```tsx [Solid]
306
+ <nav>
307
+ <Link href="/">Home</Link>
308
+ <Link href="/users" activeMatch="prefix">
309
+ Users
310
+ </Link>
311
+ </nav>
312
+ ```
313
+
314
+ :::
315
+
316
+ | Current URL | `href="/users"` | `href="/users" activeMatch="prefix"` |
317
+ | --------------- | --------------- | ------------------------------------ |
318
+ | `/users` | both attributes | both attributes |
319
+ | `/users?page=2` | both attributes | both attributes |
320
+ | `/users/42` | none | `data-void-active` |
321
+ | `/users-admin` | none | none |
322
+
323
+ `aria-current="page"` marks only the exact page, so select `[aria-current="page"]` to style it differently from its section. A link to `/` is active only on the home page.
324
+
325
+ Paths match the way pages are routed: letter case and trailing slashes count, while the query string and hash are ignored. Links to other origins and non-GET links are never active. An `aria-current` or `data-void-active` you pass to `Link` replaces the computed value.
326
+
327
+ ### Pending links
328
+
329
+ While a page loads, `Link` adds `data-void-pending` to every link to it. Use it to show that a click is being handled:
330
+
331
+ ```css
332
+ a[data-void-pending] {
333
+ opacity: 0.6;
334
+ /* Skip visits that finish quickly, such as to a prefetched page */
335
+ transition: opacity 0.15s 0.1s;
336
+ }
337
+ ```
338
+
339
+ A link is pending only while its exact destination loads. The path, query and hash must all match, so a link to `/users?page=2` isn't pending while `/users?page=3` loads. A non-GET link, which renders a `<button>`, is pending while a request with its method to its `href` runs. `router.refresh()` reloads the current page, so links to it are pending during a refresh.
340
+
341
+ A `data-void-pending` you pass to `Link` replaces the computed value. For a loading indicator that covers the whole page, use [`useNavigation()`](../../reference/api/pages.md).
342
+
343
+ ### Prefetching
344
+
345
+ Add `prefetch` to a `Link` to load its page before the user clicks, so the visit doesn't wait for the server:
346
+
347
+ ```tsx
348
+ <Link href="/dashboard" prefetch>
349
+ Dashboard
350
+ </Link>
351
+ ```
352
+
353
+ `prefetch` on its own loads the page on hover, keyboard focus, or touch. A `Link` can also prefetch on click, as soon as it renders, or once it stays in view, and `cacheFor` sets how long a prefetched page is reused. See [Prefetching](../../reference/api/pages.md#prefetching) for every option.
354
+
355
+ To give every `Link` a prefetch strategy, set `prefetch.defaultStrategy` in the adapter plugin. A `Link` that sets its own `prefetch` keeps it:
356
+
357
+ ```ts
358
+ // vite.config.ts
359
+ voidReact({ prefetch: { defaultStrategy: 'hover' } });
360
+ ```
361
+
362
+ Prefer `'hover'` or `'click'` as the default. With `'mount'` or `'visible'`, every `Link` loads its page once it renders or stays in view, which adds up in long lists.
363
+
364
+ `Link` doesn't prefetch while the browser reports that data saver is on or the connection is 2G, which only Chromium-based browsers report.
365
+
366
+ Prefetching runs the destination's loader, so keep loaders free of side effects such as counting views.
367
+
259
368
  ## Scroll Restoration
260
369
 
261
370
  Void manages scroll position for Pages automatically:
262
371
 
263
372
  - **Back/forward navigation and reloads** restore the saved scroll position.
264
373
  - **New navigation** scrolls to the top of the page.
374
+ - **Actions and forms** keep scroll when updating the current page. Redirects follow normal navigation behavior.
265
375
  - **Hash links** (`/docs#api`) scroll to the target element. Same-page hash links (`#section`) skip the server fetch entirely.
266
376
 
267
377
  To keep the current scroll position, pass `preserveScroll: true`:
@@ -16,7 +16,7 @@ Local development permits exact HTTP callbacks on localhost when the platform's
16
16
 
17
17
  The app sends users to Void's authorization page, where Void displays its registered name, operator, callback origin, and requested permission. Sign-in permits reading the user's ID and username. It does not provide an account token or project management access.
18
18
 
19
- Users can disconnect applications at `<platform API URL>/oauth/connections`. Grants also expire after an hour and become invalid when their platform login session is revoked or their account is suspended. Applications must request a new sign-in when access expires.
19
+ Users can disconnect applications at `<platform API URL>/oauth/connections`. Access tokens expire after an hour, and apps renew them with a refresh token. Refreshing does not extend access past the Void sign-in the user approved the app from: access ends 30 days after that sign-in, or earlier if the sign-in is revoked or the account is suspended. Applications must then ask the user to sign in again.
20
20
 
21
21
  ## Private previews
22
22
 
@@ -48,6 +48,8 @@ Disabling the app or disconnecting its grant stops authorization for subsequent
48
48
 
49
49
  Discover endpoints at `/.well-known/oauth-authorization-server` on the platform API origin. Use authorization code flow with `scope=profile`, a random `state`, and S256 PKCE. Authenticate token exchanges using HTTP Basic client authentication. Send access tokens as Bearer credentials to `/oauth/userinfo`; its response contains `sub`, `preferred_username`, and the consented `scope`.
50
50
 
51
+ The code exchange also returns a `refresh_token`. To renew access, POST `grant_type=refresh_token` and `refresh_token` to `/oauth/token` with client Basic authentication. The response has a new access token and a new `refresh_token`; store the new one and discard the old. Each refresh token works once: sending a used one again revokes the connection and the user must reconnect, so send one refresh at a time per connection. Store refresh tokens as securely as access tokens. An optional space-separated `scope` requests fewer permissions than the user approved; the connection keeps the narrower set, and later refreshes cannot widen it. `deploy:approve` publish tokens never come with a refresh token, so each publish still needs its own approval.
52
+
51
53
  For publishing, package the built app with [`prepareDeployArtifact`](/reference/api/deploy). POST to `/oauth/deployment-requests` using the profile token:
52
54
 
53
55
  ```ts
@@ -66,6 +68,6 @@ Redirect the browser to the returned `authorization_url`. Exchange its code with
66
68
 
67
69
  Use the token to request URLs from `POST /projects/:id/deploy/upload-urls`, upload the declared assets, and send the artifact to `POST /projects/:id/deploy`. Set `x-void-deploy-idempotency-key` to `approval_id`. Deployment uses Void's managed deployment protocol and requires the platform deployment Queue. The credential cannot read secrets, mint project tokens, delete projects, or deploy different bytes.
68
70
 
69
- Revoke identity grants with `POST /oauth/revoke`, authenticated as the client. No refresh token or OpenID Connect ID token is issued.
71
+ Revoke a connection with `POST /oauth/revoke`, authenticated as the client, using either its access token or its refresh token. Void does not issue an OpenID Connect ID token.
70
72
 
71
73
  If the API is protected by Cloudflare Access, the application operator must also configure a service identity permitted by that Access application's policy. Server OAuth endpoints and approved deployment requests still validate their own client, grant, and project authority; browser consent requires the user's company identity.
@@ -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.