void 0.21.9 → 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 (293) hide show
  1. package/README.md +5 -1
  2. package/dist/{account-cmd-DZZGK80W.mjs → account-cmd-C84Ee8cO.mjs} +5 -5
  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-B_CeugBw.mjs → auth-link-CioEg6uY.mjs} +5 -5
  8. package/dist/{auth-router-BgEFRuvZ.mjs → auth-router-BsR981d4.mjs} +5 -5
  9. package/dist/{better-auth-shared-rsBGBvWJ.mjs → better-auth-shared-hy6RPh9W.mjs} +13 -2
  10. package/dist/{build-cmd-Dpt0jd-x.mjs → build-cmd-LzvNJORH.mjs} +19 -7
  11. package/dist/{cache-7_UeZdTk.mjs → cache-C4MvnrMH.mjs} +4 -4
  12. package/dist/{cancel-deploy-D23R1RXT.mjs → cancel-deploy-abUxpP2n.mjs} +4 -4
  13. package/dist/{cf-build-output-CGT03qCD.mjs → cf-build-output-BPqOT964.mjs} +141 -63
  14. package/dist/cf-build-output-_0HNWysu.mjs +2 -0
  15. package/dist/cli/cli.mjs +114 -460
  16. package/dist/cli/cloudflare-operation-process.mjs +1103 -0
  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-QTl6ko_D.mjs → client-RV8NVeB8.mjs} +165 -21
  21. package/dist/{cloudflare-auth-C4_GPZr0.mjs → cloudflare-auth-Qdc7tw8F.mjs} +41 -43
  22. package/dist/{cloudflare-cmd-bSmZ1d5L.mjs → cloudflare-cmd-BcrVyTmJ.mjs} +9 -10
  23. package/dist/cloudflare-config-Bktvwtpf.mjs +182 -0
  24. package/dist/{cloudflare-connect-jAwacxxP.mjs → cloudflare-connect-B8uPZ4nx.mjs} +4 -4
  25. package/dist/{cloudflare-operations-BipGMJ5O.mjs → cloudflare-operations-AiWashgg.mjs} +1 -1
  26. package/dist/{cloudflare-operations-sMZXpk_S.mjs → cloudflare-operations-fxHb-byx.mjs} +118 -203
  27. package/dist/{preset-UHj9ARyP.mjs → cloudflare-process-B-wekeR6.mjs} +93 -6
  28. package/dist/{config-CF69HgXc.d.mts → config-BMHb8RCj.d.mts} +2 -2
  29. package/dist/{config-CafTW6Cz.mjs → config-Br_JZD6u.mjs} +2 -7
  30. package/dist/config-C_XRIPx2.mjs +89 -0
  31. package/dist/{config-s7Xj7tPb.mjs → config-CyQ-wVd7.mjs} +1 -1
  32. package/dist/config-entry.d.mts +1 -1
  33. package/dist/{config-write-BSduPMY8.mjs → config-write-B1f88wJA.mjs} +1 -1
  34. package/dist/{connect-BsUSRzln.mjs → connect-Bd4kJd9U.mjs} +6 -6
  35. package/dist/{create-project-BniEV0OW.mjs → create-project-Boczwj5r.mjs} +1 -1
  36. package/dist/{create-project-DBfFSZKY.mjs → create-project-bMf6ffLZ.mjs} +9 -5
  37. package/dist/{db-hRrvZaq_.mjs → db-8uG64XLl.mjs} +26 -26
  38. package/dist/{delete-D6dZ9B6B.mjs → delete-NvbiyeJf.mjs} +4 -4
  39. package/dist/{deploy-WaAQez1O.mjs → deploy-DzAIwqNU.mjs} +944 -607
  40. package/dist/{deploy-DDz7c8LK.mjs → deploy-bjXdFCtn.mjs} +1 -1
  41. package/dist/{dist-BR1quN_w.mjs → dist-AoCzRTJE.mjs} +226 -60
  42. package/dist/{dist-C5fND3R0.mjs → dist-BuDuKZJv.mjs} +1 -1
  43. package/dist/{dist-Dn6nn2IU.mjs → dist-CTBk70IR.mjs} +42 -42
  44. package/dist/{domain-Dmhvb2oU.mjs → domain-y5Tvydvo.mjs} +5 -5
  45. package/dist/{email-DFi-s2t4.mjs → email-B3umsW75.mjs} +15 -30
  46. package/dist/{env-Csi-tMbT.mjs → env-BS6qYHDb.mjs} +6 -6
  47. package/dist/{env-public-D_6u46fX.d.mts → env-public-BX_r8HR6.d.mts} +2 -1
  48. package/dist/{env-validation-BB4GkLxn.mjs → env-validation-BPn7vk-V.mjs} +18 -71
  49. package/dist/{env-validation-BXge7uyK.mjs → env-validation-DbTg7-ar.mjs} +1 -1
  50. package/dist/{fetch-CXDChK7B.mjs → fetch-BIZJh7vR.mjs} +2 -2
  51. package/dist/{fetch-stream-AOByI7Ki.mjs → fetch-stream-IvCYKyQL.mjs} +24 -4
  52. package/dist/{gen-Dz3X1Qab.mjs → gen-B580--vC.mjs} +5 -5
  53. package/dist/gen-BVaUUumi.mjs +2 -0
  54. package/dist/{github-cmd-BED3_9JD.mjs → github-cmd-v45BdfKX.mjs} +6 -8
  55. package/dist/{handler-BXJTXd02.d.mts → handler-CZ4nAylQ.d.mts} +2 -1
  56. package/dist/{headers-BOg_velo.mjs → headers-DWi2IXWx.mjs} +1 -1
  57. package/dist/help-DofyZuY7.mjs +2 -0
  58. package/dist/{help-DC7gdz7L.mjs → help-daGKjXGk.mjs} +268 -666
  59. package/dist/index.d.mts +1 -1
  60. package/dist/index.mjs +305 -1490
  61. package/dist/info-B97bTX9N.mjs +113 -0
  62. package/dist/{init-WO0JlPx8.mjs → init-Bvy7zrBo.mjs} +51 -20
  63. package/dist/limits-Bq5LG8Id.d.mts +27 -0
  64. package/dist/limits-Cjuk2VPm.mjs +68 -0
  65. package/dist/{link-CsHOinF7.mjs → link-CDqqCjFl.mjs} +5 -5
  66. package/dist/{list-CDb-4bZ1.mjs → list-CZj0dzKY.mjs} +5 -5
  67. package/dist/{live-CKiJilLr.d.mts → live-Chw1eIMv.d.mts} +1 -1
  68. package/dist/{local-d1-CC8sKFGu.mjs → local-d1-2CMnpuW_.mjs} +2 -2
  69. package/dist/login-DYt_An22.mjs +2 -0
  70. package/dist/{login-DvqXsfGs.mjs → login-UZKFM_u7.mjs} +5 -5
  71. package/dist/{logs-BdfiOezj.mjs → logs-CUZ6t9t3.mjs} +5 -5
  72. package/dist/migrate-8_2u55MD.mjs +2 -0
  73. package/dist/{migrate-B8KuoYsO.mjs → migrate-DHul7PRV.mjs} +5 -4
  74. package/dist/{node-BM43oz4G.mjs → node-BkyRWRx8.mjs} +2 -2
  75. package/dist/operator-args-CLgKGlwU.mjs +690 -0
  76. package/dist/{operator-cmd-03819ATr.mjs → operator-cmd-DBA6dl0m.mjs} +69 -23
  77. package/dist/output-Dm_A4Tbv.mjs +81 -0
  78. package/dist/pages/client.d.mts +34 -2
  79. package/dist/pages/client.mjs +59 -3
  80. package/dist/pages/index.d.mts +1 -1
  81. package/dist/pages/index.mjs +3 -3
  82. package/dist/pages/islands-plugin.d.mts +16 -6
  83. package/dist/pages/islands-plugin.mjs +2 -2
  84. package/dist/pages/protocol.d.mts +2 -2
  85. package/dist/pages/protocol.mjs +2 -308
  86. package/dist/{parse-filename-DioPHiR9.mjs → parse-filename-CUbj-1MP.mjs} +35 -1
  87. package/dist/{output-CCH48AMM.mjs → picocolors-BTps1_gs.mjs} +2 -76
  88. package/dist/plan-D1Q5rf-r.mjs +2 -0
  89. package/dist/plan-NPpwZ_kc.mjs +58 -0
  90. package/dist/platform-args-BJdRtlLq.mjs +506 -0
  91. package/dist/platform-args-D3RXyR6h.mjs +2 -0
  92. package/dist/{platform-auth-config-z92h63q5.mjs → platform-auth-config-B56E9YP1.mjs} +4 -4
  93. package/dist/{platform-auth-protection-DeE3yr2R.mjs → platform-auth-protection-BDWO_aER.mjs} +3 -3
  94. package/dist/{platform-auth-recovery-o_340Ixx.mjs → platform-auth-recovery-1gg4CSRe.mjs} +4 -4
  95. package/dist/{platform-cmd-C4ZV3Vpy.mjs → platform-cmd-Bt-1w6pY.mjs} +1 -1
  96. package/dist/{platform-cmd-DNl8WosH.mjs → platform-cmd-DMcQStSc.mjs} +26 -5
  97. package/dist/{platform-domain-CU1JtJkW.mjs → platform-domain-BNkcz0OB.mjs} +36 -9
  98. package/dist/{platform-lifecycle-Bc047IeT.mjs → platform-lifecycle-9OyBALhH.mjs} +850 -276
  99. package/dist/{platform-lifecycle-Bs2qx1E3.mjs → platform-lifecycle-BE6C_jxh.mjs} +1 -1
  100. package/dist/{platform-management-CVpGI9Y5.mjs → platform-management-CjwLVQwN.mjs} +59 -11
  101. package/dist/{platform-management-C8tt6D8h.mjs → platform-management-CnyTdcWX.mjs} +1 -1
  102. package/dist/platform-plans-config-BNGKGr4P.mjs +359 -0
  103. package/dist/{platform-recovery-dvUaptLr.mjs → platform-recovery-D6KSpuFm.mjs} +2 -2
  104. package/dist/{plugin-inference-BMfKRSqE.mjs → plugin-inference-CXWnn79A.mjs} +174 -64
  105. package/dist/{prepare-DyZ-Yok5.mjs → prepare-B5Mkic5u.mjs} +3 -3
  106. package/dist/{prepare-C3kt3Rst.mjs → prepare-DOsL0CC9.mjs} +4 -20
  107. package/dist/prepare-cgvDMtSb.mjs +2 -0
  108. package/dist/{project-cmd-B44I8J_W.mjs → project-cmd-CNzrqvBv.mjs} +30 -16
  109. package/dist/{project-team-BkbYIsXN.mjs → project-team-DQOWPfQT.mjs} +4 -4
  110. package/dist/{project-token-C8xEEQnB.mjs → project-token-CTDYU0Cc.mjs} +4 -4
  111. package/dist/project-zero-trust-BNAkW-_0.mjs +63 -0
  112. package/dist/{protocol-ZH3jP4a7.d.mts → protocol-CjF_iI9X.d.mts} +2 -2
  113. package/dist/protocol-U7bfjHmA.mjs +331 -0
  114. package/dist/{provision-DNtrtaVD.mjs → provision-C4ORE7G7.mjs} +1 -1
  115. package/dist/{provision-BhreDAOS.mjs → provision-CJFgTZY8.mjs} +111 -215
  116. package/dist/{requests-DFyhBMaf.mjs → requests-MhxYnau8.mjs} +4 -4
  117. package/dist/resource-name-C7LVpcRm.mjs +11 -0
  118. package/dist/{rollback-DHHxXZiS.mjs → rollback-CJ6iSDoU.mjs} +5 -5
  119. package/dist/route-url-CG7U-cRN.mjs +15 -0
  120. package/dist/{runner-B8wXwWlo.mjs → runner-CXA9Fh8h.mjs} +1 -1
  121. package/dist/{runner-p-dMs2UN.mjs → runner-Ol0TNjk6.mjs} +2 -2
  122. package/dist/runtime/ai.d.mts +12 -8
  123. package/dist/runtime/ai.mjs +84 -17
  124. package/dist/runtime/better-auth-mysql.mjs +1 -1
  125. package/dist/runtime/better-auth-pg.mjs +1 -1
  126. package/dist/runtime/better-auth.mjs +1 -1
  127. package/dist/runtime/client-react.mjs +2 -2
  128. package/dist/runtime/client-solid.mjs +2 -2
  129. package/dist/runtime/client-svelte.mjs +2 -2
  130. package/dist/runtime/client-vue.mjs +2 -2
  131. package/dist/runtime/client.mjs +2 -2
  132. package/dist/runtime/durable.d.mts +3 -1
  133. package/dist/runtime/durable.mjs +4 -1
  134. package/dist/runtime/email/testing.mjs +1 -1
  135. package/dist/runtime/env-public.d.mts +1 -1
  136. package/dist/runtime/fetch-stream.mjs +1 -1
  137. package/dist/runtime/fetch.mjs +1 -1
  138. package/dist/runtime/handler.d.mts +1 -1
  139. package/dist/runtime/kv.mjs +0 -1
  140. package/dist/runtime/limits.d.mts +2 -0
  141. package/dist/runtime/limits.mjs +2 -0
  142. package/dist/runtime/live-client.d.mts +1 -1
  143. package/dist/runtime/live-server.mjs +25 -16
  144. package/dist/runtime/live.d.mts +1 -1
  145. package/dist/runtime/migration-handler.mjs +62 -42
  146. package/dist/runtime/route-url.d.mts +4 -0
  147. package/dist/runtime/route-url.mjs +2 -0
  148. package/dist/runtime/routing.d.mts +180 -0
  149. package/dist/runtime/routing.mjs +1082 -0
  150. package/dist/runtime/sandbox-container.d.mts +3 -0
  151. package/dist/runtime/sandbox-container.mjs +2 -0
  152. package/dist/runtime/sandbox.d.mts +4 -32
  153. package/dist/runtime/sandbox.mjs +151 -75
  154. package/dist/runtime/sse.mjs +1 -1
  155. package/dist/runtime/validator.d.mts +1 -1
  156. package/dist/runtime/ws-server.d.mts +4 -2
  157. package/dist/runtime/ws-server.mjs +27 -2
  158. package/dist/runtime/ws.d.mts +2 -2
  159. package/dist/runtime/ws.mjs +8 -6
  160. package/dist/sandbox-XZAqzFlG.d.mts +52 -0
  161. package/dist/sandbox-container-Bo0eiFKz.d.mts +73 -0
  162. package/dist/sandbox-container-C6ItmVuN.mjs +281 -0
  163. package/dist/{scan-4tfN-PSn.mjs → scan-C7okrLyM.mjs} +4 -35
  164. package/dist/{secret-DN9sSNiV.mjs → secret-Dli5fP0B.mjs} +6 -6
  165. package/dist/{skills-O6FUaizK.mjs → skills-D1II1Juz.mjs} +1 -1
  166. package/dist/{sse-BaC1jXko.mjs → sse-CQNaDFFV.mjs} +6 -3
  167. package/dist/{subcommand-prompt-BuGYkAkC.mjs → subcommand-prompt-CY1C4fvl.mjs} +2 -2
  168. package/dist/validate-Dq_L3s0S.mjs +2 -0
  169. package/dist/{validate-CIUwFpjB.mjs → validate-ctOrgiS3.mjs} +2 -1
  170. package/dist/{wrangler-BymcxrRa.mjs → wrangler-7K-bW_DL.mjs} +14 -235
  171. package/dist/{ws-BwcqizuH.d.mts → ws-CL1w7GXU.d.mts} +13 -2
  172. package/package.json +48 -33
  173. package/sandbox.Dockerfile +4 -0
  174. package/schema.json +10 -22
  175. package/skills/migrate-vite-cloudflare-to-void/SKILL.md +34 -157
  176. package/skills/void/SKILL.md +50 -133
  177. package/skills/void/docs/guide/ai.md +94 -84
  178. package/skills/void/docs/guide/app-types.md +3 -32
  179. package/skills/void/docs/guide/auth.md +12 -116
  180. package/skills/void/docs/guide/database/d1.md +9 -54
  181. package/skills/void/docs/guide/database/mysql.md +1 -1
  182. package/skills/void/docs/guide/database/postgresql.md +5 -26
  183. package/skills/void/docs/guide/database.md +23 -75
  184. package/skills/void/docs/guide/deployment.md +27 -113
  185. package/skills/void/docs/guide/durable-state.md +43 -18
  186. package/skills/void/docs/guide/edge/headers.md +3 -47
  187. package/skills/void/docs/guide/edge/prerendering.md +5 -20
  188. package/skills/void/docs/guide/edge/redirects.md +11 -64
  189. package/skills/void/docs/guide/edge/revalidation.md +6 -19
  190. package/skills/void/docs/guide/edge/rewrites.md +56 -284
  191. package/skills/void/docs/guide/edge/static-assets.md +23 -72
  192. package/skills/void/docs/guide/email/domains.md +112 -0
  193. package/skills/void/docs/guide/email/receiving.md +139 -0
  194. package/skills/void/docs/guide/email/sending.md +231 -0
  195. package/skills/void/docs/guide/email.md +13 -619
  196. package/skills/void/docs/guide/env-migration.md +11 -11
  197. package/skills/void/docs/guide/env-vars.md +9 -29
  198. package/skills/void/docs/guide/index.md +0 -15
  199. package/skills/void/docs/guide/jobs.md +3 -18
  200. package/skills/void/docs/guide/kv.md +5 -11
  201. package/skills/void/docs/guide/live.md +5 -56
  202. package/skills/void/docs/guide/pages-routing/actions-and-forms.md +78 -125
  203. package/skills/void/docs/guide/pages-routing/head.md +10 -10
  204. package/skills/void/docs/guide/pages-routing/islands.md +6 -36
  205. package/skills/void/docs/guide/pages-routing/layouts.md +6 -128
  206. package/skills/void/docs/guide/pages-routing/loaders.md +3 -19
  207. package/skills/void/docs/guide/pages-routing/markdown.md +13 -171
  208. package/skills/void/docs/guide/pages-routing/overview.md +7 -17
  209. package/skills/void/docs/guide/pages-routing/view-transitions.md +1 -1
  210. package/skills/void/docs/guide/platform/administration/access.md +1 -4
  211. package/skills/void/docs/guide/platform/administration/email.md +35 -8
  212. package/skills/void/docs/guide/platform/administration/operations.md +26 -4
  213. package/skills/void/docs/guide/platform/administration/plans.md +126 -0
  214. package/skills/void/docs/guide/platform/administration/projects.md +5 -2
  215. package/skills/void/docs/guide/platform/administration/zero-trust.md +189 -0
  216. package/skills/void/docs/guide/platform/development/local.md +2 -2
  217. package/skills/void/docs/guide/platform/development/runtime.md +3 -13
  218. package/skills/void/docs/guide/platform/development/schema-ci.md +0 -58
  219. package/skills/void/docs/guide/platform/installation/credentials.md +6 -4
  220. package/skills/void/docs/guide/platform/installation/domains.md +31 -3
  221. package/skills/void/docs/guide/platform/installation/first-deployment.md +6 -0
  222. package/skills/void/docs/guide/platform/installation/maintenance.md +3 -1
  223. package/skills/void/docs/guide/platform/installation/prerequisites.md +21 -16
  224. package/skills/void/docs/guide/platform/installation/setup.md +9 -5
  225. package/skills/void/docs/guide/platform/installation/uninstall.md +17 -2
  226. package/skills/void/docs/guide/platform-administration.md +2 -0
  227. package/skills/void/docs/guide/queues.md +7 -9
  228. package/skills/void/docs/guide/quickstart.md +38 -37
  229. package/skills/void/docs/guide/remote-dev.md +4 -9
  230. package/skills/void/docs/guide/sandboxes.md +78 -41
  231. package/skills/void/docs/guide/server-routing.md +9 -72
  232. package/skills/void/docs/guide/sse.md +4 -18
  233. package/skills/void/docs/guide/ssg.md +3 -15
  234. package/skills/void/docs/guide/ssr.md +14 -62
  235. package/skills/void/docs/guide/storage.md +9 -4
  236. package/skills/void/docs/guide/type-safety.md +3 -14
  237. package/skills/void/docs/guide/typed-fetch.md +3 -7
  238. package/skills/void/docs/guide/websockets.md +68 -40
  239. package/skills/void/docs/integrations/agents.md +3 -3
  240. package/skills/void/docs/integrations/cloudflare.md +85 -316
  241. package/skills/void/docs/integrations/frameworks/analog.md +5 -64
  242. package/skills/void/docs/integrations/frameworks/astro.md +4 -73
  243. package/skills/void/docs/integrations/frameworks/nuxt.md +5 -62
  244. package/skills/void/docs/integrations/frameworks/overview.md +11 -54
  245. package/skills/void/docs/integrations/frameworks/react-router.md +5 -60
  246. package/skills/void/docs/integrations/frameworks/sveltekit.md +6 -65
  247. package/skills/void/docs/integrations/frameworks/tanstack-start.md +4 -62
  248. package/skills/void/docs/integrations/nodejs-bun-deno.md +5 -69
  249. package/skills/void/docs/reference/api/auth.md +156 -0
  250. package/skills/void/docs/reference/api/client.md +87 -0
  251. package/skills/void/docs/reference/api/database.md +95 -0
  252. package/skills/void/docs/reference/api/durable.md +46 -0
  253. package/skills/void/docs/reference/api/env.md +50 -0
  254. package/skills/void/docs/reference/api/handlers.md +254 -0
  255. package/skills/void/docs/reference/api/pages.md +241 -0
  256. package/skills/void/docs/reference/api/plugin.md +39 -0
  257. package/skills/void/docs/reference/api/resources.md +109 -0
  258. package/skills/void/docs/reference/api/rewrites.md +76 -0
  259. package/skills/void/docs/reference/api/types.md +92 -0
  260. package/skills/void/docs/reference/api.md +56 -1218
  261. package/skills/void/docs/reference/cli/auth.md +88 -0
  262. package/skills/void/docs/reference/cli/database.md +128 -0
  263. package/skills/void/docs/reference/cli/deploy.md +85 -0
  264. package/skills/void/docs/reference/cli/domains.md +41 -0
  265. package/skills/void/docs/reference/cli/email.md +129 -0
  266. package/skills/void/docs/reference/cli/generate.md +116 -0
  267. package/skills/void/docs/reference/cli/github.md +189 -0
  268. package/skills/void/docs/reference/cli/platform-config.md +92 -0
  269. package/skills/void/docs/reference/cli/platform-email.md +81 -0
  270. package/skills/void/docs/reference/cli/platform-installation.md +127 -0
  271. package/skills/void/docs/reference/cli/platform-operations.md +90 -0
  272. package/skills/void/docs/reference/cli/platform-users.md +89 -0
  273. package/skills/void/docs/reference/cli/platform-zero-trust.md +45 -0
  274. package/skills/void/docs/reference/cli/platform.md +70 -0
  275. package/skills/void/docs/reference/cli/project.md +214 -0
  276. package/skills/void/docs/reference/cli/secrets.md +76 -0
  277. package/skills/void/docs/reference/cli/setup.md +70 -0
  278. package/skills/void/docs/reference/cli.md +33 -1621
  279. package/skills/void/docs/reference/config.md +26 -32
  280. package/skills/void/docs/reference/resource-inference.md +3 -58
  281. package/skills/void/docs/reference/structure.md +14 -41
  282. package/dist/canonical-json-DuDiiUsQ.mjs +0 -13
  283. package/dist/cli/cf-compat.mjs +0 -968
  284. package/dist/client-4cDVv7BO.mjs +0 -2
  285. package/dist/gen-Vnv2f65C.mjs +0 -2
  286. package/dist/help-DQMfeKMz.mjs +0 -2
  287. package/dist/login-DFQk7rbW.mjs +0 -2
  288. package/dist/migrate-TsHGBnDA.mjs +0 -2
  289. package/dist/plan-BEZ8VJW0.mjs +0 -256
  290. package/dist/plan-DpuOr14e.mjs +0 -2
  291. package/dist/prepare-BZXkjdNe.mjs +0 -2
  292. package/dist/validate-EKmJWxmy.mjs +0 -2
  293. /package/dist/cli/{cf-compat.d.mts → cloudflare-operation-process.d.mts} +0 -0
@@ -4,355 +4,127 @@ outline: deep
4
4
 
5
5
  # Rewrites
6
6
 
7
- A rewrite serves one route's content at another URL while keeping the browser's address unchanged. For example, `/docs` can serve the content from `/en/docs`.
8
-
9
- Define source patterns and destination paths in `routing.rewrites` in [`void.config.ts`](../../reference/config):
10
-
11
- ```json
12
- {
13
- "routing": {
14
- "rewrites": {
15
- "/": "/en",
16
- "/docs": "/en/docs",
17
- "/docs/*": "/en/docs/:splat"
18
- }
19
- }
20
- }
21
- ```
22
-
23
- ## When to use rewrites
24
-
25
- Use rewrites to decouple the **public URL** from the **internal route**. Common scenarios:
26
-
27
- - **i18n routing** — serve the default locale at unprefixed paths (`/docs` serves `/en/docs`)
28
- - **URL restructuring** — reorganize internal route files without changing public URLs or SEO
29
- - **Vanity URLs** — map `/pricing` to `/marketing/pricing-page` without exposing the internal structure
30
- - **API versioning** — route `/api/users` to `/api/v3/users` internally so consumers use clean, unversioned endpoints
31
- - **Incremental migration** — old URL structure continues working at the edge while route handlers move to new paths
32
- - **Multi-app composition** — serve different internal apps under a unified URL namespace (e.g., `/docs/*` rewrites to a docs app, `/app/*` to the main app)
33
-
34
- If you **do** want the user to see the new URL (e.g., for SEO canonical signals or moving a page permanently), use a [redirect](./redirects) instead.
35
-
36
- ## Rules
7
+ A rewrite serves a route at a different URL without changing the browser's address. For example, `/docs` can serve `/en/docs`. Use a [redirect](./redirects) when the browser should move to the destination instead.
37
8
 
38
- - **Source patterns** start with `/`. `*` matches any characters including `/`.
39
- - **Destinations** are strings starting with `/` (only internal paths are supported).
40
- - `:splat` in the destination is replaced with the portion of the path matched by `*` in the source pattern.
41
- - When multiple rules match, the **first match wins**. Put more-specific rules above more-general ones (matches Netlify `_redirects` and Vercel `vercel.json` semantics).
42
- - On the default target, rewrites are evaluated at the edge **before** the request reaches the worker. On `node` / `bun` / `deno` targets they run in-process as Hono middleware, still before route dispatch. Either way, the rewritten path is then used for static asset serving, ISR, and SSR.
43
-
44
- ## Example: i18n routing
45
-
46
- Define route files only under `[locale]/` and rewrite the default locale to unprefixed paths:
47
-
48
- ```json
49
- {
50
- "routing": {
51
- "rewrites": {
52
- "/": "/en",
53
- "/docs": "/en/docs",
54
- "/docs/*": "/en/docs/:splat"
55
- }
56
- }
57
- }
58
- ```
59
-
60
- A request to `/docs/getting-started` serves the content from `/en/docs/getting-started`, but the browser URL stays at `/docs/getting-started`. Non-default locales like `/zh-CN/docs/getting-started` work as-is because they match the `[locale]/` route directly.
61
-
62
- ## Example: vanity URLs
63
-
64
- Map short marketing URLs to internal route paths:
65
-
66
- ```json
67
- {
68
- "routing": {
69
- "rewrites": {
70
- "/pricing": "/marketing/pricing-page",
71
- "/start": "/onboarding/get-started",
72
- "/jobs": "/company/careers"
73
- }
74
- }
75
- }
76
- ```
9
+ Define rewrites in [`void.config.ts`](../../reference/config):
77
10
 
78
- ## Example: API versioning
79
-
80
- Route unversioned API paths to the current version internally:
11
+ ```ts
12
+ import { defineConfig } from 'void/config';
81
13
 
82
- ```json
83
- {
84
- "routing": {
85
- "rewrites": {
86
- "/api/users": "/api/v3/users",
87
- "/api/users/*": "/api/v3/users/:splat"
88
- }
89
- }
90
- }
14
+ export default defineConfig({
15
+ routing: {
16
+ rewrites: {
17
+ '/': '/en',
18
+ '/docs': '/en/docs',
19
+ '/docs/*': '/en/docs/:splat',
20
+ },
21
+ },
22
+ });
91
23
  ```
92
24
 
93
- When v4 ships, update the rewrite — no client-side changes needed.
25
+ A request to `/docs/getting-started` serves `/en/docs/getting-started`. Other locales, such as `/ja/docs/getting-started`, keep their own routes.
94
26
 
95
- ## Example: path restructuring
96
-
97
- After reorganizing from `/blog/:slug` to `/posts/:slug`, keep the old URLs working:
98
-
99
- ```json
100
- {
101
- "routing": {
102
- "rewrites": {
103
- "/blog/*": "/posts/:splat"
104
- }
105
- }
106
- }
107
- ```
27
+ ## Rules
108
28
 
109
- Users on `/blog/hello-world` see the content from `/posts/hello-world` at the original URL.
29
+ - Sources and destinations start with `/`. Destinations must be paths within the app.
30
+ - `*` matches any characters, including `/`. Use `:splat` in the destination for the matched portion.
31
+ - The first matching rule wins. Put specific patterns before catch-all patterns.
32
+ - Rewrites run before static assets and application routes.
110
33
 
111
34
  ## Programmatic rewrites in middleware
112
35
 
113
- For dynamic rewrite logic — like i18n locale negotiation based on cookies or headers — use `c.rewrite()` in middleware:
36
+ Use `c.rewrite()` when the destination depends on the request, such as a locale chosen from a cookie:
114
37
 
115
38
  ```ts
116
39
  import { defineMiddleware } from 'void';
117
40
 
118
41
  export default defineMiddleware(async (c, next) => {
42
+ if (c.req.path.match(/^\/(en|ja)(\/|$)/)) return next();
43
+
119
44
  const locale = detectLocale(c.req);
120
- if (!c.req.path.match(/^\/(en|zh-CN)\//)) {
121
- return c.rewrite(`/${locale}${c.req.path}`);
122
- }
123
- return next();
45
+ return c.rewrite(`/${locale}${c.req.path}`);
124
46
  });
125
47
  ```
126
48
 
127
- `c.rewrite(path)` re-dispatches the request through the router with the new pathname. You must `return` the result — same shape as `c.redirect()`. A queryless destination preserves the incoming query string; a destination with `?` replaces it, so `c.rewrite('/search')` keeps `?q=...` and `c.rewrite('/search?q=all')` forwards exactly `?q=all`.
128
-
129
- `path` uses the [`RewriteDestination`](../../reference/api#rewritedestination) type. Your editor suggests known route patterns, and you can still pass dynamic strings. The suggestions don't guarantee that a destination exists.
130
-
131
- ### Runtime rewrites cannot reach static assets
132
-
133
- `c.rewrite()` can only re-dispatch to paths the worker itself handles — routes, SSR entries, API handlers. It **cannot** re-dispatch into the static asset handler, because the Void platform serves assets in front of your worker. A call like `c.rewrite('/hero.png')` re-enters the worker's route table, doesn't match anything, and 404s.
134
-
135
- This is enforced at the call site: if the destination's final path segment ends in a known static-asset extension, `c.rewrite()` throws `VoidAssetRewriteError` (exported from `"void"`, catchable by name) before the re-dispatch, with the attempted destination in the message. Query strings and fragments are stripped before matching, so `c.rewrite('/hero.png?v=2')` also throws.
49
+ Return the result of `c.rewrite()`. Middleware runs again at the destination, so skip paths that are already rewritten to avoid a loop. Use `c.isRewritten()` to skip work that should happen only once:
136
50
 
137
- The guarded extensions are:
138
-
139
- ```
140
- .png .jpg .jpeg .gif .webp .avif .svg .ico
141
- .css .js .mjs .cjs
142
- .woff .woff2 .ttf .otf .eot
143
- .mp4 .webm .mp3 .wav
144
- .pdf .txt .xml .json .wasm .map
51
+ ```ts
52
+ if (c.isRewritten()) return next();
145
53
  ```
146
54
 
147
- `.html` is allowed because a path such as `/about.html` can be a route. If it returns `404`, inspect the development `X-Void-Routing` header to see how the request was resolved.
148
-
149
- Static rewrites are different: `_redirects` `200!` entries and `routing.rewrites` run at the platform layer **before** the asset handler, so they _can_ rewrite into assets. If you need "rewrite into an asset" behavior dynamically, model it as a static rule (possibly with a broader source pattern) rather than doing it from middleware.
150
-
151
- After `c.rewrite()`, Void skips static rewrite rules on the second router pass. It tracks the request itself, so a client-supplied header can't bypass this check. Use [`c.originalUrl()`](#original-url-access) to read the URL before the rewrite.
55
+ Keep access checks on any destination that needs them.
152
56
 
153
- Your middleware still runs on each pass. Avoid cycles such as `/a → /b → /c → /a` across middleware: Void can't detect those automatically. Each middleware should skip paths that are already in its intended form.
57
+ A destination without `?` preserves the incoming query string. `c.rewrite('/search')` keeps `?q=...`, while `c.rewrite('/search?q=all')` replaces it.
154
58
 
155
- Also avoid deep rewrite chains for performance: every hop re-runs all middleware from the top, so `/a → /b → /c → /d` costs four router passes.
59
+ Your editor suggests known routes through the [`RewriteDestination`](../../reference/api/rewrites.md#rewritedestination) type. Dynamic strings are also accepted.
156
60
 
157
- ### Performance notes
158
-
159
- - Static `routing.rewrites` and `routing.fallbacks` rules are evaluated in order, first-match-wins, at O(rules) per request. The list is small in practice, but keep it bounded — don't programmatically generate thousands of entries.
160
- - Each `c.rewrite()` hop replays the full middleware stack against a fresh `Request`. A chain of three middleware rewrites with four middleware in the stack is roughly twelve middleware invocations, not four.
161
- - The loop check skips static rules after a rewrite, but it doesn't skip your middleware. Keep middleware rewrite chains short and ensure they terminate.
162
-
163
- ### Side effects in re-dispatched middleware
164
-
165
- Every rewrite runs middleware again. Database lookups and auth checks repeat, and counters or loggers may record the same request more than once.
166
-
167
- For work that should happen only before a rewrite, check `c.isRewritten()`. Keep access checks wherever the destination needs them:
168
-
169
- ```ts
170
- if (c.isRewritten()) return next();
171
- ```
172
-
173
- `c.isRewritten()` returns `true` after either a static edge rewrite or `c.rewrite()` in middleware. Void records this on the request after accepting the edge's rewrite metadata.
61
+ ### Runtime rewrites cannot reach static assets
174
62
 
175
- ::: tip
176
- This is the recommended approach for i18n libraries. The library can export a middleware factory that handles locale detection and rewriting, and users just drop it into their `middleware/` directory.
177
- :::
63
+ `c.rewrite()` targets application routes. To serve an asset such as `/hero.png` at another URL, use `routing.rewrites` or a `_redirects` rule instead. A middleware rewrite to a recognized asset extension throws `VoidAssetRewriteError`.
178
64
 
179
65
  ## Original URL access
180
66
 
181
- When a request has been rewritten — either by a static rule at the edge or by `c.rewrite()` in middleware — `c.originalUrl()` returns the URL the user originally requested. This is useful for canonical links, locale detection, and building correct hrefs:
67
+ `c.originalUrl()` returns the URL requested before a static or middleware rewrite, or `null` when no rewrite occurred. Use it for canonical links or locale detection:
182
68
 
183
69
  ```ts
70
+ import { defineHandler } from 'void';
71
+
184
72
  export default defineHandler((c) => {
185
73
  const original = c.originalUrl();
186
- // original is a `URL` instance for the full URL the user requested
187
- // before the rewrite, or null if the request was not rewritten.
74
+ return c.json({ pathname: original?.pathname ?? c.req.path });
188
75
  });
189
76
  ```
190
77
 
191
- On managed Void deployments, the edge passes the original URL to the Worker as trusted request metadata. On direct Cloudflare deployments, the generated Worker records that metadata when it applies the rewrite itself. Further middleware rewrites update the same metadata without requiring you to parse headers.
192
-
193
78
  ## Fallbacks
194
79
 
195
- `routing.fallbacks` shares the same shape as `rewrites` but runs **only when no static asset or route matched** — i.e. the request would otherwise return a 404. This lets you add catch-all rewrites without preempting real routes.
196
-
197
- Void only treats generated no-route 404s as fallback-eligible, whether the check runs in managed dispatch or in a native Cloudflare Worker. A route handler or API endpoint that intentionally returns `404` is returned as-is, so catch-all fallbacks do not turn missing API resources into HTML. Third-party framework deployments do not expose Void's no-route marker, so their fallback rules still apply after the framework worker returns `404`.
198
-
199
- ```json
200
- {
201
- "routing": {
202
- "fallbacks": {
203
- "/*": "/index.html"
204
- }
205
- }
206
- }
207
- ```
208
-
209
- Common uses:
210
-
211
- - **SPA shell** — serve `/index.html` for any unmatched path so client-side routing can take over (for app types that don't already do this automatically).
212
- - **Default-locale catch-all** — send unmatched paths to `/en/:splat` without stealing requests that already resolve to an existing page under `/zh-CN/…`, `/ja/…`, etc.
213
-
214
- Ordering:
215
-
216
- - `rewrites` are evaluated **before** the static asset lookup; a matching rule always wins.
217
- - `fallbacks` are evaluated **after** the static asset lookup, only when it would 404.
218
-
219
- Use `rewrites` when you want to force a path mapping regardless of what exists; use `fallbacks` when the rule should only kick in as a safety net.
220
-
221
- ### SPA app type + `routing.fallbacks`
222
-
223
- For the `spa` app type, the platform already serves `/index.html` for any asset miss by default (`not_found_handling: 'single-page-application'`). Adding `routing.fallbacks` to a SPA app is **additive, not an override**:
224
-
225
- 1. Your `routing.fallbacks` rules are checked first, in the order they appear (first match wins among user rules).
226
- 2. If none of them match, the implicit `/* → /index.html` SPA fallback still fires.
227
-
228
- So a SPA app can carve out specific paths without losing the SPA shell behavior for everything else:
229
-
230
- ```json
231
- {
232
- "routing": {
233
- "fallbacks": {
234
- "/docs/*": "/docs.html"
235
- }
236
- }
237
- }
238
- ```
239
-
240
- With this config, an asset miss under `/docs/getting-started` resolves to `/docs.html`, while an asset miss under `/app/settings` still resolves to `/index.html` (the SPA default).
241
-
242
- You don't need to write `"/*": "/index.html"` yourself — the CLI **appends** a synthetic `{ source: '/*', destination: '/index.html' }` rule to the fallback list when packaging a SPA deploy that has user fallbacks. Because evaluation is first-match-wins, user rules come before the synthetic entry and take precedence; the synthetic rule only fires when no user rule matched. This is why the shipped manifest may contain more fallback rules than you wrote in `void.config.ts`. If you do write `"/*": "/index.html"` yourself, the CLI emits a warning on `void deploy` noting that the rule duplicates the default and can be omitted.
243
-
244
- ## `_redirects` file
245
-
246
- Rewrites can also be defined in a `_redirects` file placed in Vite's `publicDir` (defaults to `public/`). Void mirrors Netlify-compat semantics for the `200` status code:
247
-
248
- ```text
249
- # plain 200 = fallback (asset-miss only, equivalent to routing.fallbacks)
250
- /* /index.html 200
251
-
252
- # 200! with force suffix = always rewrite (equivalent to routing.rewrites)
253
- /docs/* /en/docs/:splat 200!
254
- ```
255
-
256
- | File-based form | `void.config.ts` equivalent | Behavior |
257
- | --------------- | --------------------------- | ------------------------------------------------------------------------ |
258
- | `... 200` | `routing.fallbacks` | Fires only when no static asset and no route matched (would have 404'd). |
259
- | `... 200!` | `routing.rewrites` | Always fires, overriding any static asset that would have served. |
260
-
261
- - `void.config.ts` rules are applied **before** file-based rules. Since the first match wins, `routing.rewrites` / `routing.fallbacks` in `void.config.ts` take precedence.
262
- - The `_redirects` file can mix 3xx redirects, `200` fallbacks, and `200!` force rewrites. Ordering is preserved within each bucket.
263
- - The `!` force suffix is only meaningful on `200`. On a 3xx entry like `301!`, the `!` is silently stripped — 3xx redirects always "force" by their nature (they change the URL), so the suffix is meaningless. `void deploy` prints a single aggregated warning tallying all `301!` / `302!` / `307!` / `308!` entries so you can clean them up.
264
-
265
- ## Precedence: `_redirects` vs `void.config.ts`
266
-
267
- When the same source pattern appears in both a `_redirects` file and `void.config.ts` (`routing.redirects` / `routing.rewrites` / `routing.fallbacks`), the rules don't replace each other — they **merge into a single ordered list per phase**, and the first match wins.
268
-
269
- Rules are bucketed by phase before merging:
270
-
271
- - **Pre-asset phase** (always fires, runs before static asset lookup): `routing.redirects` + `routing.rewrites` + `_redirects` 3xx entries + `_redirects` `200!` entries.
272
- - **Post-asset phase** (only fires on an asset miss): `routing.fallbacks` + `_redirects` plain `200` entries. For SPA app types, the synthetic `/* → /index.html` rule is **appended last** in this phase, so user fallbacks evaluated earlier take precedence under first-match-wins.
273
-
274
- Within each phase, `void.config.ts` rules run first, followed by `_redirects` rules. The first matching rule wins, so a `void.config.ts` rule takes precedence over the same source pattern in `_redirects`.
275
-
276
- ### Concrete example
277
-
278
- ```text
279
- # _redirects
280
- /docs/* /en/docs/:splat 200!
281
- ```
80
+ `routing.fallbacks` uses the same patterns as rewrites, but applies only when no asset or route matches:
282
81
 
283
82
  ```ts
284
83
  import { defineConfig } from 'void/config';
285
84
 
286
85
  export default defineConfig({
287
86
  routing: {
288
- rewrites: {
289
- '/docs/*': '/handbook/:splat',
290
- },
87
+ fallbacks: { '/*': '/index.html' },
291
88
  },
292
89
  });
293
90
  ```
294
91
 
295
- A request to `/docs/intro` matches both rules. Merged order is `[void.config.ts: /docs/* → /handbook/:splat, _redirects: /docs/* → /en/docs/:splat]`, so `void.config.ts` wins and the request resolves to `/handbook/intro`.
296
-
297
- To confirm precedence in practice, check the [`X-Void-Routing` dev header](#debugging-with-x-void-routing) on any response during `vite dev` — it names the winning rule and its origin (`_redirects:<line>` vs `void.config.ts#routing.rewrites`).
298
-
299
- ## How rewrites work
92
+ Use a fallback for a client-side router or a default-locale catch-all. An intentional `404` from a Void route remains a `404`. For third-party frameworks, fallbacks can also replace the framework's `404` response.
300
93
 
301
- **Static rewrites** (`void.config.ts` and `_redirects` file) on managed Void deployments:
94
+ SPA apps already fall back to `/index.html`. Custom fallback rules run first; unmatched paths still use the SPA shell. You don't need to add `'/*': '/index.html'` yourself.
302
95
 
303
- 1. `void deploy` reads rewrite rules from the `_redirects` file (status `200` entries) and `routing.rewrites` in `void.config.ts`, then includes them in the deploy manifest alongside redirect rules.
304
- 2. The platform stores the rules in the KV routing entry for your project.
305
- 3. The dispatch worker evaluates all routing rules (redirects and rewrites) before any worker invocation. If a rewrite matches, the request pathname is updated internally and the request continues through the normal pipeline (static assets, ISR, worker). The original URL is passed as `X-Void-Original-URL`.
306
-
307
- On direct Cloudflare deployments of native Void apps, Vite compiles the same merged redirects, rewrites, headers, and fallbacks into the generated Worker. They run there without managed dispatch, and rewrite metadata remains internal to the Worker.
308
-
309
- **Middleware rewrites** (`c.rewrite()`):
96
+ ## `_redirects` file
310
97
 
311
- 1. The request reaches the worker with its original (or edge-rewritten) pathname.
312
- 2. Your middleware calls `c.rewrite(newPath)`, which constructs a new request with the rewritten pathname and re-dispatches it through the Hono router.
313
- 3. The re-dispatched request runs through all middleware and route handlers as if it were a fresh request to the new path.
98
+ You can also place rules in Vite's `publicDir`, which defaults to `public/`:
314
99
 
315
- Static rewrites run before application routes: in dispatch for managed deployments and in generated middleware for direct Cloudflare deployments. Middleware rewrites repeat routing inside the Worker, which lets them use request-specific logic.
100
+ ```text
101
+ # Fallback: only when no asset or route matches
102
+ /* /index.html 200
316
103
 
317
- ## Caveat: client navigation skips rewrites
104
+ # Rewrite: before assets and routes
105
+ /docs/* /en/docs/:splat 200!
106
+ ```
318
107
 
319
- Rewrites run on the server. A full HTTP request to `/docs` resolves through `routing.rewrites` and serves `/en/docs` content. But a client-side `<Link to="/docs">` navigation in Pages mode fetches loader data directly for `/docs` — the Void Router doesn't know about the server's rewrite table, so there's no lookup against `/en/docs` on that path.
108
+ The file can include [3xx redirects](./redirects) too. Rules in `void.config.ts` take precedence over file rules; within each group, the first match wins.
320
109
 
321
- In practice this only matters when the source and destination have **different loader behavior**. If `/docs` has no route handler but `/en/docs` does, clicking a `<Link to="/docs">` will fail where a fresh page load would succeed. The first render (server) and a subsequent client nav (CSR) to the same URL can diverge.
110
+ ## Client navigation
322
111
 
323
- Two mitigations:
112
+ Rewrites run on the server. In Pages mode, a client-side `<Link to="/docs">` navigation may fetch loader data for `/docs` rather than the rewritten route `/en/docs`.
324
113
 
325
- - Use a plain `<a href="/docs">` when you need the navigation to round-trip through the server (and therefore through rewrites).
326
- - If the URL change is meant to be authoritative, use a [redirect](./redirects) instead — the Void Router follows redirects via HTTP, so behavior is consistent.
114
+ Use `<a href="/docs">` to make a full server request when the destination has a different loader. Use a redirect if the URL should change.
327
115
 
328
116
  ## ISR cache keys with rewrites
329
117
 
330
- If you use [`routing.revalidate`](./revalidation) on a dispatch rewrite (`routing.rewrites`, `routing.fallbacks`, or `_redirects` 200/200!), the cache slot is keyed on the **rewritten** pathname plus the original request URL's pathname. By default, query parameters are dropped from the rewrite variant key to avoid unbounded cache fanout; add `routing.revalidateQueryAllowlist` when selected query params should vary cached output. So a direct request to `/en/docs/foo` and a rewrite from `/docs/foo → /en/docs/foo` cache independently — useful when your worker reads `c.isRewritten()` or `c.originalUrl()`. Middleware `c.rewrite()` runs after ISR lookup, so it does not create a separate ISR variant.
118
+ Static rewrites cache the destination separately for each original pathname. Query parameters vary the cache only when included in `routing.revalidateQueryAllowlist`. Middleware rewrites don't create a separate cache variant.
331
119
 
332
- `revalidate({ paths })` operates on the rewritten pathname (the slot's primary key). Purging `/en/docs/foo` removes all variants — direct + every rewrite source — under that path. Purging the source path (`/docs/foo`) invalidates nothing, because no slot is written under the source.
120
+ Purge the destination with `revalidate({ paths: ['/en/docs/foo'] })` to clear direct and rewritten requests. Purging only `/docs/foo` does not clear that entry. See [Revalidation](./revalidation).
333
121
 
334
122
  ## Debugging with `X-Void-Routing`
335
123
 
336
- During `vite dev`, every response carries an `X-Void-Routing` header that traces how the request was resolved. Open the Network tab in devtools and inspect the response headers:
124
+ During development, inspect the `X-Void-Routing` response header in your browser's Network tab. It shows the matching rule and where it was declared:
337
125
 
338
- ```
339
- X-Void-Routing: redirect[/old] -> /new 301 (_redirects:12)
340
- X-Void-Routing: rewrite[/api/*] -> /backend/:splat (void.config.ts#routing.rewrites)
341
- X-Void-Routing: fallback[/docs/*] -> /docs.html (void.config.ts#routing.fallbacks)
126
+ ```text
127
+ X-Void-Routing: rewrite[/docs/*] -> /en/docs/:splat (void.config.ts#routing.rewrites)
342
128
  X-Void-Routing: c.rewrite -> /new-path (middleware)
343
129
  X-Void-Routing: pass-through
344
130
  ```
345
-
346
- Phases are separated by `->` so the diagnostic value stays valid as an HTTP header. The parenthesised source hint points at the exact declaration — a line number for `_redirects`, a config path for `void.config.ts`, or `spa-default` for the synthetic SPA catch-all. The header is **only emitted in dev** — production builds strip both the trace code and the per-rule `origin` metadata from the bundle and manifest.
347
-
348
- ::: info What fires in `vite dev`
349
- `vite dev` applies the full static routing pipeline on every target — `node`, `bun`, `deno`, and the default target alike. `void.config.ts` rules (`routing.redirects` / `routing.rewrites` / `routing.fallbacks` / `routing.headers`) and file-based rules (`public/_redirects`, `public/_headers`) are merged at plugin load and compiled into the Hono middleware your worker runs behind. Editing `_redirects` or `_headers` during a dev session re-runs the merge and reloads the page — no restart needed. `c.rewrite()` calls in middleware work everywhere because they live inside the worker itself, and the `X-Void-Routing` dev header reports every decision on every target.
350
-
351
- A few things still only run in the deployed runtime, not `vite dev`:
352
-
353
- - [ISR caching](./revalidation) (`routing.revalidate`) — served cold in dev, no cached slot warm-ups.
354
- - Custom-domain rewriting and per-project asset prefixes — dev always runs against the root.
355
- - AI Gateway metering for `void/ai` calls — dev hits the provider directly.
356
-
357
- For everything else, the rule that fires in `vite dev` is the rule that will fire after `void deploy`.
358
- :::
@@ -14,7 +14,7 @@ Files in Vite's `build.assetsDir` (default `assets/`) are produced with content
14
14
  Cache-Control: public, max-age=31536000, immutable
15
15
  ```
16
16
 
17
- Cached at the edge for up to one year. Browsers cache them indefinitely. Because the cache key is unversioned, hashed assets survive across deploys without re-fetching.
17
+ Browsers and the edge can cache these files for one year and reuse them across deploys.
18
18
 
19
19
  If your Vite config customizes `build.assetsDir`, Void automatically detects this and applies the immutable optimization to the configured directory:
20
20
 
@@ -29,17 +29,23 @@ export default defineConfig({
29
29
 
30
30
  If `build.assetsDir` is set to `""`, meaning hashed files live at the root, the optimization is skipped because there is no directory-based way to distinguish hashed from non-hashed files.
31
31
 
32
- Void also includes presets for where supported meta frameworks (Astro, Nuxt, SvelteKit, etc.) place their hashed assets, so framework-generated assets enjoy optimal caching out of the box.
32
+ Supported meta-frameworks use their own asset directories automatically.
33
+
34
+ ### Native Cloudflare deployments
35
+
36
+ With `void deploy --platform cloudflare`, generated JavaScript bundles with content fingerprints receive immutable caching. Files copied from `public/` and custom build outputs with stable filenames keep normal revalidation, even when they live in the assets directory. CSS and other assets keep Cloudflare's default or your configured `Cache-Control`.
37
+
38
+ Use [Custom Headers](./headers) to choose a cache policy for other files. Apply immutable caching only to URLs that change whenever their content changes.
33
39
 
34
40
  ## Non-hashed assets
35
41
 
36
- Everything else such as `index.html`, `favicon.ico`, and `/about` is edge-cached using deploy-versioned cache keys. On each deploy, the version changes and previous cache entries are invalidated automatically, so there is nothing to purge.
42
+ Other static files, such as `index.html` and `favicon.ico`, are cached until the next deploy. You do not need to purge them manually.
37
43
 
38
44
  ```
39
45
  Cache-Control: public, s-maxage=31536000, max-age=0, must-revalidate
40
46
  ```
41
47
 
42
- Cached at the edge until the next deploy. Browsers always revalidate on the next request.
48
+ Browsers revalidate these files on each request.
43
49
 
44
50
  **What gets cached:**
45
51
 
@@ -51,6 +57,7 @@ Cached at the edge until the next deploy. Browsers always revalidate on the next
51
57
  - `/api/*` routes, which always hit the worker
52
58
  - SSR-rendered pages (paths without file extensions in SSR projects)
53
59
  - Non-GET requests
60
+ - Requests carrying `Cookie`, `Authorization`, or `Cf-Access-Jwt-Assertion` credentials
54
61
  - Responses other than a complete `200`
55
62
 
56
63
  ### Opting out
@@ -59,86 +66,30 @@ If your worker serves dynamic content at a URL that looks static (e.g., a dynami
59
66
 
60
67
  ## ETags and 304 Not Modified
61
68
 
62
- All static asset responses include an `ETag` header derived from the file's content hash in R2. When a browser revalidates a cached resource, it sends `If-None-Match` with the previous ETag. If the file has not changed, the edge returns **304 Not Modified** with no body. That saves bandwidth and speeds up page loads.
63
-
64
- This happens automatically for all static assets. No configuration is needed.
69
+ Static assets include an `ETag` header. When a browser revalidates an unchanged file, Void returns `304 Not Modified` without downloading it again. No configuration is needed.
65
70
 
66
71
  ## Custom headers
67
72
 
68
73
  You can override caching headers or add your own for any static asset path using [Custom Headers](./headers).
69
74
 
70
- ## Request pipeline
71
-
72
- Static assets can run in front of the worker, behind the worker, or without any worker at all. Void chooses the pipeline from the app shape so static pages stay static unless application code must inspect document navigations.
73
-
74
- ### Deploy shapes
75
-
76
- | Shape | Worker deployed | First handler for assets | First handler for document navigations | Miss behavior |
77
- | ---------------------------------------------------------------------------------- | --------------- | ------------------------ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
78
- | `inference.appType: "static"` | No | Asset platform | Asset platform | Platform 404 page. |
79
- | Static SPA deploy | No | Asset platform | Asset platform | Platform serves `/index.html` for unmatched navigations. If user `routing.fallbacks` exist, Void ships fallback rules. |
80
- | Void app with only `/api` routes or managed auth | Yes | Worker first for `/api` | Asset platform | Static navigations keep the platform SPA fallback; API requests, including document navigations, reach the worker. |
81
- | Void app with `middleware/`, non-`/api` routes, document WebSockets, live bindings | Yes | Worker first | Worker first | Asset misses stay 404, then the worker serves `/index.html` for HTML requests after routes and middleware run. |
82
- | Pages, SSR, and framework apps | Yes | Worker first | Worker first | Asset misses stay 404. Pages, SSR, or framework rendering owns HTML responses, including intentional HTML 404s. |
83
-
84
- ### Worker-first Void apps
85
-
86
- For worker-owned HTML, Void sets Cloudflare assets to `not_found_handling: "none"` and configures `run_worker_first`. The request order is:
87
-
88
- 1. Platform routing rules that always run before assets, such as redirects and forced rewrites.
89
- 2. Worker route table, middleware, auth, WebSocket upgrades, Pages, or SSR.
90
- 3. `env.ASSETS.fetch()` from inside the worker for static files.
91
- 4. For non-Pages, non-SSR Void apps only, a worker-side SPA fallback to `/index.html` when the original request accepts HTML.
92
- 5. The worker's original 404.
93
-
94
- This is the path needed for preview auth and other middleware. Cloudflare's platform SPA fallback can serve `index.html` directly for browser navigations; when that happens, middleware never sees the request. Worker-owned HTML avoids that by moving fallback HTML behind middleware.
95
-
96
- ### Asset-first Void apps
97
-
98
- For Void apps with only `/api` routes, Void keeps the platform SPA fallback and scopes `run_worker_first` to `/api` and `/api/*`. Static assets and non-API SPA navigations stay on the asset platform. API requests, including browser document navigations such as OAuth callbacks, reach the worker instead of being rewritten to `index.html`.
75
+ ## Navigation and middleware
99
76
 
100
- ### Unmatched requests
77
+ Void serves static files directly unless application code needs to handle the request first. API requests reach your Worker. Apps with middleware, routes outside `/api`, Pages, or SSR run application code before serving fallback HTML.
101
78
 
102
- `not_found_handling` decides what the asset layer does with a request that matched no asset and no worker route. Void infers it:
79
+ SPAs serve `index.html` for unmatched HTML navigation so client-side routing works. For a static site with a `404.html` page, set [`routing.notFound`](../../reference/config.md#routing-notfound):
103
80
 
104
- | App shape | Inferred value | Result for an unknown URL |
105
- | ------------------------------------------------- | -------------------------------- | -------------------------------- |
106
- | Pages or SSR | `none` | The worker's own 404 |
107
- | Worker owns HTML, no `pages/`, no SSR entry | `none` + worker fallback | `index.html` with status **200** |
108
- | Asset-first (only `/api` routes, or none) | `single-page-application` | `index.html` with status **200** |
109
- | Framework deploy (SvelteKit, Nuxt, Analog, Astro) | `none` — pinned, not overridable | The framework worker's own 404 |
110
-
111
- Apps with middleware, a route outside `/api`, document WebSockets, or Live send requests through the Worker first. If they have no Pages or SSR entry, the Worker can then serve `index.html` for HTML navigation. Middleware and auth run before that fallback.
112
-
113
- A SPA needs `index.html` for deep links so its client router can load. A generated static site usually needs a real `404.html` instead. Void can't distinguish the two from built files alone. Set [`routing.notFound`](../../reference/config.md#routing-notfound) for the behavior you want:
81
+ ```ts
82
+ import { defineConfig } from 'void/config';
114
83
 
115
- ```json
116
- { "routing": { "notFound": "404-page" } }
84
+ export default defineConfig({
85
+ routing: { notFound: '404-page' },
86
+ });
117
87
  ```
118
88
 
119
- Choose `"single-page-application"`, `"404-page"`, or `"none"`. This leaves `run_worker_first` unchanged, so the same requests still reach your middleware and API handlers.
120
-
121
- Choosing anything other than `"single-page-application"` disables the Worker's `index.html` fallback. With `"404-page"`, unmatched HTML navigation uses the asset layer's nearest `404.html`. Intentional API `404` responses keep their body, status, and headers. If no `404.html` exists, the Worker's original `404` is kept.
122
-
123
- SvelteKit, Nuxt, Analog, and Astro manage their own not-found behavior. Void ignores `routing.notFound` for those deploys and prints a warning. Their prerendered files are served first, and the framework handles unmatched routes without a platform SPA fallback replacing its error page.
124
-
125
- TanStack Start, React Router, and vinext follow the rows above on a managed `void deploy` — that path resolves the asset config itself and applies it to the uploaded Worker. Void writes no `assets` policy into their generated Worker config:
126
-
127
- | Framework | Generated worker config |
128
- | -------------- | ---------------------------- |
129
- | TanStack Start | `dist/server/wrangler.json` |
130
- | React Router | `build/server/wrangler.json` |
131
- | vinext (App) | `dist/server/wrangler.json` |
132
- | vinext (Pages) | `dist/ssr/wrangler.json` |
133
-
134
- For direct Cloudflare deployment, these frameworks need a complete `assets` policy in their own config: `binding`, `directory`, `not_found_handling`, and `run_worker_first`. Void preserves that policy. Without one, Cloudflare's default applies. The build warns when `routing.notFound` is set so you know to check the framework's asset configuration.
135
-
136
- ### Generated config
137
-
138
- Void owns the generated asset routing policy during dev and build for Void apps. If `cloudflare.assets` in `void.config.ts` contains stale `not_found_handling` or `run_worker_first` values, Void replaces those fields so generated config cannot accidentally change which layer sees a request first.
89
+ Choose `single-page-application`, `404-page`, or `none`. These settings preserve which requests reach middleware and API handlers. Intentional API `404` responses keep their status and body.
139
90
 
140
- TanStack Start and React Router are the exception: Void generates no asset policy for them and leaves both fields to your own Cloudflare config. Writing `not_found_handling` alone would make the asset layer answer unmatched requests and the framework Worker would never run, and completing the policy needs `assets.binding` and `assets.directory` that the framework owns, not Void.
91
+ SvelteKit, Nuxt, Analog, and Astro handle their own error pages and ignore `routing.notFound`. For direct Cloudflare deployment with TanStack Start, React Router, or vinext, configure the asset binding, directory, and routing policy through the framework's Cloudflare config.
141
92
 
142
93
  ## API routes and SSR pages
143
94
 
144
- API responses (`/api/*`) and SSR-rendered pages without file extensions always hit the worker. They are **not** edge-cached by the dispatch layer.
95
+ API responses and SSR pages are not cached as static assets. Use [Revalidation](./revalidation) to cache public rendered pages.