void 0.20.3 → 0.21.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 (294) hide show
  1. package/README.md +2 -2
  2. package/dist/agents-gni4eqBu.mjs +111 -0
  3. package/dist/auth-3sGB0zJ1.mjs +22 -0
  4. package/dist/{auth-DPl6kck4.mjs → auth-B9_D6ygs.mjs} +6 -241
  5. package/dist/auth-CAw7zHqj.mjs +2 -0
  6. package/dist/auth-client-BWBT8HLp.mjs +6 -0
  7. package/dist/auth-client-Bawdj38n.d.mts +7 -0
  8. package/dist/auth-client-react-7GFffu8R.d.mts +7 -0
  9. package/dist/auth-client-react-CMLwT2xI.mjs +6 -0
  10. package/dist/auth-client-solid-DyTFL4cq.d.mts +7 -0
  11. package/dist/auth-client-solid-UoreJWZG.mjs +6 -0
  12. package/dist/auth-client-svelte-Cv_WvrRk.mjs +6 -0
  13. package/dist/auth-client-svelte-zetW0KIH.d.mts +7 -0
  14. package/dist/auth-client-vue-CFk7Xbv3.mjs +6 -0
  15. package/dist/auth-client-vue-bChShbQP.d.mts +7 -0
  16. package/dist/{auth-cmd-CzwquNiP.mjs → auth-cmd-MkBG2u1f.mjs} +5 -5
  17. package/dist/{auth-link-ElDTgF7j.mjs → auth-link-Devmv96E.mjs} +5 -5
  18. package/dist/{better-auth-shared-DSCeohOK.d.mts → better-auth-shared-BoVwA5Vm.d.mts} +1 -6
  19. package/dist/{better-auth-shared-CYw1T3k4.mjs → better-auth-shared-syGYYmnY.mjs} +1 -1
  20. package/dist/{build-cmd-BpJe6boP.mjs → build-cmd-DsBGwtfs.mjs} +6 -4
  21. package/dist/{cache-D98YTqeE.mjs → cache-BMw8eMyF.mjs} +6 -4
  22. package/dist/{cancel-deploy-CPbEQLMG.mjs → cancel-deploy-B3_s9NIN.mjs} +5 -3
  23. package/dist/cf-access-rAZxzMkL.mjs +181 -0
  24. package/dist/cf-build-output-CTdlo6Rt.mjs +520 -0
  25. package/dist/cli/cf-compat.d.mts +1 -0
  26. package/dist/cli/cf-compat.mjs +934 -0
  27. package/dist/cli/cli.mjs +60 -38
  28. package/dist/cli/env-schema-probe.mjs +3 -3
  29. package/dist/client-DAAivdid.mjs +2 -0
  30. package/dist/{client-BQBrZoCX.mjs → client-PdAJ-F0t.mjs} +6 -12
  31. package/dist/{cloudflare-auth-6M5llVPC.mjs → cloudflare-auth-BCmTc1X_.mjs} +13 -44
  32. package/dist/{cloudflare-cmd-4RPGN3KB.mjs → cloudflare-cmd-D6PrKn7o.mjs} +4 -7
  33. package/dist/{cloudflare-connect-t1UU5svD.mjs → cloudflare-connect-DloREDlc.mjs} +6 -6
  34. package/dist/cloudflare-operations-BHNJVDbN.mjs +2 -0
  35. package/dist/{cloudflare-operations-BzWnlC1_.mjs → cloudflare-operations-CPEdHYhM.mjs} +37 -39
  36. package/dist/cloudflare-user-output-Q-k0QoNQ.mjs +20 -0
  37. package/dist/collect-DAUItMDS.mjs +2 -0
  38. package/dist/collect-DXHNWHcT.mjs +48 -0
  39. package/dist/config--T87TD8T.mjs +2 -0
  40. package/dist/{config-NOG_U1aK.mjs → config-BSe70f4T.mjs} +4 -6
  41. package/dist/config-DDIFxQYx.mjs +2 -0
  42. package/dist/{config-uNGuFsI2.mjs → config-Dxr6cTXn.mjs} +22 -37
  43. package/dist/config-DywxBLQC.d.mts +185 -0
  44. package/dist/config-entry.d.mts +6 -0
  45. package/dist/config-entry.mjs +7 -0
  46. package/dist/config-uP7ZDtVZ.mjs +21 -0
  47. package/dist/config-write-y3CBI_ux.mjs +60 -0
  48. package/dist/{connect-WCQZ_u3m.mjs → connect-BvC9kolB.mjs} +8 -6
  49. package/dist/{create-project-D0oXA090.mjs → create-project-C9lQhRzj.mjs} +8 -23
  50. package/dist/create-project-CI-17RVJ.mjs +2 -0
  51. package/dist/database-provider-Cx525bwX.mjs +6 -0
  52. package/dist/database-provider.mjs +1 -5
  53. package/dist/{db-DJ-9qs3S.mjs → db-R7IQgOv5.mjs} +48 -44
  54. package/dist/{delete-BZ4-WaGm.mjs → delete-CghI_NXn.mjs} +6 -4
  55. package/dist/deploy-CYPymbtG.mjs +2 -0
  56. package/dist/{deploy-BAhhcg5q.mjs → deploy-H968Lo4T.mjs} +751 -190
  57. package/dist/discover-BBzDZe_o.mjs +2 -0
  58. package/dist/{discover-xvfrgJeo.mjs → discover-C4O6YxVS.mjs} +3 -8
  59. package/dist/{dist-BrsS7cai.mjs → dist-4WkAWhWx.mjs} +1 -15
  60. package/dist/{dist-m40_XgNh.mjs → dist-Bn8Kodjp.mjs} +1 -1
  61. package/dist/dist-C5fND3R0.mjs +2 -0
  62. package/dist/dist-D7-nEOXi.mjs +2 -0
  63. package/dist/{output-B0cfNSx5.mjs → dist-Dn6nn2IU.mjs} +3 -926
  64. package/dist/{domain-BxAyhxXN.mjs → domain-CITt8lC-.mjs} +7 -5
  65. package/dist/{route-types-Da-DpyUp.mjs → drizzle-Beb2Am5S.mjs} +1 -280
  66. package/dist/{email-Ce6SQq-i.mjs → email-C5kaZXzJ.mjs} +2 -2
  67. package/dist/{email-Bj7Cvdwp.mjs → email-_8VmyX7V.mjs} +14 -12
  68. package/dist/{entry-DU3oDoQ3.mjs → entry-DdRFGK0y.mjs} +2 -2
  69. package/dist/{env-DP_EErve.mjs → env-DV4r3nHz.mjs} +9 -7
  70. package/dist/{env-DBKmK4vc.mjs → env-DX_v-Q-v.mjs} +1 -1
  71. package/dist/env-Yz4HcvHs.mjs +78 -0
  72. package/dist/env-helpers--wFmQ_5Q.mjs +136 -0
  73. package/dist/{env-types-BNPhro-M.mjs → env-types-CWDtqHgw.mjs} +6 -2
  74. package/dist/{env-validation-CF6KvTRf.mjs → env-validation-BsFEXps5.mjs} +19 -28
  75. package/dist/env-validation-DIDGM7h4.mjs +2 -0
  76. package/dist/fetch-CXDChK7B.mjs +18 -0
  77. package/dist/fetch-_SeGZao9.d.mts +57 -0
  78. package/dist/fetch-stream-AOByI7Ki.mjs +81 -0
  79. package/dist/fetch-stream-Bjf0hoZb.d.mts +49 -0
  80. package/dist/gen-BBiIZw6g.mjs +2 -0
  81. package/dist/{gen-B_wPnVTK.mjs → gen-CFOEEc-t.mjs} +13 -11
  82. package/dist/{generate-RTK8_kK1.mjs → generate-C0VY6RVf.mjs} +2 -2
  83. package/dist/{github-cmd-C-z_xRrQ.mjs → github-cmd-jYjha2LO.mjs} +6 -4
  84. package/dist/{handler-D1hLsObx.d.mts → handler-BXJTXd02.d.mts} +6 -1
  85. package/dist/handler-DghKr6dU.mjs +150 -0
  86. package/dist/head-D_QRR5Yd.mjs +112 -0
  87. package/dist/head-client-DzmJGN4C.mjs +90 -0
  88. package/dist/{headers-BAHwgHdW.mjs → headers-B_HBMgi0.mjs} +2 -2
  89. package/dist/{help-CwOX-zmI.mjs → help-C46mnlUS.mjs} +17 -12
  90. package/dist/help-CS_nAsWu.mjs +2 -0
  91. package/dist/index.d.mts +2 -20
  92. package/dist/index.mjs +116 -60
  93. package/dist/{init-BGktCXgA.mjs → init-CSXmvxKu.mjs} +49 -50
  94. package/dist/{link-D2kbqhWb.mjs → link-DxMOALXk.mjs} +7 -5
  95. package/dist/{list-CvkK_G7k.mjs → list-0wQs0oYg.mjs} +7 -5
  96. package/dist/live-CB1y5IuC.mjs +411 -0
  97. package/dist/live-CKiJilLr.d.mts +105 -0
  98. package/dist/local-d1-DzykTWY8.mjs +104 -0
  99. package/dist/{login-WIjNc77c.mjs → login-CKk5NX4d.mjs} +6 -11
  100. package/dist/login-Ch9cgWRF.mjs +2 -0
  101. package/dist/{logs-dLUFCapG.mjs → logs-hxWBSoej.mjs} +6 -4
  102. package/dist/migrate-CLty4mZR.mjs +2 -0
  103. package/dist/migrate-DcW8F2W8.mjs +285 -0
  104. package/dist/migration-handler-DM4clYj5.d.mts +51 -0
  105. package/dist/{neon-DHwd2zvC.mjs → neon-n74ta1Pr.mjs} +1 -1
  106. package/dist/{node-Ez5KW5rn.mjs → node-Cupyf7-s.mjs} +6 -6
  107. package/dist/{operator-auth-B3e08unv.mjs → operator-auth-BkVgJqv-.mjs} +2 -2
  108. package/dist/{operator-client-LUZnlnYk.mjs → operator-client-A0iex2yi.mjs} +2 -1
  109. package/dist/{operator-cmd-CKJ7xIRs.mjs → operator-cmd-BEUYhaHB.mjs} +6 -6
  110. package/dist/output-urU86XeT.mjs +146 -0
  111. package/dist/{package-json-CPoWX79C.mjs → package-json-iCbMg5XF.mjs} +1 -1
  112. package/dist/pages/client.d.mts +5 -2
  113. package/dist/pages/client.mjs +5 -3
  114. package/dist/pages/head-client.mjs +1 -89
  115. package/dist/pages/head.mjs +1 -111
  116. package/dist/pages/index.d.mts +2 -3
  117. package/dist/pages/index.mjs +7 -7
  118. package/dist/pages/islands-plugin.mjs +2 -2
  119. package/dist/pages/prefetch.d.mts +2 -30
  120. package/dist/pages/prefetch.mjs +1 -89
  121. package/dist/pages/protocol.d.mts +2 -2
  122. package/dist/pages/protocol.mjs +3 -3
  123. package/dist/pages/serialize.d.mts +2 -9
  124. package/dist/pages/serialize.mjs +1 -13
  125. package/dist/plan-BEZ8VJW0.mjs +256 -0
  126. package/dist/plan-DpuOr14e.mjs +2 -0
  127. package/dist/{platform-auth-config-CdVWRRJr.mjs → platform-auth-config-Df6yVw-e.mjs} +6 -6
  128. package/dist/{platform-auth-protection-Drl0qhrn.mjs → platform-auth-protection-Jb0yftay.mjs} +7 -5
  129. package/dist/{platform-auth-recovery-CmKEWpDo.mjs → platform-auth-recovery-DmRyIfW0.mjs} +6 -5
  130. package/dist/platform-cmd-C9Vt7m-d.mjs +2 -0
  131. package/dist/{platform-cmd-5q_k56xS.mjs → platform-cmd-DRxCOTwy.mjs} +8 -5
  132. package/dist/{platform-domain-4GiDlcqx.mjs → platform-domain-IjiXgrXJ.mjs} +4 -3
  133. package/dist/{platform-lifecycle-R9xAxvtG.mjs → platform-lifecycle-BquAaU-5.mjs} +208 -37
  134. package/dist/platform-lifecycle-CuJIZNvA.mjs +2 -0
  135. package/dist/{platform-management-BfWsXHEW.mjs → platform-management-CCQKGsq4.mjs} +8 -5
  136. package/dist/platform-management-Cgyed0WY.mjs +2 -0
  137. package/dist/{platform-recovery-CbK-I1FB.mjs → platform-recovery-DS8ih1SW.mjs} +3 -3
  138. package/dist/platform-registry-BJbgZLS1.mjs +431 -0
  139. package/dist/{plugin-inference-BDRfZngg.mjs → plugin-inference-DsvtJLll.mjs} +4 -4
  140. package/dist/prefetch-Bsc_Pb6c.mjs +90 -0
  141. package/dist/prefetch-Ce6la4EI.d.mts +31 -0
  142. package/dist/{prepare-blNRQvQl.mjs → prepare-CaUxODOU.mjs} +3 -2
  143. package/dist/prepare-D4CkM3_v.mjs +2 -0
  144. package/dist/{prepare-CtDJjoOj.mjs → prepare-pcWcxSCh.mjs} +13 -11
  145. package/dist/prerender-render-Cf_WDE9W.mjs +111 -0
  146. package/dist/prerender-render.mjs +1 -110
  147. package/dist/{preset-lAy0B0BQ.mjs → preset-Dowh9tTt.mjs} +16 -118
  148. package/dist/project-BEBFDFLz.mjs +2 -0
  149. package/dist/project-CWNIPoXc.mjs +209 -0
  150. package/dist/{project-cmd-CTdmnzvc.mjs → project-cmd-2lN--YAX.mjs} +18 -16
  151. package/dist/{project-paths-SK8nMHPp.mjs → project-paths-CKQ-Q5JS.mjs} +47 -14
  152. package/dist/project-slug-23TpquG4.mjs +8 -0
  153. package/dist/project-slug-DofjTFd-.mjs +2 -0
  154. package/dist/{project-team-CGxsQe3_.mjs → project-team-Dapn9HZn.mjs} +6 -4
  155. package/dist/{project-token-Cirx7uwZ.mjs → project-token-C90v9SJK.mjs} +6 -4
  156. package/dist/{project-tsconfig-Ql2XsSQp.mjs → project-tsconfig-CwfqUnVp.mjs} +2 -2
  157. package/dist/{protocol-C-pqYJjE.d.mts → protocol-ZH3jP4a7.d.mts} +1 -1
  158. package/dist/providers-BNKRacMr.d.mts +7 -0
  159. package/dist/provision-CNgEBkVA.mjs +3 -0
  160. package/dist/{provision-CSJOjjQk.mjs → provision-Cck2m3jJ.mjs} +11 -25
  161. package/dist/queues-BWKt1Xo4.d.mts +7 -0
  162. package/dist/{requests-4Nq59hOr.mjs → requests-CzX46I0i.mjs} +5 -3
  163. package/dist/resolve-project-BTotl8Nn.mjs +2 -0
  164. package/dist/{resolve-project--Vxawf7z.mjs → resolve-project-Xvis70DG.mjs} +2 -8
  165. package/dist/response-Tn7rU0MV.mjs +30 -0
  166. package/dist/{rollback-Dr7u0Ljx.mjs → rollback-BEeyc73H.mjs} +6 -4
  167. package/dist/{rolldown-runtime-rQ84J-ij.mjs → rolldown-runtime-DXIUcv95.mjs} +1 -10
  168. package/dist/route-types-Id82-veQ.mjs +280 -0
  169. package/dist/{local-d1-D2I6Ox5F.mjs → runner-BGVsGgkb.mjs} +6 -114
  170. package/dist/runner-CQs_cDSG.mjs +2 -0
  171. package/dist/runner-mysql-1o47achK.mjs +2 -0
  172. package/dist/{runner-mysql-7BPUNGmL.mjs → runner-mysql-BhwMk2Bm.mjs} +2 -9
  173. package/dist/{runner-pg-BkEza-dX.mjs → runner-pg-CJ_JeGF6.mjs} +2 -9
  174. package/dist/runner-pg-D7z01mQS.mjs +2 -0
  175. package/dist/runtime/ai.mjs +1 -1
  176. package/dist/runtime/auth-client-react.d.mts +2 -6
  177. package/dist/runtime/auth-client-react.mjs +1 -5
  178. package/dist/runtime/auth-client-solid.d.mts +2 -6
  179. package/dist/runtime/auth-client-solid.mjs +1 -5
  180. package/dist/runtime/auth-client-svelte.d.mts +2 -6
  181. package/dist/runtime/auth-client-svelte.mjs +1 -5
  182. package/dist/runtime/auth-client-vue.d.mts +2 -6
  183. package/dist/runtime/auth-client-vue.mjs +1 -5
  184. package/dist/runtime/auth-client.d.mts +2 -6
  185. package/dist/runtime/auth-client.mjs +1 -5
  186. package/dist/runtime/auth.mjs +1 -21
  187. package/dist/runtime/better-auth-mysql.d.mts +1 -1
  188. package/dist/runtime/better-auth-mysql.mjs +1 -1
  189. package/dist/runtime/better-auth-pg.d.mts +1 -1
  190. package/dist/runtime/better-auth-pg.mjs +1 -1
  191. package/dist/runtime/better-auth.d.mts +1 -1
  192. package/dist/runtime/better-auth.mjs +1 -1
  193. package/dist/runtime/client-react.d.mts +3 -3
  194. package/dist/runtime/client-react.mjs +3 -3
  195. package/dist/runtime/client-solid.d.mts +3 -3
  196. package/dist/runtime/client-solid.mjs +3 -3
  197. package/dist/runtime/client-svelte.d.mts +3 -3
  198. package/dist/runtime/client-svelte.mjs +3 -3
  199. package/dist/runtime/client-vue.d.mts +3 -3
  200. package/dist/runtime/client-vue.mjs +3 -3
  201. package/dist/runtime/client.d.mts +3 -3
  202. package/dist/runtime/client.mjs +3 -3
  203. package/dist/runtime/db.mjs +1 -1
  204. package/dist/runtime/durable.mjs +1 -1
  205. package/dist/runtime/email/testing.mjs +1 -1
  206. package/dist/runtime/env-helpers.mjs +1 -135
  207. package/dist/runtime/env-public-client.mjs +1 -1
  208. package/dist/runtime/env-public.mjs +2 -2
  209. package/dist/runtime/env.mjs +1 -77
  210. package/dist/runtime/fetch-stream.d.mts +2 -49
  211. package/dist/runtime/fetch-stream.mjs +2 -80
  212. package/dist/runtime/fetch.d.mts +2 -57
  213. package/dist/runtime/fetch.mjs +2 -17
  214. package/dist/runtime/handler.d.mts +1 -1
  215. package/dist/runtime/handler.mjs +1 -149
  216. package/dist/runtime/kv.mjs +1 -1
  217. package/dist/runtime/live-client.d.mts +1 -1
  218. package/dist/runtime/live-server.mjs +2 -2
  219. package/dist/runtime/live.d.mts +2 -104
  220. package/dist/runtime/live.mjs +1 -410
  221. package/dist/runtime/migration-handler-mysql.d.mts +1 -1
  222. package/dist/runtime/migration-handler-pg.d.mts +1 -1
  223. package/dist/runtime/migration-handler.d.mts +2 -50
  224. package/dist/runtime/queues.d.mts +2 -6
  225. package/dist/runtime/queues.mjs +1 -1
  226. package/dist/runtime/response.mjs +1 -29
  227. package/dist/runtime/sandbox.mjs +1 -1
  228. package/dist/runtime/sse.mjs +1 -171
  229. package/dist/runtime/storage.mjs +1 -1
  230. package/dist/runtime/validator.d.mts +1 -1
  231. package/dist/runtime/validator.mjs +1 -71
  232. package/dist/runtime/ws-server.d.mts +2 -2
  233. package/dist/runtime/ws-server.mjs +2 -2
  234. package/dist/runtime/ws.d.mts +2 -121
  235. package/dist/{scan-CpK-57ug.mjs → scan-DJbooZm2.mjs} +3 -3
  236. package/dist/{scan-BMH4rzlv.mjs → scan-DdDvRCU1.mjs} +8 -26
  237. package/dist/{secret-AcPi-FoA.mjs → secret-wnTel5Yw.mjs} +8 -6
  238. package/dist/serialize-BPvnNQuA.mjs +14 -0
  239. package/dist/serialize-CfSwWfF2.d.mts +10 -0
  240. package/dist/{skills-C0RvGjeE.mjs → skills-B-690E7h.mjs} +3 -2
  241. package/dist/sse-BaC1jXko.mjs +172 -0
  242. package/dist/{subcommand-prompt-Bmyn5Rlc.mjs → subcommand-prompt-Gj3VzLIh.mjs} +2 -1
  243. package/dist/sveltekit.d.mts +2 -1
  244. package/dist/sveltekit.mjs +3 -2
  245. package/dist/validate-DqJ33oHj.mjs +2 -0
  246. package/dist/validate-qNhV00PD.mjs +180 -0
  247. package/dist/validator-BTOu0fB0.mjs +72 -0
  248. package/dist/{wrangler--imS8n0d.mjs → wrangler-D01qs6VB.mjs} +259 -71
  249. package/dist/ws-BwcqizuH.d.mts +122 -0
  250. package/dist/{yarn-pnp-DxSInkzL.mjs → yarn-pnp-CVEc3gE7.mjs} +1 -1
  251. package/package.json +19 -8
  252. package/skills/void/SKILL.md +6 -4
  253. package/skills/void/docs/guide/ai.md +3 -3
  254. package/skills/void/docs/guide/app-types.md +12 -11
  255. package/skills/void/docs/guide/auth.md +2 -2
  256. package/skills/void/docs/guide/database/d1.md +1 -1
  257. package/skills/void/docs/guide/database/mysql.md +1 -1
  258. package/skills/void/docs/guide/database/postgresql.md +3 -3
  259. package/skills/void/docs/guide/deployment.md +2 -2
  260. package/skills/void/docs/guide/durable-state.md +2 -2
  261. package/skills/void/docs/guide/edge/headers.md +3 -3
  262. package/skills/void/docs/guide/edge/prerendering.md +1 -1
  263. package/skills/void/docs/guide/edge/redirects.md +4 -4
  264. package/skills/void/docs/guide/edge/revalidation.md +6 -6
  265. package/skills/void/docs/guide/edge/rewrites.md +28 -27
  266. package/skills/void/docs/guide/edge/static-assets.md +1 -1
  267. package/skills/void/docs/guide/email.md +15 -15
  268. package/skills/void/docs/guide/env-migration.md +1 -1
  269. package/skills/void/docs/guide/index.md +1 -1
  270. package/skills/void/docs/guide/pages-routing/head.md +1 -1
  271. package/skills/void/docs/guide/platform/administration/access.md +13 -5
  272. package/skills/void/docs/guide/platform/administration/projects.md +3 -1
  273. package/skills/void/docs/guide/platform/installation/ci.md +3 -0
  274. package/skills/void/docs/guide/platform/installation/credentials.md +15 -5
  275. package/skills/void/docs/guide/platform/installation/prerequisites.md +2 -0
  276. package/skills/void/docs/guide/platform/installation/setup.md +1 -1
  277. package/skills/void/docs/guide/remote-dev.md +2 -2
  278. package/skills/void/docs/guide/sandboxes.md +1 -1
  279. package/skills/void/docs/guide/ssg.md +1 -1
  280. package/skills/void/docs/guide/websockets.md +1 -1
  281. package/skills/void/docs/integrations/cloudflare.md +86 -84
  282. package/skills/void/docs/integrations/frameworks/analog.md +14 -9
  283. package/skills/void/docs/integrations/frameworks/astro.md +14 -10
  284. package/skills/void/docs/integrations/frameworks/nuxt.md +14 -9
  285. package/skills/void/docs/integrations/frameworks/overview.md +35 -29
  286. package/skills/void/docs/integrations/frameworks/react-router.md +1 -1
  287. package/skills/void/docs/integrations/frameworks/sveltekit.md +33 -30
  288. package/skills/void/docs/integrations/frameworks/tanstack-start.md +1 -1
  289. package/skills/void/docs/integrations/nodejs-bun-deno.md +5 -5
  290. package/skills/void/docs/reference/api.md +21 -4
  291. package/skills/void/docs/reference/cli.md +32 -23
  292. package/skills/void/docs/reference/config.md +56 -33
  293. package/skills/void/docs/reference/structure.md +2 -2
  294. package/dist/validate-tBBN_dXH.mjs +0 -505
@@ -21,53 +21,56 @@ cd my-app
21
21
  npm install -D @sveltejs/adapter-cloudflare void
22
22
  ```
23
23
 
24
- ### 3. Configure `svelte.config.js`
25
-
26
- ```js
27
- import adapter from '@sveltejs/adapter-cloudflare';
28
- import { withVoidTSConfig } from 'void/sveltekit';
29
-
30
- export default {
31
- kit: {
32
- adapter: adapter(),
33
- typescript: {
34
- config: withVoidTSConfig(),
35
- },
36
- },
37
- };
38
- ```
39
-
40
- ### 4. Add `voidPlugin()` to `vite.config.ts`
24
+ ### 3. Configure `vite.config.ts`
41
25
 
42
26
  ```ts
27
+ import adapter from '@sveltejs/adapter-cloudflare';
43
28
  import { sveltekit } from '@sveltejs/kit/vite';
44
29
  import { voidPlugin } from 'void';
30
+ import { withVoidTSConfig } from 'void/sveltekit';
45
31
  import { defineConfig } from 'vite';
46
32
 
47
33
  export default defineConfig({
48
- plugins: [voidPlugin(), sveltekit()],
34
+ plugins: [
35
+ voidPlugin(),
36
+ sveltekit({
37
+ adapter: adapter({
38
+ config: './.void-wrangler.jsonc',
39
+ platformProxy: { configPath: './.void-wrangler.jsonc' },
40
+ }),
41
+ typescript: {
42
+ config: withVoidTSConfig(),
43
+ },
44
+ }),
45
+ ],
49
46
  });
50
47
  ```
51
48
 
52
- ### 5. Create `wrangler.jsonc`
49
+ If your project already configures SvelteKit in `svelte.config.js`, keep that file and add `typescript.config: withVoidTSConfig()` under its `kit` options instead. SvelteKit ignores `svelte.config.js` when options are passed directly to `sveltekit()`.
53
50
 
54
- SvelteKit's adapter reads bindings from `wrangler.jsonc` for local dev. `voidPlugin()` auto-syncs inferred bindings into this file on dev startup, so you only need the base config:
51
+ ### 4. Create `void.config.ts`
55
52
 
56
- ```jsonc
57
- {
58
- "name": "my-app",
59
- "compatibility_date": "2026-02-24",
60
- "compatibility_flags": ["nodejs_compat"],
61
- }
53
+ Point SvelteKit's adapter at Void's generated Cloudflare config as shown above. Add your Cloudflare settings to `void.config.ts`:
54
+
55
+ ```ts
56
+ import { defineConfig } from 'void/config';
57
+
58
+ export default defineConfig({
59
+ cloudflare: {
60
+ name: 'my-app',
61
+ compatibility_date: '2026-02-24',
62
+ compatibility_flags: ['nodejs_compat'],
63
+ },
64
+ });
62
65
  ```
63
66
 
64
67
  By default, SvelteKit's Cloudflare adapter, `voidPlugin()` migrations, and `void db` commands share local state at `.wrangler/state/v3`, so no extra `platformProxy.persist` configuration is required.
65
68
 
66
- ### 6. Configure `tsconfig.json`
69
+ ### 5. Configure `tsconfig.json`
67
70
 
68
71
  SvelteKit generates `.svelte-kit/tsconfig.json` and expects your root config to extend it. Void generates `.void/tsconfig.json` for project-specific aliases such as `void/db` and `@schema`.
69
72
 
70
- Do not add Void's `compilerOptions.paths` to the root `tsconfig.json`; SvelteKit warns because root-level paths override its generated aliases. The `withVoidTSConfig()` hook above merges Void's generated files and aliases into SvelteKit's generated config instead.
73
+ Do not add Void's `compilerOptions.paths` to the root `tsconfig.json`; SvelteKit warns because root-level paths override its generated aliases. The `withVoidTSConfig()` hook merges Void's generated files and aliases into SvelteKit's generated config instead.
71
74
 
72
75
  ```json
73
76
  {
@@ -80,7 +83,7 @@ Do not add Void's `compilerOptions.paths` to the root `tsconfig.json`; SvelteKit
80
83
 
81
84
  Run `void prepare` after a fresh clone or before typechecking in CI so `.void/tsconfig.json` exists before SvelteKit syncs its config.
82
85
 
83
- ### 7. Deploy
86
+ ### 6. Deploy
84
87
 
85
88
  ```bash
86
89
  void auth login
@@ -132,7 +135,7 @@ import { ai } from 'void/ai';
132
135
 
133
136
  export const actions = {
134
137
  summarize: async () => {
135
- return ai.run('@cf/meta/llama-3.1-8b-instruct', {
138
+ return ai.run('@cf/meta/llama-3.3-70b-instruct-fp8-fast', {
136
139
  prompt: 'Summarize the latest news',
137
140
  });
138
141
  },
@@ -92,7 +92,7 @@ import { createServerFn } from '@tanstack/react-start';
92
92
  import { ai } from 'void/ai';
93
93
 
94
94
  const summarize = createServerFn().handler(async () => {
95
- return ai.run('@cf/meta/llama-3.1-8b-instruct', {
95
+ return ai.run('@cf/meta/llama-3.3-70b-instruct-fp8-fast', {
96
96
  prompt: 'Summarize the latest news',
97
97
  });
98
98
  });
@@ -4,7 +4,7 @@ outline: deep
4
4
 
5
5
  # Node.js, Bun, and Deno
6
6
 
7
- Set `target` in `void.json` to build for Node.js, Bun, or Deno. You can run the resulting server on your own machine, in a container, or with a hosting provider.
7
+ Set `target` in `void.config.ts` to build for Node.js, Bun, or Deno. You can run the resulting server on your own machine, in a container, or with a hosting provider.
8
8
 
9
9
  ```json
10
10
  { "target": "node" }
@@ -25,7 +25,7 @@ All three produce the same project structure and use the same Hono-based routing
25
25
  ### 1. Configure the target
26
26
 
27
27
  ```json
28
- // void.json
28
+ // void.config.ts
29
29
  { "target": "node" }
30
30
  ```
31
31
 
@@ -140,7 +140,7 @@ Inbound [email handlers](../guide/email.md#inbound) in `email/` need Cloudflare
140
140
 
141
141
  ### Ignored config fields
142
142
 
143
- Void warns and ignores these Cloudflare-specific `void.json` fields on other targets:
143
+ Void warns and ignores these Cloudflare-specific `void.config.ts` fields on other targets:
144
144
 
145
145
  - `inference.bindings`: Cloudflare binding configuration
146
146
  - `remote`: remote binding proxy
@@ -166,11 +166,11 @@ my-app/
166
166
  hello.ts
167
167
  package.json
168
168
  vite.config.ts
169
- void.json
169
+ void.config.ts
170
170
  ```
171
171
 
172
172
  ```json
173
- // void.json
173
+ // void.config.ts
174
174
  { "target": "node" }
175
175
  ```
176
176
 
@@ -10,7 +10,7 @@ This page is the source of truth for user-facing `void` exports. Use it when you
10
10
 
11
11
  ### `voidPlugin(options?)`
12
12
 
13
- Named export from `"void"`. Returns an array of Vite plugins that set up file-based routing, migration support, and the Cloudflare Workers runtime. Application-level configuration is read from [`void.json`](./config.md); the optional `options` object controls Vite/Cloudflare plugin behavior.
13
+ Named export from `"void"`. Returns an array of Vite plugins that set up file-based routing, migration support, and the Cloudflare Workers runtime. Application-level configuration is read from [`void.config.ts`](./config.md); the optional `options` object controls Vite/Cloudflare plugin behavior.
14
14
 
15
15
  ```ts
16
16
  import { voidPlugin } from 'void';
@@ -25,6 +25,23 @@ export default defineConfig({
25
25
  | `persistTo` | `string` | Directory path for persisting local dev state (D1, KV, R2). Defaults to `.void/` in the project root. |
26
26
  | `auxiliaryWorkers` | `AuxiliaryWorkerConfig[]` | Additional workers to run inside the same Miniflare instance during dev. Passed through to `@cloudflare/vite-plugin`. Useful for running multiple workers that share bindings (e.g. a separate API worker alongside a dashboard). |
27
27
 
28
+ ## Project configuration
29
+
30
+ ### `defineConfig(config)`
31
+
32
+ Import from `void/config` in the root `void.config.ts`. It returns the config with editor completion and TypeScript checking. Void validates the result when loading it, including values computed at runtime.
33
+
34
+ ```ts
35
+ import { defineConfig } from 'void/config';
36
+
37
+ export default defineConfig({
38
+ cloudflare: { name: 'my-app' },
39
+ routing: { revalidate: 60 },
40
+ });
41
+ ```
42
+
43
+ See the [config reference](./config.md) for all fields.
44
+
28
45
  ## Handlers
29
46
 
30
47
  Imported from `"void"` or `"void/handler"`.
@@ -278,7 +295,7 @@ function defineHead<P = Record<string, unknown>>(
278
295
 
279
296
  ## Rewrites
280
297
 
281
- URL rewrites re-dispatch a request at a different internal path without changing the browser's URL. `c.rewrite()`, `c.originalUrl()`, and `c.isRewritten()` are available on every Hono `Context` the Void runtime hands you. See the [Rewrites guide](../guide/edge/rewrites.md) for the full overview, including static `routing.rewrites` / `routing.fallbacks` in [`void.json`](./config.md#routing).
298
+ URL rewrites re-dispatch a request at a different internal path without changing the browser's URL. `c.rewrite()`, `c.originalUrl()`, and `c.isRewritten()` are available on every Hono `Context` the Void runtime hands you. See the [Rewrites guide](../guide/edge/rewrites.md) for the full overview, including static `routing.rewrites` / `routing.fallbacks` in [`void.config.ts`](./config.md#routing).
282
299
 
283
300
  ### `c.rewrite(destination)`
284
301
 
@@ -345,7 +362,7 @@ import type { RewriteDestination } from 'void/routes';
345
362
  Union of the exact route patterns from your generated `RouteMap` plus a `string` fallback (`RouteName | (string & {})`). Known route patterns (e.g. `/posts/[id]`) are offered as autocomplete entries in your editor, while the `string` branch keeps the type assignable from concrete runtime paths like `` `/posts/${id}` `` — there is no `:id` template-literal resolution at the type level. Used as:
346
363
 
347
364
  - The parameter type of [`c.rewrite()`](#c-rewrite-destination).
348
- - The type of `destination` entries in `routing.rewrites` and `routing.fallbacks` in [`void.json`](./config.md#routing).
365
+ - The type of `destination` entries in `routing.rewrites` and `routing.fallbacks` in [`void.config.ts`](./config.md#routing).
349
366
 
350
367
  Like [`RouteMap`](#routemap), `RewriteDestination` lives in the virtual `void/routes` module and is refreshed whenever routes change.
351
368
 
@@ -752,7 +769,7 @@ Typed AI client for Cloudflare AI models and provider-native AI Gateway requests
752
769
  ```ts
753
770
  import { ai } from 'void/ai';
754
771
 
755
- const result = await ai.run('@cf/meta/llama-3.1-8b-instruct', {
772
+ const result = await ai.run('@cf/meta/llama-3.3-70b-instruct-fp8-fast', {
756
773
  messages: [{ role: 'user', content: 'Summarize this release note.' }],
757
774
  });
758
775
 
@@ -48,6 +48,7 @@ Use this page as a command reference. If you are setting up a project for the fi
48
48
  | `void email disallow <address>` | Remove a recipient from the allowlist |
49
49
  | `void email domain` | Send and receive at your own domain on a Cloudflare zone |
50
50
  | `void init` | Setup wizard for new or existing projects |
51
+ | `void migrate` | Convert legacy `void.json` and root Wrangler JSON/JSONC into `void.config.ts` |
51
52
 
52
53
  ## Binary Invocation
53
54
 
@@ -75,6 +76,10 @@ Use `void --help` for the command list. For a specific command, try `void deploy
75
76
 
76
77
  ## Setup
77
78
 
79
+ ### `void migrate`
80
+
81
+ `void migrate` converts `void.json` and root `wrangler.jsonc` or `wrangler.json` into a typed `void.config.ts`. It also recognizes a single root `wrangler*.json(c)` file explicitly referenced by a supported framework adapter. Void backs up the originals under `.void/config-migration/`, keeps Cloudflare resource state in `void.lock.json`, and updates supported framework adapters to use its generated Cloudflare config. `.void-wrangler.jsonc` is a generated Cloudflare tooling file; migration adds it to `.gitignore`. `void init` and `void deploy` run this migration automatically when they find legacy files. Before Cloudflare deployment, the project's installed `void` package must match the CLI version. Review and commit the new config, lock, and `.gitignore`. If multiple Cloudflare config files exist or existing files disagree, resolve them before retrying.
82
+
78
83
  ### `void init`
79
84
 
80
85
  ```
@@ -108,7 +113,7 @@ After that, the full interactive flow walks through:
108
113
  3. **Agent instructions:** always creates or updates `AGENTS.md` with brief Void instructions and the bundled docs path, preserving content outside the versioned block.
109
114
  4. **Skills:** links Void skills for detected coding agents.
110
115
  5. **Demo code:** for existing non-Pages projects, optionally scaffolds a `db/migrations/` directory plus an API route and typed fetch example.
111
- 6. **Deployment platform:** asks where `void deploy` should send the app: Cloudflare (the default), Void, or Skip deployment setup. The choice is stored as `platform` in `.void/project.json`. Choosing Cloudflare creates or augments `wrangler.jsonc`, checks the Cloudflare session through Void's bundled tooling, opens secure browser sign-in when needed, and writes the selected account as `account_id` (automatically when only one account is available).
116
+ 6. **Deployment platform:** asks where `void deploy` should send the app: Cloudflare (the default), Void, or Skip deployment setup. The choice is stored as `platform` in `.void/project.json`. Choosing Cloudflare records settings in `void.config.ts` and `void.lock.json`, checks the Cloudflare session through Void's bundled tooling, opens secure browser sign-in when needed, and writes the selected account as `account_id` (automatically when only one account is available).
112
117
  7. **GitHub Actions:** optionally creates `.github/workflows/void-deploy.yml` for the selected target. Cloudflare workflows run `void deploy --platform cloudflare` with `CLOUDFLARE_API_TOKEN` and pass the optional `DATABASE_URL` secret needed by PostgreSQL/MySQL apps. Void workflows use the selected platform's API URL and are offered only when its discovery document advertises GitHub Actions support.
113
118
  8. **`env.ts` scaffold:** if the project has no `env.ts` but has a root `.env`, generates an `env.ts` pre-populated with its keys. Values get conservative type inference (`boolean`/`url`/`number`/`string`) — the file carries a banner nudging you to tighten anything the heuristic got wrong.
114
119
  9. **Void project setup:** when Void is selected, optionally logs you in, lets you select or create a project, and adds the link to `.void/project.json` so your first deploy can just be `void deploy`.
@@ -154,7 +159,7 @@ void connect --platform void
154
159
 
155
160
  Connect a project to its deployment destination. With no arguments, choose Cloudflare or a Void platform interactively. A URL selects a Void platform directly. `--platform void` offers saved platforms and an option to enter another URL.
156
161
 
157
- For Cloudflare, Void signs in through the browser when needed, selects an accessible account, and saves `account_id` in the root `wrangler.jsonc` or `wrangler.json`. It shares this setup with `void init`. An existing account selection is preserved; conflicting or inaccessible account settings must be resolved before continuing.
162
+ For Cloudflare, Void signs in through the browser when needed, selects an accessible account, and saves `cloudflare.account_id` in `void.config.ts` or resolved state in `void.lock.json`. It shares this setup with `void init`. An existing account selection is preserved; conflicting or inaccessible account settings must be resolved before continuing.
158
163
 
159
164
  For a Void platform, Void validates its discovery document, reuses a valid session or opens browser login using the platform's supported providers, and saves the verified API and proxy origins. Credentials are stored in the operating-system keychain for that API origin. A sole login provider is selected automatically.
160
165
 
@@ -220,11 +225,11 @@ An API token or global API key pair in the environment takes precedence over bro
220
225
  Show deployments for the configured target.
221
226
 
222
227
  - Void targets show recent hosted deployments; `[name]` looks up a project by slug and otherwise the linked project is used.
223
- - Cloudflare targets list Worker Versions, identify the active version, and show the recorded migration count. A project name is not accepted because the Worker name comes from root `wrangler.jsonc`.
228
+ - Cloudflare targets list Worker Versions, identify the active version, and show the recorded migration count. A project name is not accepted because the Worker name comes from `cloudflare.name` in `void.config.ts`.
224
229
 
225
230
  ### `void project link [name]`
226
231
 
227
- Link current directory to an existing hosted Void project by slug, or select interactively if omitted. State is stored in `.void/project.json`. Direct Cloudflare apps use the Worker name in the root config and do not need linking.
232
+ Link current directory to an existing hosted Void project by slug, or select interactively if omitted. State is stored in `.void/project.json`. Direct Cloudflare apps use `cloudflare.name` in `void.config.ts` and do not need linking.
228
233
 
229
234
  ### `void project list`
230
235
 
@@ -309,7 +314,7 @@ in the two entries when the Access policies require them.
309
314
  void project logs [--level <level>] [--filter <text>] [--range <duration>] [--deployment <id>]
310
315
  ```
311
316
 
312
- Show runtime logs from the deployed target. Hosted Void targets query retained log history. Cloudflare targets open a live tail for the Worker named in root `wrangler.jsonc`; they do not provide historical log storage.
317
+ Show runtime logs from the deployed target. Hosted Void targets query retained log history. Cloudflare targets open a live tail for the Worker named in `void.config.ts`; they do not provide historical log storage.
313
318
 
314
319
  | Flag | Purpose | Default |
315
320
  | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
@@ -625,7 +630,7 @@ void platform signup allow identity <connection-id> <subject> [--note <text>]
625
630
  void platform signup disallow identity <connection-id> <subject>
626
631
  ```
627
632
 
628
- Connection IDs are shown by `void platform config auth list`. Identity subjects match exactly and case-sensitively; wildcards, email inference, and account linking are not applied. The login method's domain or group restrictions must still pass, and a newly admitted account has the ordinary user role. With restrictions enabled and an empty allowlist, nobody new can sign up.
633
+ Connection IDs are shown by `void platform config auth list`. Identity subjects match exactly and case-sensitively; wildcards, email inference, and account linking are not applied. The login method's domain or group restrictions must still pass, and a newly admitted account has the ordinary user role. Under invited/allowlisted signup, an empty allowlist blocks new accounts. Under company-approved signup, explicit grants admit people in addition to the company rules.
629
634
 
630
635
  #### Invitations {#operator-invitations}
631
636
 
@@ -637,7 +642,7 @@ void platform invitation send <email[,email...]>
637
642
  void platform invitation revoke <id>
638
643
  ```
639
644
 
640
- Send accepts up to 100 comma-separated addresses. Invitations grant signup access even if email delivery is unavailable or fails; delivery is reported separately. Revoking a pending invitation removes its exact email grant. A broader domain entry can still allow that person to sign up.
645
+ Send accepts up to 100 comma-separated addresses. Invitations grant signup access even if email delivery is unavailable or fails; delivery is reported separately. Share the platform's `/invite` page or `void connect '<platform URL>'` command yourself when no email is sent. Revoking a pending invitation removes its exact email grant. A broader domain entry can still allow that person to sign up.
641
646
 
642
647
  #### Email {#operator-email}
643
648
 
@@ -772,8 +777,12 @@ To enable email during install or upgrade, set both `VOID_EMAIL_SENDER_DOMAIN` a
772
777
 
773
778
  `--plan` prints the actual resource names, selected login methods, login callback, and direct setup links without opening credential pages or saving a draft; Cloudflare browser login still opens if needed. New platform resources use `void-<name>-<role>` names without random suffixes. Existing installations keep their recorded names, and unowned name conflicts stop installation without overwriting resources. After you confirm an interactive install, Void opens each missing credential's setup page and shows a short permission/checklist fallback. The runtime-token link preselects all required account permissions, including Workers Tail, Hyperdrive, and AI Gateway when needed; domain installations must also select the indicated zone. Supplied credentials skip browser opening. Setup drafts pin Worker names and the login callback and save partial credentials encrypted locally. Interactive installs list unfinished installations, including interrupted provisioning, or offer a new install. Entering an existing unfinished name asks to resume it; declining returns to name entry. Starting new leaves previous setup, credentials, and resources untouched. Completed platforms are not offered for resumption. `--resume` skips the choice and is required for non-interactive recovery.
774
779
 
780
+ At the end of a plan, Void prints a command to install with the resolved name, account, domain, and any supplied authentication file or runtime. Running that command later recalculates the plan; interactive use asks for confirmation and missing credentials. If you chose login methods interactively, choose them again during installation. A plan for an unfinished installation instead prints its checkpointed `--resume` command.
781
+
775
782
  Use an empty PostgreSQL database dedicated to the installation. You can correct a failed initial connection, but after the database is claimed or Hyperdrive is provisioned, commands reject a different URL.
776
783
 
784
+ During interactive installation, choose whether Void creates Hyperdrive or uses one you manage separately. If the separately managed configuration is missing, Void shows the required name and setup instructions, then stops before provisioning. Once it exists, Void shows its database, host, port, runtime user, and cache setting for confirmation. Supply an owner PostgreSQL URL at the normal prompt for database claims and migrations. Void adopts the Hyperdrive after verifying its origin and disabled SQL result caching; its configuration stays under the external manager's control. Unattended installs can set `VOID_PLATFORM_HYPERDRIVE_ID`, `VOID_PLATFORM_HYPERDRIVE_ORIGIN_HOST`, and `VOID_PLATFORM_HYPERDRIVE_ORIGIN_USER` together.
785
+
777
786
  Recovery secrets are encrypted with AES-256-GCM using a key in your system keychain. The encrypted data is tied to the installation identity. Without a keychain, supply a canonical base64-encoded 32-byte `VOID_PLATFORM_RECOVERY_KEY`; otherwise Void stops before saving secrets. CI can generate a temporary key when its original credentials remain in protected secrets.
778
787
 
779
788
  If a newly created zone is waiting for registrar delegation, resume after it becomes active:
@@ -855,11 +864,11 @@ void deploy [--platform <cloudflare|void>] [--require-email]
855
864
 
856
865
  Auto-detects your project type and chooses the right pipeline. See [Supported App Types](../guide/app-types.md) and [Deployment](../guide/deployment.md) for details.
857
866
 
858
- An unlinked project with a root `wrangler.jsonc` or `wrangler.json` gets a prompt to link and deploy to Cloudflare using its existing Worker and resources. Accepting verifies the target, saves Cloudflare as the destination, and continues deployment. A failed build retains the link for retry. Declining changes nothing. Explicit platform/project selections and saved destinations take precedence; CI must select a destination explicitly.
867
+ An unlinked project with a root `wrangler.jsonc`, `wrangler.json`, or a single root `wrangler*.json(c)` file explicitly referenced by a supported framework adapter gets a prompt to link and deploy to Cloudflare using its existing Worker and resources. Accepting verifies the target, saves Cloudflare as the destination, and continues deployment. A failed build retains the link for retry. Declining changes nothing. Explicit platform/project selections and saved destinations take precedence; CI must select a destination explicitly.
859
868
 
860
869
  The first handoff preserves production bindings, variables, secrets, event handlers, and triggers. The active version must be the latest uploaded version so inherited secrets have an unambiguous source. Apart from an explicitly enabled ISR cache, new resources, migrations, runtime features, auth setup, or local secret overrides must be handled separately. See [Deploy an existing Worker](../integrations/cloudflare.md#deploy-an-existing-worker).
861
870
 
862
- When prerendered or revalidated pages need a cache during migration, Void asks whether to enable ISR and saves `routing.isr` in `void.json`. Yes provisions the KV cache during this handoff; No keeps ISR disabled on every later deploy until you change the setting. CI must set `routing.isr` explicitly if a pending migration has no saved choice. Existing ISR namespaces are reused; application KV bindings are still required.
871
+ When prerendered or revalidated pages need a cache during migration, Void asks whether to enable ISR and saves `routing.isr` in `void.config.ts`. Yes provisions the KV cache during this handoff; No keeps ISR disabled on every later deploy until you change the setting. CI must set `routing.isr` explicitly if a pending migration has no saved choice. Existing ISR namespaces are reused; application KV bindings are still required.
863
872
 
864
873
  For Drizzle projects, deploy performs a read-only schema drift check. If a new migration would be generated, deploy stops and tells you to run `void db generate`, review the migration, commit it yourself, and rerun `void deploy`.
865
874
 
@@ -925,7 +934,7 @@ That fallback is mainly for projects that skipped Void project setup during `voi
925
934
 
926
935
  ### `void deploy --platform cloudflare`
927
936
 
928
- Build and deploy to your Cloudflare account using the root `wrangler.jsonc`:
937
+ Build and deploy to your Cloudflare account using `void.config.ts`:
929
938
 
930
939
  ```sh
931
940
  void deploy --platform cloudflare
@@ -938,13 +947,13 @@ Void signs you in through your browser when needed and saves the selected accoun
938
947
  | ------------------------------ | -------------------------------------------------------------------------------------- |
939
948
  | `--dir`, `--spa` | Deploy static output through a small Worker and Workers Assets |
940
949
  | `--skip-build` | Reuse existing static, SPA, or SSG output; unavailable for Worker apps |
941
- | `--project` | Unavailable; the Worker and account come from the Cloudflare config |
942
- | Named environments | Unavailable; use the top-level root config |
950
+ | `--project` | Unavailable; the Worker and account come from `void.config.ts` and `void.lock.json` |
951
+ | Named environments | Unavailable; use the top-level `cloudflare` config |
943
952
  | `CLOUDFLARE_WORKERS_SUBDOMAIN` | Needed in fresh CI when versions have no preview URL; cached locally after a deploy |
944
953
  | `--require-email` | Fail instead of deploying without email when the email step cannot run, as in CI |
945
954
  | `DATABASE_URL` | Required in the deploy environment for PostgreSQL or MySQL provisioning and migrations |
946
955
 
947
- The token needs Workers Scripts: Edit, read access to bound resources, and edit permissions for products Void provisions. First-time Hyperdrive provisioning specifically needs `CLOUDFLARE_API_TOKEN` with Hyperdrive edit permission, or an existing config ID in `wrangler.jsonc`.
956
+ The token needs Workers Scripts: Edit, read access to bound resources, and edit permissions for products Void provisions. First-time Hyperdrive provisioning specifically needs `CLOUDFLARE_API_TOKEN` with Hyperdrive edit permission, or an existing config ID in `cloudflare.hyperdrive` in `void.config.ts`.
948
957
 
949
958
  Email setup needs a browser session from `void cloudflare login`, which carries the Email Routing and Email Sending scopes (a session created by older Cloudflare tooling lacks them: `void cloudflare logout`, then sign in again), or a `CLOUDFLARE_API_TOKEN` that also has Email Routing Edit and Email Sending Edit. A Global API Key pair is refused.
950
959
 
@@ -956,13 +965,13 @@ If Cloudflare Access protects readiness URLs, supply an allowed `CF_ACCESS_CLIEN
956
965
 
957
966
  Secrets and migrations are validated after the build, so a failed check may leave provisioned resources. It doesn't apply remote D1 migrations or upload the application Worker. PostgreSQL migrations are transactional; MySQL schema changes may partially apply on error.
958
967
 
959
- Provisioning reuses known resource IDs and writes newly resolved IDs into `wrangler.jsonc`, preserving comments but possibly changing indentation. Commit that file for other machines and CI. Run the first deploy from one machine at a time because provisioning locks are local. The old `--provision` flag is accepted but no longer needed.
968
+ Provisioning reuses known resource IDs and records newly resolved IDs in `void.lock.json`. Commit that file for other machines and CI. Run the first deploy from one machine at a time because provisioning locks are local. The old `--provision` flag is accepted but no longer needed.
960
969
 
961
- `.env` is local-only and isn't emitted into Worker vars. Store every schema-declared server key with `void secret put <NAME>`; Void emits required names through `secrets.required` and blocks plaintext server vars. On a new Worker, set required secrets before retrying if the initial remote check reports them missing. Custom D1 layouts are accepted only when Cloudflare's exact file set, bytes, and numeric order match the migrations Void validated. Direct deploy and operational commands use the top-level root config and reject named environments and alternate config-path overrides.
970
+ `.env` is local-only and isn't emitted into Worker vars. Store every schema-declared server key with `void secret put <NAME>`; Void emits required names through `secrets.required` and blocks plaintext server vars. On a new Worker, set required secrets before retrying if the initial remote check reports them missing. Custom D1 layouts are accepted only when Cloudflare's exact file set, bytes, and numeric order match the migrations Void validated. Direct deploy and operational commands use the top-level Cloudflare settings and reject named environments and alternate config-path overrides.
962
971
 
963
972
  Existing remote secrets are preserved. Void also preserves or creates `BETTER_AUTH_SECRET` for auth apps.
964
973
 
965
- **Email.** When the app uses email (`sendEmail()` or `email/` handlers) and `void.json` has `email.from`, the deploy reads the state of that address's zone before the build — session scopes, zone, MX records, Email Routing, subaddressing, routing rules, Email Sending, and what `wrangler.jsonc` holds — prints a checklist of what it would change in your account, and asks once (default Yes). On Yes it enables what is missing, writes `send_email: [{ "name": "SEND_EMAIL" }]`, the `__VOID_EMAIL_FROM` var and the `addresses` array into `wrangler.jsonc`, and lets wrangler create the routing rules when the activated version's triggers are synchronized; the deploy ends with the address map. A deploy with nothing left to set up asks nothing. Without `email.from` the deploy prints `add "email": { "from": "you@mail.acme.com" } to void.json` and continues without email. Non-interactive runs (CI, or stdin/stdout not a terminal) never prompt: they print the checklist plus `Run void email setup --platform cloudflare once locally, commit wrangler.jsonc, then redeploy` and deploy without email (or with the setup `wrangler.jsonc` already carries, when the binding is committed) — unless `--require-email` is passed, which fails instead. If setup has committed the exact subdomain `addresses` plan but the deploy's resolver still sees no MX records, Void preserves the plan and stops before build or upload until DNS can be verified. A deploy whose account rows all read ready reconciles the two config rows — `addresses` against the current derivation and `vars.__VOID_EMAIL_FROM` against `email.from` — with a plain file write and no prompt. See [Your own Cloudflare account](../guide/email.md#your-own-cloudflare-account) for the whole flow, including the subdomain-vs-apex rule and what stays manual.
974
+ **Email.** When the app uses email (`sendEmail()` or `email/` handlers) and `void.config.ts` has `email.from`, the deploy reads the state of that address's zone before the build — session scopes, zone, MX records, Email Routing, subaddressing, routing rules, Email Sending, and what Void's Cloudflare config holds — prints a checklist of what it would change in your account, and asks once (default Yes). On Yes it enables what is missing, writes `send_email: [{ "name": "SEND_EMAIL" }]`, the `__VOID_EMAIL_FROM` var and the `addresses` array into Void's Cloudflare config, and lets Cloudflare tooling create the routing rules when the activated version's triggers are synchronized; the deploy ends with the address map. A deploy with nothing left to set up asks nothing. Without `email.from` the deploy prints `set email.from in void.config.ts` and continues without email. Non-interactive runs (CI, or stdin/stdout not a terminal) never prompt: they print the checklist plus `Run void email setup --platform cloudflare once locally, commit void.lock.json, then redeploy` and deploy without email (or with the setup Void's Cloudflare config already carries, when the binding is committed) — unless `--require-email` is passed, which fails instead. If setup has committed the exact subdomain `addresses` plan but the deploy's resolver still sees no MX records, Void preserves the plan and stops before build or upload until DNS can be verified. A deploy whose account rows all read ready reconciles the two config rows — `addresses` against the current derivation and `vars.__VOID_EMAIL_FROM` against `email.from` — with a plain file write and no prompt. See [Your own Cloudflare account](../guide/email.md#your-own-cloudflare-account) for the whole flow, including the subdomain-vs-apex rule and what stays manual.
966
975
 
967
976
  See the [Cloudflare guide](../integrations/cloudflare.md#deploy-to-your-own-cloudflare-account) for the complete deployment sequence, first-deploy exceptions, secret precedence, and recovery behavior.
968
977
 
@@ -1017,7 +1026,7 @@ Run ad-hoc SQL against the database. Provide SQL inline or from a file. SELECT q
1017
1026
  By default, targets the local database. Pass `--remote` to run against the deployed database selected in `.void/project.json`:
1018
1027
 
1019
1028
  - **Void platform D1 projects**: routes the query through the selected platform's registered proxy using your auth token. Void Cloud's proxy is `proxy.void.cloud`; a self-hosted platform uses its own proxy URL.
1020
- - **Direct Cloudflare D1 projects**: invokes Cloudflare against the pinned D1 binding from root `wrangler.jsonc`.
1029
+ - **Direct Cloudflare D1 projects**: invokes Cloudflare against the pinned D1 binding from `void.config.ts` or `void.lock.json`.
1021
1030
  - **Hosted PostgreSQL and MySQL projects**: fetches the stored connection string from the platform and connects directly.
1022
1031
  - **Direct Cloudflare PostgreSQL and MySQL projects**: uses `DATABASE_URL` from the current shell; Cloudflare cannot return the password from Hyperdrive.
1023
1032
 
@@ -1209,7 +1218,7 @@ void gen queue emails
1209
1218
  void secret list [--project <name>]
1210
1219
  ```
1211
1220
 
1212
- List production secret names for the saved target. Secret values are never printed. Direct Cloudflare targets query the Worker named in root `wrangler.jsonc`; `--project` is hosted-only.
1221
+ List production secret names for the saved target. Secret values are never printed. Direct Cloudflare targets query the Worker named in `void.config.ts`; `--project` is hosted-only.
1213
1222
 
1214
1223
  ### `void secret put`
1215
1224
 
@@ -1495,7 +1504,7 @@ Remove a custom domain from the saved target. For Cloudflare, this removes the m
1495
1504
  void domain list [--project <name>]
1496
1505
  ```
1497
1506
 
1498
- List all custom domains. Hosted projects show active/pending state from the platform; direct Cloudflare projects list the custom-domain routes currently configured in root `wrangler.jsonc`.
1507
+ List all custom domains. Hosted projects show active/pending state from the platform; direct Cloudflare projects list the custom-domain routes currently configured in `void.config.ts`.
1499
1508
 
1500
1509
  ### `void domain status`
1501
1510
 
@@ -1509,7 +1518,7 @@ Pass `--verbose` to additionally print the raw multi-line status breakdown (DB s
1509
1518
 
1510
1519
  Project resolution for domain commands follows the same order as deploy (`--project`, `VOID_PROJECT`, linked project).
1511
1520
 
1512
- For direct Cloudflare projects, status reports whether the route is present in the root config. It does not claim to inspect remote certificate issuance; Cloudflare owns that state and exposes it in the dashboard. `--project` is hosted-only.
1521
+ For direct Cloudflare projects, status reports whether the route is present in the Void Cloudflare config. It does not claim to inspect remote certificate issuance; Cloudflare owns that state and exposes it in the dashboard. `--project` is hosted-only.
1513
1522
 
1514
1523
  ## Email
1515
1524
 
@@ -1621,7 +1630,7 @@ Disable the domain assignment and record cleanup. Zone resources used by another
1621
1630
  void email status --platform cloudflare
1622
1631
  ```
1623
1632
 
1624
- Read-only. Checks the email setup on your own Cloudflare account for the domain of `email.from` in `void.json` — session scopes, zone, MX records, Email Routing (and its subaddressing setting), Email Sending, the routing rule for every `email/` handler, and the `send_email` binding — then prints the status rows and the address map (`inbound <address> → email/<handler>`, `outbound sendEmail() from <email.from>`). Exits 1 when anything is not ready. A domain still not onboarded for Email Sending reads as set up once the `send_email` binding is committed — the binding is written only after an onboarding attempt, so that pair is how a Workers Free refusal is remembered — and the sending row says so (`not onboarded — verified destinations only; after upgrading to Workers Paid run void email setup --platform cloudflare`). Takes no `--project`: it reads the local project and your Cloudflare session, never a Void project.
1633
+ Read-only. Checks the email setup on your own Cloudflare account for the domain of `email.from` in `void.config.ts` — session scopes, zone, MX records, Email Routing (and its subaddressing setting), Email Sending, the routing rule for every `email/` handler, and the `send_email` binding — then prints the status rows and the address map (`inbound <address> → email/<handler>`, `outbound sendEmail() from <email.from>`). Exits 1 when anything is not ready. A domain still not onboarded for Email Sending reads as set up once the `send_email` binding is committed — the binding is written only after an onboarding attempt, so that pair is how a Workers Free refusal is remembered — and the sending row says so (`not onboarded — verified destinations only; after upgrading to Workers Paid run void email setup --platform cloudflare`). Takes no `--project`: it reads the local project and your Cloudflare session, never a Void project.
1625
1634
 
1626
1635
  Without `--platform cloudflare` (or with `--platform void`) the command is not available yet; on the Void platform use `void email usage` and `void email destinations`. The older `--backend cloudflare` spelling remains available as a compatibility alias on `void email status` and `void email setup`, with the same rules as `void deploy`: at most once, and never together with `--platform`.
1627
1636
 
@@ -1631,12 +1640,12 @@ Without `--platform cloudflare` (or with `--platform void`) the command is not a
1631
1640
  void email setup --platform cloudflare
1632
1641
  ```
1633
1642
 
1634
- The same setup `void deploy --platform cloudflare` offers on its first deploy, on its own — for CI, which cannot press Enter: run it locally once, commit `wrangler.jsonc`, then let CI run `void deploy --platform cloudflare --require-email`. Needs `email.from` in `void.json` and a `void cloudflare login` session (a session created by older Cloudflare tooling lacks the email scopes: `void cloudflare logout`, then sign in again) or a `CLOUDFLARE_API_TOKEN` with Email Routing Edit + Email Sending Edit — the CI credential. It runs the preflight above, prints the checklist of what will change on your account, asks once, then:
1643
+ The same setup `void deploy --platform cloudflare` offers on its first deploy, on its own — for CI, which cannot press Enter: run it locally once, commit `void.lock.json`, then let CI run `void deploy --platform cloudflare --require-email`. Needs `email.from` in `void.config.ts` and a `void cloudflare login` session (a session created by older Cloudflare tooling lacks the email scopes: `void cloudflare logout`, then sign in again) or a `CLOUDFLARE_API_TOKEN` with Email Routing Edit + Email Sending Edit — the CI credential. It runs the preflight above, prints the checklist of what will change on your account, asks once, then:
1635
1644
 
1636
1645
  1. enables Email Routing on the domain (on an apex through Void's bundled Cloudflare tooling; a subdomain through your session's bearer, borrowed for that one call and dropped),
1637
1646
  2. turns on subaddressing for the zone, so `support+anything@` reaches `support@`,
1638
1647
  3. onboards the domain for Email Sending (a Workers Free account keeps inbound and sends to verified destinations only),
1639
- 4. writes `send_email: [{ "name": "SEND_EMAIL" }]`, the derived `addresses` array, and `vars.__VOID_EMAIL_FROM` into your root `wrangler.jsonc`, comments preserved.
1648
+ 4. writes `send_email: [{ "name": "SEND_EMAIL" }]`, the derived `addresses` array, and `vars.__VOID_EMAIL_FROM` into `void.lock.json`.
1640
1649
 
1641
1650
  The routing rules themselves are created by the next `void deploy --platform cloudflare`: wrangler applies its Email Routing plan from `addresses` on deploy. `void email setup` never writes `addresses` unless routing is ready for the domain, prunes an address already routed to another worker or a forward (and says so), and skips the whole step when the existing `addresses` array holds entries it did not derive. A run that finds every row ready asks nothing and changes nothing on your account — with one exception: a domain still not onboarded for Email Sending while the `send_email` binding is committed (a remembered Workers Free refusal, see `void email status`) is offered as a retry on its own prompt, `Onboard <domain> for Email Sending? Inbound already works; onboarding needs Workers Paid.` — the step to run once after upgrading; answer No and nothing changes. The deploy never retries it. Needs an interactive terminal; exits 1 when the inbound rows are still not ready afterwards — routing not enabled, subaddressing still off, or `addresses` withheld — naming the row and saying to rerun. A Workers Free account's refused sending row is not a failure: inbound is complete, `addresses` is written, the plan hint is printed, and the binding written alongside is what makes the next deploy and `void email status` read the domain as set up. See [Your own Cloudflare account](../guide/email.md#your-own-cloudflare-account).
1642
1651
 
@@ -6,38 +6,44 @@ outline: deep
6
6
 
7
7
  ## Config File Format
8
8
 
9
- Use this page as the exact reference for `void.json`. If you are still learning how the pieces fit together, start in the guide first and come back here when you need field-by-field details.
10
-
11
- Project-level configuration lives in a `void.json` file at the project root. Most fields are optional. Cloudflare-targeted apps must pin a Workers `compatibility_date` in `worker.compatibility_date` or in a supported Cloudflare fallback file (`wrangler.jsonc` or `wrangler.json`). If no date is configured, Void writes the latest known-good date to `void.json` so future runs stay explicit and stable.
12
-
13
- ```json
14
- {
15
- "$schema": "./node_modules/void/schema.json",
16
- "sourceDir": "src",
17
- "target": "cloudflare",
18
- "auth": {
19
- "providers": ["email", "github", "google"]
9
+ Use this page as the exact reference for `void.config.ts`. If you are still learning how the pieces fit together, start in the guide first and come back here when you need field-by-field details.
10
+
11
+ Project configuration lives in a typed `void.config.ts` at the project root. Import `defineConfig` from `void/config`; all fields are optional. `void init` creates this file, and `void init`, `void deploy`, or `void migrate` converts existing `void.json` and root Wrangler JSON/JSONC files. Void saves the originals under `.void/config-migration/`. Commit `void.config.ts` and `void.lock.json` when Void creates the lock file. You can edit the typed config at any time; the lock records Cloudflare resource IDs and migration history that Void resolves for you.
12
+
13
+ ```ts
14
+ // void.config.ts
15
+ import { defineConfig } from 'void/config';
16
+
17
+ export default defineConfig({
18
+ sourceDir: 'src',
19
+ target: 'cloudflare',
20
+ auth: { providers: ['email', 'github', 'google'] },
21
+ routing: {
22
+ revalidate: { '/': 60, '*': 30 },
23
+ headers: {
24
+ '/assets/*': ['Cache-Control: public, max-age=31536000, immutable'],
25
+ '/*': ['X-Frame-Options: DENY', 'X-Content-Type-Options: nosniff'],
26
+ },
20
27
  },
21
- "routing": {
22
- "revalidate": { "/": 60, "*": 30 },
23
- "headers": {
24
- "/assets/*": ["Cache-Control: public, max-age=31536000, immutable"],
25
- "/*": ["X-Frame-Options: DENY", "X-Content-Type-Options: nosniff"]
26
- }
28
+ inference: {
29
+ bindings: { db: true, kv: false },
30
+ appType: 'spa',
31
+ outputDir: 'dist',
27
32
  },
28
- "inference": {
29
- "bindings": { "db": true, "kv": false },
30
- "appType": "spa",
31
- "outputDir": "dist"
33
+ worker: {
34
+ compatibility_date: '2025-12-01',
35
+ compatibility_flags: ['nodejs_compat'],
32
36
  },
33
- "worker": {
34
- "compatibility_date": "2025-12-01",
35
- "compatibility_flags": ["nodejs_compat"]
36
- }
37
- }
37
+ cloudflare: {
38
+ name: 'my-app',
39
+ account_id: 'your-account-id',
40
+ },
41
+ });
38
42
  ```
39
43
 
40
- Add the `$schema` field for autocomplete and validation in your editor. The schema ships with the `void` package at `node_modules/void/schema.json` and is also exposed as the `void/schema.json` package subpath.
44
+ TypeScript provides editor completion and checks. Void validates the config again when it runs, including values computed at runtime.
45
+
46
+ The shorter JSON fragments below show individual fields to place inside `defineConfig({ ... })`.
41
47
 
42
48
  ## Fields
43
49
 
@@ -53,7 +59,7 @@ When set, those conventions move under the configured directory:
53
59
  { "sourceDir": "src" }
54
60
  ```
55
61
 
56
- With that config, Void reads `src/pages`, `src/routes`, `src/db/schema.ts`, `src/db/migrations`, `src/auth.ts`, and `src/env.ts`. Project files such as `void.json`, `vite.config.ts`, `package.json`, `tsconfig.json`, `wrangler.json`, `public/`, and the local-only `.env` stay at the project root. Void does not scan both locations; if source conventions exist in both places during dev/build, remove one copy so the active source tree is unambiguous.
62
+ With that config, Void reads `src/pages`, `src/routes`, `src/db/schema.ts`, `src/db/migrations`, `src/auth.ts`, and `src/env.ts`. Project files such as `void.config.ts`, `vite.config.ts`, `package.json`, `tsconfig.json`, `public/`, and the local-only `.env` stay at the project root. Void does not scan both locations; if source conventions exist in both places during dev/build, remove one copy so the active source tree is unambiguous.
57
63
 
58
64
  ### `auth`
59
65
 
@@ -152,7 +158,7 @@ What `from` does depends on where the app runs:
152
158
 
153
159
  - **`void dev`** — becomes the default `from` of every `sendEmail()` call, captured in the dev inbox; no mail leaves the machine.
154
160
  - **`void deploy`** (managed platform) — not used: the sender is pinned to your project's own platform address, which Void fills in for you.
155
- - **`void deploy --platform cloudflare`** (your own Cloudflare account) — the address host (`mail.acme.com`) is the domain Void sets Email Routing and Email Sending up on, and the address becomes the default `from` (written into the worker as the `__VOID_EMAIL_FROM` var). The host must be a zone in the pinned Cloudflare account, or a subdomain of one; a subdomain is the usual choice, and the apex is refused when it already receives mail elsewhere. An app that uses email without `email.from` deploys without it and prints the line to add. Void never picks a zone or writes `void.json` for you. See [Your own Cloudflare account](../guide/email.md#your-own-cloudflare-account).
161
+ - **`void deploy --platform cloudflare`** (your own Cloudflare account) — the address host (`mail.acme.com`) is the domain Void sets Email Routing and Email Sending up on, and the address becomes the default `from` (written into the worker as the `__VOID_EMAIL_FROM` var). The host must be a zone in the pinned Cloudflare account, or a subdomain of one; a subdomain is the usual choice, and the apex is refused when it already receives mail elsewhere. An app that uses email without `email.from` deploys without it and prints the line to add. Void never picks a zone or writes `void.config.ts` for you. See [Your own Cloudflare account](../guide/email.md#your-own-cloudflare-account).
156
162
 
157
163
  ### `head`
158
164
 
@@ -215,7 +221,7 @@ Use remote D1/KV/R2 bindings during local development instead of local miniflare
215
221
  - Must have a linked project (`void project link`)
216
222
  - Only affects D1 (`DB`), KV (`KV`), and R2 (`STORAGE`) bindings
217
223
 
218
- You can also enable remote mode via the `VOID_REMOTE=1` environment variable without modifying `void.json`:
224
+ You can also enable remote mode via the `VOID_REMOTE=1` environment variable without modifying `void.config.ts`:
219
225
 
220
226
  ```bash
221
227
  VOID_REMOTE=1 pnpm dev
@@ -270,7 +276,7 @@ Void-managed WebSocket route files (`*.ws.ts`) are Cloudflare-only because they
270
276
 
271
277
  ### `worker`
272
278
 
273
- Curated Cloudflare Workers configuration. Cloudflare-targeted apps require an explicit `compatibility_date` here unless it is provided by a supported Cloudflare fallback file. If no date is configured, Void writes the latest known-good date here. Binding arrays such as `d1_databases`, `kv_namespaces`, and `r2_buckets` are not allowed here because Void manages bindings through inference and `inference.bindings`. If you need custom bindings with real IDs, add them to `wrangler.jsonc`; Void preserves them during deployment.
279
+ Curated Cloudflare Workers configuration. `void init` pins `compatibility_date` here. Binding arrays such as `d1_databases`, `kv_namespaces`, and `r2_buckets` go in [`cloudflare`](#cloudflare), where Void preserves custom settings and resolved IDs during deployment.
274
280
 
275
281
  | Field | Type | Description |
276
282
  | --------------------- | ---------- | -------------------------------------- |
@@ -293,7 +299,24 @@ Curated Cloudflare Workers configuration. Cloudflare-targeted apps require an ex
293
299
 
294
300
  `worker.vars` values must be strings. Root `.env` values override them during local development only. Production builds do not load `.env`, and reject any `worker.vars` name declared as a server key in `env.ts`. Use `void secret put` for production server values.
295
301
 
296
- `worker.limits.cpu_ms` caps Workers CPU time per request, in milliseconds. It must be an integer between 1 and 300000 (Cloudflare's hard maximum, 5 minutes). A deploy that requests more than your account plan's ceiling fails with an error naming both the requested value and the plan maximum. Only a rollback clamps: rolling back to a deployment whose configured limit now exceeds your plan applies the plan ceiling instead of failing. If your plan changes so that a previously valid value now exceeds the ceiling, deploys keep failing until you lower `cpu_ms` in `void.json`. On the direct Cloudflare path, the value is written into the generated `dist/ssr/wrangler.json` as `limits.cpu_ms` and enforced by Cloudflare directly. The Void plan ceiling does not apply there, but your Cloudflare account's own CPU-time allowance still does: the Workers Free plan caps CPU at 10 ms per request, and the Workers Paid plan allows up to 300000 ms. A value above what your Cloudflare account permits is constrained or rejected by Cloudflare, not by Void.
302
+ ### `cloudflare`
303
+
304
+ The complete Cloudflare Worker configuration for direct Cloudflare builds and deployment. Put custom bindings, `name`, `account_id`, routes, services, vars, migrations, and any other Cloudflare fields here. Void passes these fields through to the generated Cloudflare build configuration. Settings you edit here take precedence over values Void previously recorded in `void.lock.json`.
305
+
306
+ ```ts
307
+ // Inside defineConfig({ ... })
308
+ cloudflare: {
309
+ name: 'my-app',
310
+ d1_databases: [{ binding: 'ANALYTICS', database_name: 'analytics', database_id: '...' }],
311
+ vars: { PUBLIC_API_BASE: 'https://api.example.com' },
312
+ },
313
+ ```
314
+
315
+ Void writes a generated Cloudflare config for its tooling and records provisioned resource IDs and append-only migration history in `void.lock.json`. Commit the lock when it changes. Root `wrangler.jsonc` and `wrangler.json` are migrated on `void init` or `void deploy`; Void keeps backup copies under `.void/config-migration/`.
316
+
317
+ If you need to remove a value that Void previously generated, remove it from the `resolved` object in `void.lock.json`. Void refreshes the generated Cloudflare file on the next command. Put ongoing custom settings in `cloudflare` in `void.config.ts`.
318
+
319
+ `worker.limits.cpu_ms` caps Workers CPU time per request, in milliseconds. It must be an integer between 1 and 300000 (Cloudflare's hard maximum, 5 minutes). A deploy that requests more than your account plan's ceiling fails with an error naming both the requested value and the plan maximum. Only a rollback clamps: rolling back to a deployment whose configured limit now exceeds your plan applies the plan ceiling instead of failing. If your plan changes so that a previously valid value now exceeds the ceiling, deploys keep failing until you lower `cpu_ms` in `void.config.ts`. On the direct Cloudflare path, the value is written into the generated `dist/ssr/wrangler.json` as `limits.cpu_ms` and enforced by Cloudflare directly. The Void plan ceiling does not apply there, but your Cloudflare account's own CPU-time allowance still does: the Workers Free plan caps CPU at 10 ms per request, and the Workers Paid plan allows up to 300000 ms. A value above what your Cloudflare account permits is constrained or rejected by Cloudflare, not by Void.
297
320
 
298
321
  ```json
299
322
  {
@@ -472,7 +495,7 @@ Each binding accepts `true` (use default name), `false` (disable), or a string (
472
495
 
473
496
  Custom resource binding names flow through deploy manifests, Cloudflare config generation, remote binding proxying, internal migrations, and generated runtime helpers such as `void/db`, `void/kv`, and `void/storage`. Custom AI names apply to generated Cloudflare configuration and `void/ai` runtime resolution for direct Cloudflare builds; managed Workers AI continues to use Void's service proxy.
474
497
 
475
- `email` is a feature switch rather than a Cloudflare binding, so it has no binding name or type. On the platform, outbound mail is sent through the Void proxy, which owns the `send_email` binding — none is written into your worker; on your own Cloudflare account, `void deploy --platform cloudflare` writes a `send_email` binding named `SEND_EMAIL` into `wrangler.jsonc` itself once email is set up (see [`email.from`](#email)). Set it to `true` to turn the [email integration](../guide/email.md) on — which registers the `void dev` inbox — even when no scanned file imports `void/email`, or `false` to turn it off.
498
+ `email` is a feature switch rather than a Cloudflare binding, so it has no binding name or type. On the platform, outbound mail is sent through the Void proxy, which owns the `send_email` binding — none is written into your worker; on your own Cloudflare account, `void deploy --platform cloudflare` records a `send_email` binding named `SEND_EMAIL` in `void.lock.json` once email is set up (see [`email.from`](#email)). Set it to `true` to turn the [email integration](../guide/email.md) on — which registers the `void dev` inbox — even when no scanned file imports `void/email`, or `false` to turn it off.
476
499
 
477
500
  #### `inference.build`
478
501
 
@@ -14,7 +14,7 @@ const items = [
14
14
  { name: "public/", description: "Static assets (served as-is)", link: "#public" },
15
15
  { name: ".void/", description: "Auto-generated (gitignored)", link: "#void" },
16
16
  { name: "vite.config.ts", description: "Vite config with voidPlugin()", link: "#config-files" },
17
- { name: "void.json", description: "Void project config (optional)", link: "#config-files" },
17
+ { name: "void.config.ts", description: "Void project config (optional)", link: "#config-files" },
18
18
  { name: ".env", description: "Environment variables", link: "#config-files" },
19
19
  { name: "package.json" },
20
20
  { name: "tsconfig.json" },
@@ -167,7 +167,7 @@ Generate or refresh it with `void prepare`, or let `vite dev` / `vite build` pop
167
167
  | File | Purpose |
168
168
  | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
169
169
  | `vite.config.ts` | Vite configuration. Must include `voidPlugin()`. |
170
- | `void.json` | Optional Void config for [routing](/reference/config#routing), [inference](/reference/config#inference), and [worker settings](/reference/config#worker) |
170
+ | `void.config.ts` | Optional Void config for [routing](/reference/config#routing), [inference](/reference/config#inference), and [worker settings](/reference/config#worker) |
171
171
  | `tsconfig.json` | TypeScript config. Extend `.void/tsconfig.json` for auto-generated types; run `void init --tsconfig` when an existing config already uses `extends`. |
172
172
  | `.env` | Local development values only (gitignored; never deployed) |
173
173
  | `env.ts` | Checked-in env names, types, defaults, and requiredness |