void 0.22.0 → 0.23.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 (276) hide show
  1. package/README.md +5 -1
  2. package/dist/{account-cmd-CjyxcGkM.mjs → account-cmd-C84Ee8cO.mjs} +4 -4
  3. package/dist/{scan-ClYmX3sa.mjs → application-analysis-BVsVqc11.mjs} +135 -18
  4. package/dist/application-routing-B7QEjqSR.mjs +27 -0
  5. package/dist/{auth-CZuiVsFh.mjs → auth-CCjt0hcq.mjs} +1 -1
  6. package/dist/{auth-DLNN0D3Z.mjs → auth-CSkdO2Bb.mjs} +4 -47
  7. package/dist/{auth-link-BLO4ptzo.mjs → auth-link-CioEg6uY.mjs} +4 -4
  8. package/dist/{auth-router-ZUg9MF_U.mjs → auth-router-BsR981d4.mjs} +4 -4
  9. package/dist/{better-auth-shared-rsBGBvWJ.mjs → better-auth-shared-hy6RPh9W.mjs} +13 -2
  10. package/dist/{build-cmd-BxR5FROK.mjs → build-cmd-LzvNJORH.mjs} +17 -5
  11. package/dist/{cache-D0sWhgKI.mjs → cache-C4MvnrMH.mjs} +2 -2
  12. package/dist/{cancel-deploy-D4NUqFbi.mjs → cancel-deploy-abUxpP2n.mjs} +2 -2
  13. package/dist/{cf-build-output-BJ6yGEIS.mjs → cf-build-output-BPqOT964.mjs} +2 -1
  14. package/dist/cf-build-output-_0HNWysu.mjs +2 -0
  15. package/dist/cli/cli.mjs +80 -455
  16. package/dist/cli/{cf-compat.mjs → cloudflare-operation-process.mjs} +442 -421
  17. package/dist/cli/env-schema-probe.d.mts +2 -1
  18. package/dist/cli/env-schema-probe.mjs +3 -3
  19. package/dist/client-Cu7jWiF1.mjs +2 -0
  20. package/dist/{client-BTZ3XkrB.mjs → client-RV8NVeB8.mjs} +140 -21
  21. package/dist/{cloudflare-auth-DQkqoMYa.mjs → cloudflare-auth-Qdc7tw8F.mjs} +41 -38
  22. package/dist/{cloudflare-cmd-BKlfGHAy.mjs → cloudflare-cmd-BcrVyTmJ.mjs} +5 -5
  23. package/dist/cloudflare-config-Bktvwtpf.mjs +182 -0
  24. package/dist/{cloudflare-connect-Ctmrw579.mjs → cloudflare-connect-B8uPZ4nx.mjs} +3 -3
  25. package/dist/{cloudflare-operations-BT6OWFBk.mjs → cloudflare-operations-AiWashgg.mjs} +1 -1
  26. package/dist/{cloudflare-operations-B9tzgjmf.mjs → cloudflare-operations-fxHb-byx.mjs} +116 -172
  27. package/dist/{preset-UHj9ARyP.mjs → cloudflare-process-B-wekeR6.mjs} +93 -6
  28. package/dist/{config-VavjpDnp.d.mts → config-BMHb8RCj.d.mts} +1 -0
  29. package/dist/config-C_XRIPx2.mjs +89 -0
  30. package/dist/config-entry.d.mts +1 -1
  31. package/dist/{connect-Dg-WkW-C.mjs → connect-Bd4kJd9U.mjs} +5 -5
  32. package/dist/{create-project-DdoqwFLF.mjs → create-project-Boczwj5r.mjs} +1 -1
  33. package/dist/{create-project-l9J7pbtm.mjs → create-project-bMf6ffLZ.mjs} +2 -2
  34. package/dist/{db-gp2sCXyN.mjs → db-8uG64XLl.mjs} +21 -21
  35. package/dist/{delete-TTedbH6B.mjs → delete-NvbiyeJf.mjs} +2 -2
  36. package/dist/{deploy-CH-o2CaZ.mjs → deploy-DzAIwqNU.mjs} +908 -582
  37. package/dist/{deploy-B19L2Bra.mjs → deploy-bjXdFCtn.mjs} +1 -1
  38. package/dist/{domain-JRF59P_r.mjs → domain-y5Tvydvo.mjs} +3 -3
  39. package/dist/{email-Bo6G9LOZ.mjs → email-B3umsW75.mjs} +13 -28
  40. package/dist/{env-BYOrWQnv.mjs → env-BS6qYHDb.mjs} +4 -4
  41. package/dist/{env-public-BxU_0yTL.d.mts → env-public-BX_r8HR6.d.mts} +1 -1
  42. package/dist/{env-validation-BB4GkLxn.mjs → env-validation-BPn7vk-V.mjs} +18 -71
  43. package/dist/{env-validation-BXge7uyK.mjs → env-validation-DbTg7-ar.mjs} +1 -1
  44. package/dist/{fetch-CXDChK7B.mjs → fetch-BIZJh7vR.mjs} +2 -2
  45. package/dist/{fetch-stream-AOByI7Ki.mjs → fetch-stream-IvCYKyQL.mjs} +24 -4
  46. package/dist/{gen-sCtlCOdA.mjs → gen-B580--vC.mjs} +2 -2
  47. package/dist/gen-BVaUUumi.mjs +2 -0
  48. package/dist/{github-cmd-0-7PexDq.mjs → github-cmd-v45BdfKX.mjs} +2 -2
  49. package/dist/{handler-HEcZsaij.d.mts → handler-CZ4nAylQ.d.mts} +1 -1
  50. package/dist/help-DofyZuY7.mjs +2 -0
  51. package/dist/{help-GKtwl07I.mjs → help-daGKjXGk.mjs} +229 -747
  52. package/dist/index.d.mts +1 -1
  53. package/dist/index.mjs +288 -1502
  54. package/dist/info-B97bTX9N.mjs +113 -0
  55. package/dist/{init-FZx3Elvz.mjs → init-Bvy7zrBo.mjs} +46 -15
  56. package/dist/limits-Bq5LG8Id.d.mts +27 -0
  57. package/dist/limits-Cjuk2VPm.mjs +68 -0
  58. package/dist/{link-BrQfb_CU.mjs → link-CDqqCjFl.mjs} +3 -3
  59. package/dist/{list-D44jmIAM.mjs → list-CZj0dzKY.mjs} +3 -3
  60. package/dist/{live-CKJlvlNp.d.mts → live-Chw1eIMv.d.mts} +1 -1
  61. package/dist/{local-d1-Bg9OzEEO.mjs → local-d1-2CMnpuW_.mjs} +2 -2
  62. package/dist/login-DYt_An22.mjs +2 -0
  63. package/dist/{login-CAsAsQ-_.mjs → login-UZKFM_u7.mjs} +3 -3
  64. package/dist/{logs-BjKvFnVM.mjs → logs-CUZ6t9t3.mjs} +3 -3
  65. package/dist/migrate-8_2u55MD.mjs +2 -0
  66. package/dist/{migrate-BPITvDJN.mjs → migrate-DHul7PRV.mjs} +2 -1
  67. package/dist/{node-Dt7z256D.mjs → node-BkyRWRx8.mjs} +1 -1
  68. package/dist/operator-args-CLgKGlwU.mjs +690 -0
  69. package/dist/{operator-cmd-BK5CCiT9.mjs → operator-cmd-DBA6dl0m.mjs} +68 -22
  70. package/dist/pages/client.d.mts +34 -2
  71. package/dist/pages/client.mjs +59 -3
  72. package/dist/pages/index.d.mts +1 -1
  73. package/dist/pages/index.mjs +1 -1
  74. package/dist/pages/islands-plugin.mjs +1 -1
  75. package/dist/pages/protocol.d.mts +2 -2
  76. package/dist/pages/protocol.mjs +2 -308
  77. package/dist/{parse-filename-DioPHiR9.mjs → parse-filename-CUbj-1MP.mjs} +35 -1
  78. package/dist/plan-D1Q5rf-r.mjs +2 -0
  79. package/dist/plan-NPpwZ_kc.mjs +58 -0
  80. package/dist/platform-args-BJdRtlLq.mjs +506 -0
  81. package/dist/platform-args-D3RXyR6h.mjs +2 -0
  82. package/dist/{platform-auth-config-BlN8xTdD.mjs → platform-auth-config-B56E9YP1.mjs} +3 -3
  83. package/dist/{platform-auth-protection-7d5aV2Jg.mjs → platform-auth-protection-BDWO_aER.mjs} +2 -2
  84. package/dist/{platform-auth-recovery-Dxij8ZbR.mjs → platform-auth-recovery-1gg4CSRe.mjs} +3 -3
  85. package/dist/{platform-cmd-E0FuL212.mjs → platform-cmd-Bt-1w6pY.mjs} +1 -1
  86. package/dist/{platform-cmd-B3hwKrFK.mjs → platform-cmd-DMcQStSc.mjs} +24 -3
  87. package/dist/{platform-domain-D6Xcy9ZX.mjs → platform-domain-BNkcz0OB.mjs} +2 -2
  88. package/dist/{platform-lifecycle-k0E0xoxx.mjs → platform-lifecycle-9OyBALhH.mjs} +327 -215
  89. package/dist/{platform-lifecycle-DMh_qrry.mjs → platform-lifecycle-BE6C_jxh.mjs} +1 -1
  90. package/dist/{platform-management-Brz_BDiT.mjs → platform-management-CjwLVQwN.mjs} +6 -3
  91. package/dist/{platform-management-DOtss0BN.mjs → platform-management-CnyTdcWX.mjs} +1 -1
  92. package/dist/platform-plans-config-BNGKGr4P.mjs +359 -0
  93. package/dist/{platform-recovery-BvtcXON5.mjs → platform-recovery-D6KSpuFm.mjs} +2 -2
  94. package/dist/{plugin-inference-BMfKRSqE.mjs → plugin-inference-CXWnn79A.mjs} +174 -64
  95. package/dist/{prepare-C-6YZyyg.mjs → prepare-B5Mkic5u.mjs} +1 -1
  96. package/dist/{prepare-CRhJbVrG.mjs → prepare-DOsL0CC9.mjs} +4 -20
  97. package/dist/prepare-cgvDMtSb.mjs +2 -0
  98. package/dist/{project-cmd-BZLCqOqw.mjs → project-cmd-CNzrqvBv.mjs} +16 -16
  99. package/dist/{project-team-BvgM0WoX.mjs → project-team-DQOWPfQT.mjs} +2 -2
  100. package/dist/{project-token-l5DqK6Az.mjs → project-token-CTDYU0Cc.mjs} +2 -2
  101. package/dist/{project-zero-trust-v6Mvpp8y.mjs → project-zero-trust-BNAkW-_0.mjs} +2 -2
  102. package/dist/{protocol-BBa6cstI.d.mts → protocol-CjF_iI9X.d.mts} +2 -2
  103. package/dist/protocol-U7bfjHmA.mjs +331 -0
  104. package/dist/{provision-Fr9pRqce.mjs → provision-C4ORE7G7.mjs} +1 -1
  105. package/dist/{provision-C4IGqkBf.mjs → provision-CJFgTZY8.mjs} +89 -198
  106. package/dist/{requests-DN-BbNiM.mjs → requests-MhxYnau8.mjs} +2 -2
  107. package/dist/resource-name-C7LVpcRm.mjs +11 -0
  108. package/dist/{rollback-D7rzSaZM.mjs → rollback-CJ6iSDoU.mjs} +3 -3
  109. package/dist/route-url-CG7U-cRN.mjs +15 -0
  110. package/dist/{runner-B8wXwWlo.mjs → runner-CXA9Fh8h.mjs} +1 -1
  111. package/dist/{runner-p-dMs2UN.mjs → runner-Ol0TNjk6.mjs} +2 -2
  112. package/dist/runtime/ai.d.mts +12 -8
  113. package/dist/runtime/ai.mjs +84 -17
  114. package/dist/runtime/better-auth-mysql.mjs +1 -1
  115. package/dist/runtime/better-auth-pg.mjs +1 -1
  116. package/dist/runtime/better-auth.mjs +1 -1
  117. package/dist/runtime/client-react.mjs +2 -2
  118. package/dist/runtime/client-solid.mjs +2 -2
  119. package/dist/runtime/client-svelte.mjs +2 -2
  120. package/dist/runtime/client-vue.mjs +2 -2
  121. package/dist/runtime/client.mjs +2 -2
  122. package/dist/runtime/durable.d.mts +3 -1
  123. package/dist/runtime/durable.mjs +4 -1
  124. package/dist/runtime/email/testing.mjs +1 -1
  125. package/dist/runtime/env-public.d.mts +1 -1
  126. package/dist/runtime/fetch-stream.mjs +1 -1
  127. package/dist/runtime/fetch.mjs +1 -1
  128. package/dist/runtime/handler.d.mts +1 -1
  129. package/dist/runtime/kv.mjs +0 -1
  130. package/dist/runtime/limits.d.mts +2 -0
  131. package/dist/runtime/limits.mjs +2 -0
  132. package/dist/runtime/live-client.d.mts +1 -1
  133. package/dist/runtime/live-server.mjs +25 -16
  134. package/dist/runtime/live.d.mts +1 -1
  135. package/dist/runtime/migration-handler.mjs +62 -42
  136. package/dist/runtime/route-url.d.mts +4 -0
  137. package/dist/runtime/route-url.mjs +2 -0
  138. package/dist/runtime/routing.d.mts +180 -0
  139. package/dist/runtime/routing.mjs +1082 -0
  140. package/dist/runtime/sandbox-container.d.mts +1 -1
  141. package/dist/runtime/sandbox-container.mjs +1 -1
  142. package/dist/runtime/sandbox.d.mts +3 -3
  143. package/dist/runtime/sandbox.mjs +75 -45
  144. package/dist/runtime/sse.mjs +1 -1
  145. package/dist/runtime/validator.d.mts +1 -1
  146. package/dist/runtime/ws-server.d.mts +4 -2
  147. package/dist/runtime/ws-server.mjs +27 -2
  148. package/dist/runtime/ws.d.mts +2 -2
  149. package/dist/runtime/ws.mjs +8 -6
  150. package/dist/{sandbox-qpNBT8a3.d.mts → sandbox-XZAqzFlG.d.mts} +11 -8
  151. package/dist/{sandbox-container-DdNEBfCc.d.mts → sandbox-container-Bo0eiFKz.d.mts} +2 -1
  152. package/dist/{sandbox-container-4fdqLnyb.mjs → sandbox-container-C6ItmVuN.mjs} +4 -2
  153. package/dist/{scan-4tfN-PSn.mjs → scan-C7okrLyM.mjs} +4 -35
  154. package/dist/{secret-BOtOl_cb.mjs → secret-Dli5fP0B.mjs} +4 -4
  155. package/dist/{sse-BaC1jXko.mjs → sse-CQNaDFFV.mjs} +6 -3
  156. package/dist/validate-Dq_L3s0S.mjs +2 -0
  157. package/dist/{validate-CIUwFpjB.mjs → validate-ctOrgiS3.mjs} +2 -1
  158. package/dist/{wrangler-DQF1vKyf.mjs → wrangler-7K-bW_DL.mjs} +8 -239
  159. package/dist/{ws-BoY7vQML.d.mts → ws-CL1w7GXU.d.mts} +13 -2
  160. package/package.json +15 -8
  161. package/skills/migrate-vite-cloudflare-to-void/SKILL.md +34 -157
  162. package/skills/void/SKILL.md +50 -135
  163. package/skills/void/docs/guide/ai.md +94 -84
  164. package/skills/void/docs/guide/app-types.md +3 -32
  165. package/skills/void/docs/guide/auth.md +12 -116
  166. package/skills/void/docs/guide/database/d1.md +9 -54
  167. package/skills/void/docs/guide/database/mysql.md +1 -1
  168. package/skills/void/docs/guide/database/postgresql.md +5 -26
  169. package/skills/void/docs/guide/database.md +23 -75
  170. package/skills/void/docs/guide/deployment.md +27 -113
  171. package/skills/void/docs/guide/durable-state.md +43 -18
  172. package/skills/void/docs/guide/edge/headers.md +3 -47
  173. package/skills/void/docs/guide/edge/prerendering.md +5 -20
  174. package/skills/void/docs/guide/edge/redirects.md +11 -64
  175. package/skills/void/docs/guide/edge/revalidation.md +5 -18
  176. package/skills/void/docs/guide/edge/rewrites.md +56 -284
  177. package/skills/void/docs/guide/edge/static-assets.md +22 -72
  178. package/skills/void/docs/guide/email/domains.md +112 -0
  179. package/skills/void/docs/guide/email/receiving.md +139 -0
  180. package/skills/void/docs/guide/email/sending.md +231 -0
  181. package/skills/void/docs/guide/email.md +13 -619
  182. package/skills/void/docs/guide/env-migration.md +11 -11
  183. package/skills/void/docs/guide/env-vars.md +9 -29
  184. package/skills/void/docs/guide/index.md +0 -15
  185. package/skills/void/docs/guide/jobs.md +3 -18
  186. package/skills/void/docs/guide/kv.md +5 -11
  187. package/skills/void/docs/guide/live.md +5 -56
  188. package/skills/void/docs/guide/pages-routing/actions-and-forms.md +78 -125
  189. package/skills/void/docs/guide/pages-routing/head.md +10 -10
  190. package/skills/void/docs/guide/pages-routing/islands.md +6 -36
  191. package/skills/void/docs/guide/pages-routing/layouts.md +6 -128
  192. package/skills/void/docs/guide/pages-routing/loaders.md +3 -19
  193. package/skills/void/docs/guide/pages-routing/markdown.md +13 -171
  194. package/skills/void/docs/guide/pages-routing/overview.md +7 -17
  195. package/skills/void/docs/guide/pages-routing/view-transitions.md +1 -1
  196. package/skills/void/docs/guide/platform/administration/access.md +1 -4
  197. package/skills/void/docs/guide/platform/administration/email.md +35 -8
  198. package/skills/void/docs/guide/platform/administration/operations.md +26 -4
  199. package/skills/void/docs/guide/platform/administration/plans.md +126 -0
  200. package/skills/void/docs/guide/platform/administration/projects.md +5 -2
  201. package/skills/void/docs/guide/platform/administration/zero-trust.md +23 -152
  202. package/skills/void/docs/guide/platform/development/runtime.md +3 -13
  203. package/skills/void/docs/guide/platform/development/schema-ci.md +0 -58
  204. package/skills/void/docs/guide/platform/installation/credentials.md +6 -4
  205. package/skills/void/docs/guide/platform/installation/domains.md +30 -2
  206. package/skills/void/docs/guide/platform/installation/first-deployment.md +2 -0
  207. package/skills/void/docs/guide/platform/installation/maintenance.md +3 -1
  208. package/skills/void/docs/guide/platform/installation/prerequisites.md +20 -15
  209. package/skills/void/docs/guide/platform/installation/setup.md +9 -5
  210. package/skills/void/docs/guide/platform-administration.md +1 -0
  211. package/skills/void/docs/guide/queues.md +7 -9
  212. package/skills/void/docs/guide/quickstart.md +38 -37
  213. package/skills/void/docs/guide/remote-dev.md +4 -9
  214. package/skills/void/docs/guide/sandboxes.md +29 -21
  215. package/skills/void/docs/guide/server-routing.md +9 -72
  216. package/skills/void/docs/guide/sse.md +4 -18
  217. package/skills/void/docs/guide/ssg.md +3 -15
  218. package/skills/void/docs/guide/ssr.md +14 -62
  219. package/skills/void/docs/guide/storage.md +9 -4
  220. package/skills/void/docs/guide/type-safety.md +3 -14
  221. package/skills/void/docs/guide/typed-fetch.md +3 -7
  222. package/skills/void/docs/guide/websockets.md +68 -40
  223. package/skills/void/docs/integrations/agents.md +3 -3
  224. package/skills/void/docs/integrations/cloudflare.md +85 -316
  225. package/skills/void/docs/integrations/frameworks/analog.md +5 -64
  226. package/skills/void/docs/integrations/frameworks/astro.md +4 -73
  227. package/skills/void/docs/integrations/frameworks/nuxt.md +5 -62
  228. package/skills/void/docs/integrations/frameworks/overview.md +11 -54
  229. package/skills/void/docs/integrations/frameworks/react-router.md +5 -60
  230. package/skills/void/docs/integrations/frameworks/sveltekit.md +6 -65
  231. package/skills/void/docs/integrations/frameworks/tanstack-start.md +4 -62
  232. package/skills/void/docs/integrations/nodejs-bun-deno.md +5 -69
  233. package/skills/void/docs/reference/api/auth.md +156 -0
  234. package/skills/void/docs/reference/api/client.md +87 -0
  235. package/skills/void/docs/reference/api/database.md +95 -0
  236. package/skills/void/docs/reference/api/durable.md +46 -0
  237. package/skills/void/docs/reference/api/env.md +50 -0
  238. package/skills/void/docs/reference/api/handlers.md +254 -0
  239. package/skills/void/docs/reference/api/pages.md +241 -0
  240. package/skills/void/docs/reference/api/plugin.md +39 -0
  241. package/skills/void/docs/reference/api/resources.md +109 -0
  242. package/skills/void/docs/reference/api/rewrites.md +76 -0
  243. package/skills/void/docs/reference/api/types.md +92 -0
  244. package/skills/void/docs/reference/api.md +56 -1218
  245. package/skills/void/docs/reference/cli/auth.md +88 -0
  246. package/skills/void/docs/reference/cli/database.md +128 -0
  247. package/skills/void/docs/reference/cli/deploy.md +85 -0
  248. package/skills/void/docs/reference/cli/domains.md +41 -0
  249. package/skills/void/docs/reference/cli/email.md +129 -0
  250. package/skills/void/docs/reference/cli/generate.md +116 -0
  251. package/skills/void/docs/reference/cli/github.md +189 -0
  252. package/skills/void/docs/reference/cli/platform-config.md +92 -0
  253. package/skills/void/docs/reference/cli/platform-email.md +81 -0
  254. package/skills/void/docs/reference/cli/platform-installation.md +127 -0
  255. package/skills/void/docs/reference/cli/platform-operations.md +90 -0
  256. package/skills/void/docs/reference/cli/platform-users.md +89 -0
  257. package/skills/void/docs/reference/cli/platform-zero-trust.md +45 -0
  258. package/skills/void/docs/reference/cli/platform.md +70 -0
  259. package/skills/void/docs/reference/cli/project.md +214 -0
  260. package/skills/void/docs/reference/cli/secrets.md +76 -0
  261. package/skills/void/docs/reference/cli/setup.md +70 -0
  262. package/skills/void/docs/reference/cli.md +32 -1682
  263. package/skills/void/docs/reference/config.md +12 -18
  264. package/skills/void/docs/reference/resource-inference.md +3 -58
  265. package/skills/void/docs/reference/structure.md +14 -41
  266. package/dist/canonical-json-DuDiiUsQ.mjs +0 -13
  267. package/dist/client-Czz8o5jP.mjs +0 -2
  268. package/dist/gen-CNJ62MM7.mjs +0 -2
  269. package/dist/help-CmZzxUba.mjs +0 -2
  270. package/dist/login-CGcRKEoi.mjs +0 -2
  271. package/dist/migrate-CYfbKkXh.mjs +0 -2
  272. package/dist/plan-BEZ8VJW0.mjs +0 -256
  273. package/dist/plan-DpuOr14e.mjs +0 -2
  274. package/dist/prepare-Bm3iq-u4.mjs +0 -2
  275. package/dist/validate-EKmJWxmy.mjs +0 -2
  276. /package/dist/cli/{cf-compat.d.mts → cloudflare-operation-process.d.mts} +0 -0
@@ -6,7 +6,7 @@ outline: deep
6
6
 
7
7
  `void deploy` builds your app, provisions its resources, applies migrations, and deploys it to your own Cloudflare account or a Void platform run by your team.
8
8
 
9
- Choose Cloudflare for your own account or Void for a shared team platform. You can [install a Void platform](./self-hosted-platform.md) in your team's Cloudflare account.
9
+ You can [install a Void platform](./self-hosted-platform.md) for shared team deployments.
10
10
 
11
11
  ## Deployment Targets
12
12
 
@@ -51,21 +51,13 @@ Your choice is saved in `.void/project.json`, so the next deploy is just `void d
51
51
 
52
52
  Already have a Cloudflare Worker and a root `wrangler.jsonc` or `wrangler.json`? Run `void deploy`. If no destination is selected, Void offers to link and deploy using the existing Worker and resources. Accept once to keep deploying to that site. See [Deploy an existing Worker](../integrations/cloudflare.md#deploy-an-existing-worker) for the first-deployment checks.
53
53
 
54
- To connect to your team's platform and sign in, run `void connect <url>` using the URL from your administrator. Use `void connect --platform cloudflare` to set up your own Cloudflare account. Connecting preserves existing project links. New Void projects need a platform connection.
54
+ To set up deployment later, use `void connect --platform cloudflare` or `void connect <platform-url>`.
55
55
 
56
56
  Owners can [share a platform project](./project-collaboration.md) with readers, collaborators, and project administrators. This does not apply to direct Cloudflare deployments.
57
57
 
58
58
  ### Migrations
59
59
 
60
- If your app uses Drizzle, `void deploy` runs migrations as part of the deploy flow:
61
-
62
- 1. Build the app
63
- 2. Read SQL migrations from `db/migrations/`
64
- 3. Check that the migrations match your current schema
65
- 4. Apply pending migrations to the target database
66
- 5. Make the new deploy live
67
-
68
- If you've changed your schema without a matching migration, deploy stops. Run `void db generate`, review and commit the SQL, then deploy again. For the full database workflow and backend-specific details, see the [Database guide](./database.md).
60
+ Deploy applies pending SQL migrations from `db/migrations/`. If your schema has changes without a migration, deploy stops. Run `void db generate`, review and commit the SQL, then deploy again. See the [Database guide](./database.md).
69
61
 
70
62
  ### Flags
71
63
 
@@ -117,131 +109,53 @@ If your platform supports managed GitHub builds, the Void GitHub App can build a
117
109
 
118
110
  You don't need a deployment workflow file or a repository `VOID_TOKEN` for this path.
119
111
 
120
- 1. Initialize your Void project
121
-
122
- ```bash
123
- void init
124
- # Or, for existing Void project:
125
- void project link
126
- ```
127
-
128
- 2. Install the Void GitHub app
112
+ With a linked project, connect the repository:
129
113
 
130
- ```bash
114
+ ```sh
131
115
  void github install
132
- ```
133
-
134
- Void opens GitHub so you can install and authorize the `Void Deploy` app.
135
-
136
- In the browser, select the GitHub account/organization and grant access to the repository.
137
-
138
- :::details If someone already installed the App for your organization
139
- Join that installation instead:
140
-
141
- ```bash
142
- void github join
143
- ```
144
-
145
- :::
146
-
147
- 3. Link your repository to your project
148
-
149
- ```bash
150
116
  void github connect --executor container
151
- ```
152
-
153
- Organization installations always require a browser proof for the specific repository, including for the person who installed the App. Void does not reveal the installation's full private repository list.
154
-
155
- 4. Verify the connection
156
-
157
- ```bash
158
117
  void github status
159
118
  ```
160
119
 
161
- The output shows the repository, branch, and build executor:
120
+ If your organization already installed the App, Void can join that installation during setup. Organization repositories require browser authorization.
162
121
 
163
- ```bash
164
- Repository <owner/repository>
165
- Branch main
166
- Build executor container
167
- Deploy workflow .github/workflows/void-deploy.yml (unused for container builds)
122
+ Push to the configured branch to deploy, then follow progress with `void build logs --follow`. See [GitHub commands](../reference/cli/github.md#github) for installation sharing and connection options.
168
123
 
169
- ```
124
+ ### GitHub Actions
170
125
 
171
- 5. Push to the configured branch to trigger a new deploy
126
+ Run `void init --github` to generate the workflow for your saved platform and package manager. On Void platforms with GitHub Actions support, authorize the repository once:
172
127
 
173
- ```bash
174
- git push origin main
128
+ ```sh
129
+ void github connect <project> --repo <owner/repo> --executor github_actions
175
130
  ```
176
131
 
177
- 6. Follow the build
132
+ Set the repository's `VOID_API_URL` variable to your platform's API URL. Keep `permissions: id-token: write` in the workflow for [GitHub OIDC](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect). The workflow uses your linked project, or the `VOID_PROJECT` repository variable.
178
133
 
179
- ```bash
180
- void build logs --follow
181
- ```
182
-
183
- ### GitHub Actions
134
+ Core self-hosted installations do not support this integration. Use your own CI workflow with a [project deploy token](./platform/installation/first-deployment.md).
184
135
 
185
- On platforms that support it, the generated workflow uses [GitHub OIDC](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect) to obtain a short-lived deploy token for your project. `void deploy` handles the exchange automatically. Keep `permissions: id-token: write` in the workflow so GitHub can issue that credential.
186
-
187
- The generated workflow uses the platform selected during `void init`. Core self-hosted installations don't yet support this integration, so Void doesn't offer the workflow for them. For a platform that does, the npm version looks like this; set the repository's `VOID_API_URL` variable to your platform's API URL:
188
-
189
- ```yaml
190
- name: Deploy to Void
191
- on:
192
- push:
193
- branches: [main]
194
-
195
- # Latest push wins: a newer commit cancels an in-flight deploy for the same
196
- # repo + branch, so an older commit can never overtake a newer one.
197
- concurrency:
198
- group: void-deploy-${{ github.repository }}-${{ github.ref }}
199
- cancel-in-progress: true
200
-
201
- permissions:
202
- id-token: write
203
- contents: read
204
-
205
- env:
206
- VOID_API_URL: ${{ vars.VOID_API_URL }}
207
- VOID_PROJECT: my-app
208
-
209
- jobs:
210
- deploy:
211
- runs-on: ubuntu-latest
212
- steps:
213
- - uses: actions/checkout@v6
214
- - uses: actions/setup-node@v6
215
- with:
216
- node-version: lts/*
217
- cache: npm
218
- - run: npm ci
219
- - name: Deploy
220
- run: npx void deploy --platform void --project "$VOID_PROJECT"
221
- ```
136
+ ## Other Targets
222
137
 
223
- Authorize the repository once with `void github connect <project> --repo <owner/repo> --executor github_actions`. Choose the `github_actions` executor for this workflow; `container` runs builds on the platform instead.
138
+ ### Your own Cloudflare account
224
139
 
225
- The generated workflow uses your package manager and linked project. If no project is linked, it reads the `VOID_PROJECT` repository variable.
140
+ Select Cloudflare during setup, or run `void deploy --platform cloudflare`. See the [Cloudflare guide](../integrations/cloudflare.md) for configuration, CI credentials, and deployment limits.
226
141
 
227
- ## Other Targets
142
+ ### Node.js, Bun, and Deno
228
143
 
229
- ### Your own Cloudflare account
144
+ Set [`target`](../reference/config.md#target) in `void.config.ts` to build a standalone server for Node.js, Bun, or Deno. You can run the result on your own server or in a container.
230
145
 
231
- Select Cloudflare during setup, or run:
146
+ Deploy `dist/ssr` and `dist/client` together. See the target guide for startup commands.
232
147
 
233
- ```sh
234
- void deploy --platform cloudflare
235
- ```
148
+ These targets don't provide Cloudflare bindings such as D1, KV, R2, and Workers AI. See the [Node.js, Bun, and Deno guide](../integrations/nodejs-bun-deno.md) for the features available on each target.
236
149
 
237
- Void supports full Worker apps, static sites, SPAs, and Cloudflare builds from supported frameworks. It provisions resources, applies migrations, and manages secrets for you. `.env` stays local; production server keys declared in `env.ts` must exist in encrypted remote secret storage and are rejected as plaintext Worker vars. Commands such as `void secret put`, `void project logs`, and `void project rollback` then use the same account and Worker.
150
+ ## Usage and execution limit pages
238
151
 
239
- See the [Cloudflare guide](../integrations/cloudflare.md#deploy-to-your-own-cloudflare-account) for supported features, CI setup, and deployment limits.
152
+ Void platforms show a built-in page when an app exhausts its request allowance or an invocation exceeds its CPU limit. API requests and Pages action requests receive a structured HTTP 429 with `code: 'usage_limit'`, `resource`, `reason`, and `message`.
240
153
 
241
- ### Node.js, Bun, and Deno
154
+ To customize browser error pages, add either optional file to your app's public assets:
242
155
 
243
- Set [`target`](../reference/config.md#target) in `void.config.ts` to build a standalone server for Node.js, Bun, or Deno. You can run the result on your own server or in a container.
156
+ - `public/usage-limit.html` for exhausted request allowances.
157
+ - `public/execution-limit.html` for execution limits.
244
158
 
245
- Deploy `dist/ssr` and `dist/client` together. The server loads the Pages client manifest and assets relative to its emitted module; start it from the app root with `node dist/ssr/index.js`, `bun dist/ssr/index.js`, or `deno run -A dist/ssr/index.js`.
159
+ Use standalone HTML with inline CSS and data-URL images. These pages run with scripts, external assets and form submissions disabled, so they remain usable while application requests are blocked. Void serves them directly from the deployed assets; your Worker, loaders and database are not involved. A missing or unreadable custom page uses the built-in page.
246
160
 
247
- These targets don't provide Cloudflare bindings such as D1, KV, R2, and Workers AI. See the [Node.js, Bun, and Deno guide](../integrations/nodejs-bun-deno.md) for the features available on each target.
161
+ Responses are not cached. Once a streaming response has started, it cannot be replaced with an error page; clients should display stream failures and end their pending state. These platform pages apply to Void platform deployments. Direct Cloudflare runtime limits use Cloudflare's own response behavior.
@@ -6,9 +6,9 @@ outline: deep
6
6
 
7
7
  Use a Durable Object when requests need to share state under one name, such as a shopping cart, room, or rate limiter. Void gives you typed methods and stores the object's state between calls.
8
8
 
9
- Void turns each module in `durable-objects/` into a SQLite-backed Cloudflare Durable Object. The filename determines the binding, Worker class, and initial Cloudflare migration, so no manual Cloudflare configuration is needed.
9
+ Create a module in `durable-objects/` with `defineDurableState()`. Void provides a SQLite-backed Cloudflare Durable Object for it. This feature supports native Void apps deployed directly to Cloudflare.
10
10
 
11
- Void records the inferred binding and migration entry in `void.lock.json`. Commit that file: Cloudflare Durable Object migrations are append-only, and the persisted order ensures a newly added module is migrated after every class already deployed.
11
+ Commit `void.lock.json` when Void adds a resource. Keep its deployed migration entries in their original order.
12
12
 
13
13
  ## Define state and methods
14
14
 
@@ -32,21 +32,11 @@ export const Counter = defineDurableState({
32
32
  export default Counter;
33
33
  ```
34
34
 
35
- The default export must be the object returned by `defineDurableState()`. Void uses it to export the generated Cloudflare class and associate the inferred binding at worker startup.
36
-
37
- For `counter.ts`, Void generates:
38
-
39
- | Resource | Generated name |
40
- | ------------------------ | ------------------------- |
41
- | Binding | `COUNTER` |
42
- | Worker class | `CounterDurableObject` |
43
- | Cloudflare migration tag | `void-durable-counter-v1` |
44
-
45
- Names are derived from kebab-case filenames: `shopping-cart.ts` becomes `SHOPPING_CART` and `ShoppingCartDurableObject`.
35
+ Default-export the object returned by `defineDurableState()`.
46
36
 
47
37
  ## Call it from a route
48
38
 
49
- Import the same named definition and select an object by name. Calls are typed from the method definitions, including arguments and return values.
39
+ Import your definition and call `get()` with a name to select an object. Method arguments and return values are typed:
50
40
 
51
41
  ```ts
52
42
  // routes/api/counter.ts
@@ -64,8 +54,6 @@ The same name always resolves to the same Durable Object. Use `getById(id)` when
64
54
 
65
55
  ## Execution and persistence
66
56
 
67
- Typed methods run through Cloudflare RPC on the generated Durable Object class. Only your declared methods are exposed; Void’s state-loading and persistence helpers stay private.
68
-
69
57
  Void loads state before the first operation and runs RPC methods one at a time. After a method, `fetch`, or `alarm` handler succeeds, it saves the updated state.
70
58
 
71
59
  If the handler or save fails, Void restores `context.state` to its previous value. Direct writes to `context.storage` aren't included in that rollback.
@@ -127,14 +115,51 @@ export const Counter = defineDurableState({
127
115
  export default Counter;
128
116
  ```
129
117
 
130
- These state migrations are separate from Cloudflare's Durable Object class migration. Void generates the latter with `new_sqlite_classes` when it discovers the file.
118
+ State migrations update your saved values. Void manages Cloudflare’s separate class migrations in `void.lock.json`.
131
119
 
132
120
  Do not delete or reorder generated Durable Object migrations in `void.lock.json` after deployment. For a class addition, rename, or removal on an existing Worker, review the migration and run `void deploy --platform cloudflare --atomic`. If this Worker needs atomic publication on every deploy, set `deploy: { cloudflare: { mode: 'atomic' } }` in `void.config.ts`. Cloudflare applies class lifecycle changes in one deployment. The Worker receives traffic before Void checks readiness, and you cannot roll back across that migration boundary. Staged deploys keep pre-traffic readiness verification.
133
121
 
122
+ ## Rename a file while keeping its state
123
+
124
+ Before renaming a deployed definition, run:
125
+
126
+ ```sh
127
+ void info
128
+ ```
129
+
130
+ For `durable-objects/counter.ts`, Void prints:
131
+
132
+ ```text
133
+ To preserve this resource when moving its code, add this to 'defineDurableState':
134
+ name: "counter",
135
+ ```
136
+
137
+ Add that property to the existing definition:
138
+
139
+ ```ts
140
+ export const Counter = defineDurableState({
141
+ name: 'counter',
142
+ initialState: { count: 0 },
143
+ methods: {
144
+ read(context) {
145
+ return context.state.count;
146
+ },
147
+ },
148
+ });
149
+
150
+ export default Counter;
151
+ ```
152
+
153
+ Rename the file within `durable-objects/`, update its imports, and deploy. Keep `name: 'counter'` and the names passed to `Counter.get()` unchanged to preserve the stored state.
154
+
155
+ `name` is optional. Use a static string, either inline or in a local `const`, containing words that start with a letter, such as `'shopping-cart'`. Names must produce distinct Worker classes and bindings. Changing an existing resource's `name` selects a different resource.
156
+
157
+ If you already moved the file, `void info` also shows resources recorded in `void.lock.json` without a matching definition. Identify the original resource and use its suggested name. If no name can be suggested, restore the original file from source history and run `void info` before moving it again. Keep the existing lock and migration history.
158
+
134
159
  ## Deployment support
135
160
 
136
161
  Typed state works in local development and direct Cloudflare deploys of native Void apps. Deploy with `void deploy --platform cloudflare`.
137
162
 
138
- Deploying custom Durable Object modules to a Void platform isn't supported yet. `void deploy --platform void` stops before building and points you to the Cloudflare path. Meta-frameworks and Node.js, Bun, and Deno targets also reject `durable-objects/` with guidance.
163
+ Custom Durable Object modules are not supported on Void platforms, in meta-frameworks, or on Node.js, Bun, and Deno.
139
164
 
140
165
  This is separate from [typed WebSocket routes](./websockets.md), which also use SQLite-backed Durable Objects and work on both direct Cloudflare and hosted Void deployments.
@@ -25,44 +25,13 @@ Define custom response headers in [`void.config.ts`](../../reference/config) usi
25
25
  - All matching rules are merged. When multiple rules set the same header name, the **last match wins**.
26
26
  - User-defined `Cache-Control` overrides the built-in default. The default still applies when no rule matches.
27
27
 
28
- ## Example: security headers
29
-
30
- ```json
31
- {
32
- "routing": {
33
- "headers": {
34
- "/*": [
35
- "X-Frame-Options: DENY",
36
- "X-Content-Type-Options: nosniff",
37
- "Referrer-Policy: strict-origin-when-cross-origin"
38
- ]
39
- }
40
- }
41
- }
42
- ```
43
-
44
- ## Example: override caching
45
-
46
- ```json
47
- {
48
- "routing": {
49
- "headers": {
50
- "/*.html": ["Cache-Control: public, max-age=300"],
51
- "/config.json": ["Cache-Control: no-store"]
52
- }
53
- }
54
- }
55
- ```
56
-
57
28
  ## Scope
58
29
 
59
- The dispatch Worker applies header rules to static assets, SSR pages, and API responses, including hashed assets served from cache. For example, you can add the cross-origin headers a page needs for Worker or WebAssembly files.
30
+ Header rules apply to static assets, SSR pages, and API responses, including hashed assets served from cache.
60
31
 
61
32
  For hashed assets, you can add headers, but the platform keeps control of caching and response encoding. Rules cannot replace `Cache-Control`, `Content-Type`, `Content-Encoding`, `Content-Length`, `Content-Range`, `Accept-Ranges`, or `Transfer-Encoding` on these files.
62
33
 
63
- Header rules do not apply to:
64
-
65
- - ISR cache responses (these have their own cache-control headers)
34
+ Header rules do not apply to ISR cache responses.
66
35
 
67
36
  ### Blocked headers
68
37
 
@@ -70,17 +39,4 @@ Header rules do not apply to:
70
39
 
71
40
  ## Framework `_headers` files
72
41
 
73
- Meta-frameworks like SvelteKit, Nuxt, and Astro generate a `_headers` file with cache rules for their hashed asset directories. Void automatically parses this file during deploy and merges the rules into the deploy manifest.
74
-
75
- - Framework-generated rules are applied **before** `void.config.ts` rules. Since the last match wins, `routing.headers` in `void.config.ts` takes precedence and can override framework defaults.
76
- - The `_headers` file is not uploaded as a static asset. Its contents are parsed and included in the manifest only.
77
-
78
- No configuration is needed. If the framework generates a `_headers` file, it is picked up automatically.
79
-
80
- ## How headers work
81
-
82
- 1. `void deploy` reads header rules from the framework `_headers` file (if present) and `routing.headers` in `void.config.ts`, then includes them in the deploy manifest.
83
- 2. The platform stores the rules in the KV routing entry for your project.
84
- 3. The dispatch Worker adds matching headers before returning a response. Most cached responses include those headers. Hashed assets get header rules on each response, including cache hits, so a rule change takes effect without changing the file.
85
-
86
- Headers are applied at the edge as part of serving the response; no separate network request is needed.
42
+ Void reads `_headers` files produced by supported frameworks. Your `routing.headers` rules run afterward, so they can override framework defaults. No additional setup is needed.
@@ -4,7 +4,7 @@ outline: deep
4
4
 
5
5
  # Edge Prerendering
6
6
 
7
- You can instruct Void to prerender a page so it is served from cache immediately after a new deploy. Prerendering happens on the platform at deploy time. The platform invokes the uploaded worker and writes the result to the edge cache.
7
+ Prerender pages at deploy time so the first visitor receives cached HTML.
8
8
 
9
9
  - [Markdown pages](../pages-routing/markdown.md) are auto-prerendered.
10
10
  - [Island pages](../pages-routing/islands) with no companion loader and no dynamic params are also auto-prerendered.
@@ -16,13 +16,9 @@ Export `prerender = true` from the companion `.server.ts` file:
16
16
  ```ts
17
17
  // pages/about.server.ts
18
18
  export const prerender = true;
19
-
20
- export const loader = defineHandler(async (c) => {
21
- // ...
22
- });
23
19
  ```
24
20
 
25
- Pages with no dynamic params are automatically prerendered at their URL pattern (e.g. `/about`).
21
+ Pages without dynamic params do not need `getPrerenderPaths()`.
26
22
 
27
23
  ## Dynamic pages (with params)
28
24
 
@@ -36,10 +32,6 @@ export async function getPrerenderPaths() {
36
32
  // Return param objects matching the URL pattern
37
33
  return [{ slug: 'hello-world' }, { slug: 'getting-started' }];
38
34
  }
39
-
40
- export const loader = defineHandler(async (c) => {
41
- // ...
42
- });
43
35
  ```
44
36
 
45
37
  ## Custom SSR
@@ -53,21 +45,15 @@ export const prerender = true;
53
45
  export async function getPrerenderPaths() {
54
46
  return ['/', '/about', '/blog/hello-world'];
55
47
  }
56
-
57
- export default defineRender(async (c, assetTags) => {
58
- // ...
59
- });
60
48
  ```
61
49
 
62
50
  ## Relationship to revalidation
63
51
 
64
52
  Setting `routing.isr: false` in `void.config.ts` disables ISR and this edge-prerendering behavior, including per-page exports. It does not disable build-time HTML generation with `output: "static"`.
65
53
 
66
- Pages with long revalidate TTLs (e.g. 1 year) are effectively static, but the first visitor after a deploy hits a cold cache. This is where prerendering helps - it ensures your users never get slow requests.
67
-
68
- Enabling prerendering for a page automatically sets `revalidate` to 1 year, so you don't need to export it yourself. Since the ISR cache is cleared on every deploy, the TTL only needs to be long enough to last between deploys.
54
+ Prerendered pages default to a one-year revalidate TTL. Deploys clear the ISR cache.
69
55
 
70
- You can also explicitly set to it a different value to override the default:
56
+ Override the TTL per page:
71
57
 
72
58
  ```ts
73
59
  // pages/about.server.ts
@@ -75,11 +61,10 @@ export const prerender = true;
75
61
  export const revalidate = 3600;
76
62
  ```
77
63
 
78
- Just be aware that if no new deploy happens before the revalidate expires, the first user request after expiration will miss the cache and incur a full render.
64
+ If the cached page expires before your next deploy, the next request waits for a fresh render.
79
65
 
80
66
  ## Behavior details
81
67
 
82
68
  - Prerender happens once per deployment, before traffic is routed to the new version. Prerendered pages are cached at the edge.
83
- - Each deploy clears the ISR cache. The deployment shows `"prerendering"` during this phase.
84
69
  - Only paths with a positive revalidate TTL are prerendered (TTL `0` is skipped).
85
70
  - Prerender failures are logged but never block the deploy. The page will render on the first request as usual.
@@ -23,42 +23,12 @@ Define URL redirects in [`void.config.ts`](../../reference/config) using the `ro
23
23
  - **Destinations** can be strings (default `302`) or objects with `to` and optional `status`. Supported statuses: `301`, `302`, `303`, `307`, `308`.
24
24
  - `:splat` in the destination is replaced with the portion of the path matched by `*` in the source pattern.
25
25
  - Destination query strings are merged into the `Location` header (the destination's parameters take precedence on per-key conflict). To drop the incoming query, write an explicit reset like `?`.
26
- - When multiple rules match, the **first match wins**. Put more-specific rules above more-general ones (matches Netlify `_redirects` and Vercel `vercel.json` semantics).
26
+ - When multiple rules match, the **first match wins**. Put specific patterns before catch-all patterns.
27
27
  - Redirects are evaluated **before** the request reaches the worker, so they short-circuit static asset serving, ISR, and SSR.
28
28
 
29
- ## Example: permanent redirect
30
-
31
- ```json
32
- {
33
- "routing": {
34
- "redirects": {
35
- "/old-page": { "to": "/new-page", "status": 301 }
36
- }
37
- }
38
- }
39
- ```
40
-
41
- ## Example: path prefix migration
42
-
43
- ```json
44
- {
45
- "routing": {
46
- "redirects": {
47
- "/blog/*": { "to": "/posts/:splat", "status": 301 }
48
- }
49
- }
50
- }
51
- ```
52
-
53
- A request to `/blog/hello-world` redirects to `/posts/hello-world` with a `301` status.
54
-
55
29
  ## Domain-level redirects
56
30
 
57
- Scope a redirect to a specific Host header by prefixing the source with `https://host`. Useful for:
58
-
59
- - **Domain consolidation** — redirect everything from an old marketing domain to a new one without per-host deploy config.
60
- - **Canonical host enforcement** — `www.example.com` → `example.com`.
61
- - **Per-domain rules on a multi-domain project** — when you've bound several custom domains to one project but want different behavior on each.
31
+ Prefix a source with `https://host` to redirect only requests to that domain:
62
32
 
63
33
  ```json
64
34
  {
@@ -74,43 +44,20 @@ Scope a redirect to a specific Host header by prefixing the source with `https:/
74
44
  The `_redirects` file accepts the same syntax:
75
45
 
76
46
  ```
77
- https://www.example.com/* https://example.com/:splat 301!
47
+ https://www.example.com/* https://example.com/:splat 301
78
48
  ```
79
49
 
80
- The host portion is split off the source and stored as a `host` field on the rule. Path-only sources (no `https://` prefix) apply to every domain bound to the project — that's the existing behavior. Host-prefixed sources only fire when the request's `Host` header matches.
81
-
82
- ### Validation
83
-
84
- - The host must be a literal hostname — wildcards (`*.example.com`), ports, paths, and userinfo are rejected.
85
- - Only `https://` is accepted. `http://` and protocol-relative `//` sources are rejected — TLS terminates upstream of the worker, so an `http://`-scoped rule physically cannot fire.
86
- - The host must be **bound to your project** (either `<slug>.void.app` or a custom domain you've added via `void domain add`). `void deploy` rejects rules scoped to hosts that aren't on the project — staging the rule in the same change as the domain is the recommended flow.
87
- - Custom domains in `pending` (DCV-in-progress) state are accepted. The rule deploys but stays inert until DCV completes; once the certificate is issued, the rule starts firing automatically without a redeploy.
88
-
89
- ### Combined with external destinations
50
+ Path-only sources apply to every domain on the project. Host-prefixed sources apply only to the named domain.
90
51
 
91
- The source `host` and the destination URL are independent. Combining them lets you express domain-consolidation redirects in a single rule:
92
-
93
- ```
94
- https://old.example.com/* https://www.example.com/:splat 301!
95
- ```
96
-
97
- Reads as "when a request hits `old.example.com` on any path, send a 301 to the same path on `www.example.com`."
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.
98
53
 
99
54
  ## Framework `_redirects` files
100
55
 
101
- Meta-frameworks may generate a `_redirects` file during build. Void parses this file at deploy time and merges the rules into the deploy manifest.
56
+ Void reads `_redirects` files produced by supported frameworks. You can also place one in Vite's `publicDir`:
102
57
 
103
- - `void.config.ts` rules are applied **before** framework-generated `_redirects` rules. Since the first match wins, `routing.redirects` in `void.config.ts` takes precedence.
104
- - Both 3xx redirect rules and status `200` [rewrite rules](./rewrites) are supported in `_redirects` files.
105
- - The `!` force suffix is only meaningful on `200` entries (see [rewrites — `_redirects` file](./rewrites#redirects-file)). On 3xx entries (`301!`, `302!`, `307!`, `308!`) it's silently stripped — a redirect always "forces" by nature, so the suffix is redundant. `void deploy` prints a single aggregated warning tallying every such entry so you can clean them up.
106
- - The `_redirects` file is not uploaded as a static asset. Its contents are parsed and included in the manifest only.
107
-
108
- Precedence when the same source appears in both sources follows the same rules as rewrites — config rules are merged before file rules within each phase, and first match wins, so `void.config.ts` overrides `_redirects`. See [rewrite precedence](./rewrites.md) for a worked example.
109
-
110
- ## How redirects work
111
-
112
- 1. `void deploy` reads redirect rules from the framework `_redirects` file (if present) and `routing.redirects` in `void.config.ts`, then includes them in the deploy manifest.
113
- 2. The platform stores the rules in the KV routing entry for your project.
114
- 3. The dispatch worker checks redirect rules before any worker invocation, so matching requests get a redirect response immediately.
58
+ ```text
59
+ /old-page /new-page 301
60
+ /blog/* /posts/:splat 301
61
+ ```
115
62
 
116
- Because rules are evaluated at the edge before invoking the worker, redirects add no latency to the request path.
63
+ Rules in `void.config.ts` take precedence over file rules. Use `200` for a fallback or `200!` for a [rewrite](./rewrites#redirects-file). Redirects don't need the `!` suffix.
@@ -74,13 +74,9 @@ When multiple sources set a revalidate TTL, the most specific wins:
74
74
 
75
75
  ## How revalidation works
76
76
 
77
- 1. **First request:** there is no cache entry yet. The worker renders the page, returns the response, and writes the result to KV in the background.
77
+ The first request renders and caches the page. While the cached page is fresh, visitors receive it immediately. Once it becomes stale, Void serves it while rendering an updated version in the background.
78
78
 
79
- 2. **Subsequent requests (fresh):** the cached response is served from the edge cache or KV. No worker call is needed.
80
-
81
- 3. **Subsequent requests (stale):** the stale cached response is served immediately, and the worker re-renders in the background. The next request gets the fresh version.
82
-
83
- While a stale entry is available, visitors can receive it without waiting for the refresh. A request without a cached entry still needs to render the page.
79
+ A request without a cached entry waits for the page to render.
84
80
 
85
81
  ## Per-response TTL override
86
82
 
@@ -100,8 +96,9 @@ export const GET = defineHandler(async (c) => {
100
96
 
101
97
  Only complete `200` responses are cached. A response with `Cache-Control: private`,
102
98
  `no-store`, or `no-cache`, or any `Set-Cookie` header, stays private to that request.
103
- If a previously public page starts returning one of those headers during background
104
- revalidation, Void removes its HTML, Pages JSON, and KV cache entries.
99
+ If a public page starts returning one of those headers, Void removes its cached response.
100
+
101
+ Responses that vary by request headers, such as `Vary: Accept-Language` or `Vary: Origin`, are rendered live. `Vary: *` also disables shared caching. Void's `X-VoidPages` header is supported because HTML and Pages JSON have separate cached responses.
105
102
 
106
103
  ## Cache bypass
107
104
 
@@ -115,16 +112,6 @@ Query parameters are excluded by default. Add `routing.revalidateQueryAllowlist`
115
112
 
116
113
  Purge the destination pathname with `revalidate({ paths })`. Purging `/en/docs/foo` clears both direct and rewritten variants. Purging only `/docs/foo` won't clear them, because the entries are stored under the destination.
117
114
 
118
- ::: details Upgrading from the older ISR cache format
119
-
120
- The current format uses a `v3` host-scoped prefix and a cache-policy version in its
121
- metadata. Entries written before the current response-privacy policy are treated as
122
- cold misses and refill only from responses that are safe to share.
123
-
124
- Adding a rewrite also changes the affected page's cache key, so that page starts with a cold cache again.
125
-
126
- :::
127
-
128
115
  ## On-demand revalidation
129
116
 
130
117
  You can purge ISR cache entries programmatically from a route handler: