void 0.23.0 → 0.25.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 (169) hide show
  1. package/AGENTS_TEMPLATE.md +1 -1
  2. package/README.md +19 -106
  3. package/dist/{account-cmd-C84Ee8cO.mjs → account-cmd-DcR1ywt8.mjs} +5 -5
  4. package/dist/{auth-CSkdO2Bb.mjs → auth-7wuZ5ob8.mjs} +22 -49
  5. package/dist/auth-CdgZ9uag.mjs +2 -0
  6. package/dist/{auth-link-CioEg6uY.mjs → auth-link-Z6E5DYvM.mjs} +5 -6
  7. package/dist/{auth-router-BsR981d4.mjs → auth-router-BdM4avI8.mjs} +7 -7
  8. package/dist/{build-cmd-LzvNJORH.mjs → build-cmd-CEE7D-hM.mjs} +7 -8
  9. package/dist/{cache-C4MvnrMH.mjs → cache-TcZnBLtH.mjs} +6 -7
  10. package/dist/{cancel-deploy-abUxpP2n.mjs → cancel-deploy-CYoZmcmR.mjs} +4 -6
  11. package/dist/{cf-access-P0iZnu0q.mjs → cf-access-AHKBzmuu.mjs} +4 -48
  12. package/dist/{cf-access-DRsQRe6k.mjs → cf-access-TWNzXltp.mjs} +3 -11
  13. package/dist/cf-build-output-ChY6-XWP.mjs +2 -0
  14. package/dist/cli/cli.mjs +49 -46
  15. package/dist/cli/cloudflare-operation-process.mjs +16 -7
  16. package/dist/cli/env-schema-probe.mjs +3 -3
  17. package/dist/client-B4Me-9HE.mjs +2 -0
  18. package/dist/{client-RV8NVeB8.mjs → client-RsPo8wsP.mjs} +129 -33
  19. package/dist/{cloudflare-cmd-BcrVyTmJ.mjs → cloudflare-cmd-bhwCxAN6.mjs} +2 -2
  20. package/dist/{cloudflare-connect-B8uPZ4nx.mjs → cloudflare-connect-CuhRgk3k.mjs} +2 -2
  21. package/dist/{cloudflare-operations-AiWashgg.mjs → cloudflare-operations-BhbK6yTq.mjs} +1 -1
  22. package/dist/{cloudflare-operations-fxHb-byx.mjs → cloudflare-operations-CjaV4lZi.mjs} +2 -2
  23. package/dist/{connect-Bd4kJd9U.mjs → connect-DCvUmPXY.mjs} +13 -10
  24. package/dist/{create-project-Boczwj5r.mjs → create-project-C734I-Mu.mjs} +1 -1
  25. package/dist/{create-project-bMf6ffLZ.mjs → create-project-eAPgYq35.mjs} +13 -13
  26. package/dist/{db-8uG64XLl.mjs → db-C07GEdKF.mjs} +27 -30
  27. package/dist/{delete-NvbiyeJf.mjs → delete-pKMVsrpJ.mjs} +5 -6
  28. package/dist/deploy-BDu1vhSH.mjs +2 -0
  29. package/dist/{deploy-DzAIwqNU.mjs → deploy-DfsAe-T0.mjs} +9567 -9215
  30. package/dist/{dev-inbox-P0u4tM8Y.mjs → dev-inbox-D64ZKUod.mjs} +5 -6
  31. package/dist/{domain-y5Tvydvo.mjs → domain-D3uA9ize.mjs} +8 -8
  32. package/dist/{email-B3umsW75.mjs → email-z3o2cwjH.mjs} +8 -8
  33. package/dist/{env-BS6qYHDb.mjs → env-3Q8-_2IH.mjs} +7 -9
  34. package/dist/{env-types-C2_bIk_b.mjs → env-types-D5kds_OZ.mjs} +1 -1
  35. package/dist/{env-validation-DbTg7-ar.mjs → env-validation-cZBvGWaP.mjs} +1 -1
  36. package/dist/{env-validation-BPn7vk-V.mjs → env-validation-vBSQ8gw5.mjs} +3 -3
  37. package/dist/gen-ById9r2j.mjs +2 -0
  38. package/dist/{gen-B580--vC.mjs → gen-NjwoG9FK.mjs} +2 -4
  39. package/dist/{github-cmd-v45BdfKX.mjs → github-cmd-DquUq-b1.mjs} +15 -24
  40. package/dist/{headers-DWi2IXWx.mjs → headers-2rKda9Y6.mjs} +1 -1
  41. package/dist/help-DPGBwomV.mjs +2 -0
  42. package/dist/{help-daGKjXGk.mjs → help-DRZXC4fj.mjs} +8 -4
  43. package/dist/{inbound-aVHEUhKo.mjs → inbound-fRkqcXaC.mjs} +1 -1
  44. package/dist/index.d.mts +18 -14
  45. package/dist/index.mjs +2176 -2110
  46. package/dist/{info-B97bTX9N.mjs → info-BmA3_IFZ.mjs} +1 -3
  47. package/dist/{init-Bvy7zrBo.mjs → init-DT7yuuyl.mjs} +28 -27
  48. package/dist/{link-CDqqCjFl.mjs → link-CXOlqh2F.mjs} +6 -7
  49. package/dist/{list-CZj0dzKY.mjs → list-eEWVJEPn.mjs} +8 -9
  50. package/dist/{local-d1-2CMnpuW_.mjs → local-d1-Df4XpwhW.mjs} +1 -1
  51. package/dist/log-vqY3pqwI.mjs +29 -0
  52. package/dist/login-C98-sw79.mjs +2 -0
  53. package/dist/{login-UZKFM_u7.mjs → login-pWQHYVu2.mjs} +12 -10
  54. package/dist/{logs-CUZ6t9t3.mjs → logs-DnxVX7TR.mjs} +11 -13
  55. package/dist/migrate-CEu2X5DB.mjs +2 -0
  56. package/dist/{migrate-DHul7PRV.mjs → migrate-CV1on-yJ.mjs} +2 -4
  57. package/dist/{operator-args-CLgKGlwU.mjs → operator-args-CAVcmwUt.mjs} +12 -5
  58. package/dist/{operator-auth-8KnOVXVd.mjs → operator-auth-CkmTE3rt.mjs} +2 -2
  59. package/dist/{operator-client-DUwumHpQ.mjs → operator-client-LmwjxT6q.mjs} +3 -3
  60. package/dist/{operator-cmd-DBA6dl0m.mjs → operator-cmd-d-IEKgNk.mjs} +6 -6
  61. package/dist/{output-Dm_A4Tbv.mjs → output-BBsUwdyT.mjs} +22 -14
  62. package/dist/pages/client.d.mts +3 -0
  63. package/dist/pages/client.mjs +120 -29
  64. package/dist/pages/index.mjs +1 -1
  65. package/dist/{platform-args-BJdRtlLq.mjs → platform-args-Bzf8JPc2.mjs} +11 -3
  66. package/dist/platform-args-Cq6EjQro.mjs +2 -0
  67. package/dist/{platform-auth-config-B56E9YP1.mjs → platform-auth-config-0V0lA3pF.mjs} +7 -7
  68. package/dist/{platform-auth-protection-BDWO_aER.mjs → platform-auth-protection-DFeJ-JkK.mjs} +9 -9
  69. package/dist/{platform-auth-recovery-1gg4CSRe.mjs → platform-auth-recovery-ICy4muq6.mjs} +7 -7
  70. package/dist/{platform-cmd-Bt-1w6pY.mjs → platform-cmd-BPySFOew.mjs} +1 -1
  71. package/dist/{platform-cmd-DMcQStSc.mjs → platform-cmd-D7vSWMvV.mjs} +38 -28
  72. package/dist/platform-discovery-DDDUvnqp.mjs +27 -0
  73. package/dist/{platform-domain-BNkcz0OB.mjs → platform-domain-CUdY064e.mjs} +5 -5
  74. package/dist/{platform-lifecycle-BE6C_jxh.mjs → platform-lifecycle-BaUdTRPU.mjs} +1 -1
  75. package/dist/{platform-lifecycle-9OyBALhH.mjs → platform-lifecycle-Dm09JNkn.mjs} +4404 -3297
  76. package/dist/{platform-management-CjwLVQwN.mjs → platform-management-BSEc_ZeG.mjs} +48 -11
  77. package/dist/platform-management-Bp6aoH2C.mjs +2 -0
  78. package/dist/{platform-plans-config-BNGKGr4P.mjs → platform-plans-config-B0pOVQyW.mjs} +3 -3
  79. package/dist/{platform-recovery-D6KSpuFm.mjs → platform-recovery-WOZ95Uze.mjs} +4 -4
  80. package/dist/{platform-registry-QBa4DK32.mjs → platform-registry-KfNEF84O.mjs} +3 -3
  81. package/dist/{prepare-B5Mkic5u.mjs → prepare-39EvOhI6.mjs} +2 -4
  82. package/dist/prepare-CnjcTV2s.mjs +2 -0
  83. package/dist/{prepare-DOsL0CC9.mjs → prepare-DnaKBi--.mjs} +1 -1
  84. package/dist/{project-C0Fqu05O.mjs → project-BkbfDs0V.mjs} +15 -82
  85. package/dist/project-IOjBU8R6.mjs +2 -0
  86. package/dist/{project-cmd-CNzrqvBv.mjs → project-cmd-Bs5A392E.mjs} +21 -22
  87. package/dist/{project-team-DQOWPfQT.mjs → project-team-ohAWWaew.mjs} +8 -9
  88. package/dist/{project-token-CTDYU0Cc.mjs → project-token-CP01Jna6.mjs} +6 -9
  89. package/dist/{project-zero-trust-BNAkW-_0.mjs → project-zero-trust-BzkVgx35.mjs} +5 -6
  90. package/dist/prompts-6OSVA7DJ.mjs +2087 -0
  91. package/dist/prompts-ZAuJlyCj.mjs +2 -0
  92. package/dist/{provision-C4ORE7G7.mjs → provision-BEv0k-qz.mjs} +1 -1
  93. package/dist/{provision-CJFgTZY8.mjs → provision-Btj1jppf.mjs} +5 -7
  94. package/dist/{requests-MhxYnau8.mjs → requests-B3PBuGlX.mjs} +5 -6
  95. package/dist/{rollback-CJ6iSDoU.mjs → rollback-DDub9GsO.mjs} +9 -10
  96. package/dist/runtime/ai.mjs +3 -5
  97. package/dist/runtime/email/testing.mjs +2 -2
  98. package/dist/runtime/email.mjs +36 -18
  99. package/dist/runtime/remote/index.mjs +2 -2
  100. package/dist/runtime/routing.mjs +1 -1
  101. package/dist/{secret-Dli5fP0B.mjs → secret-3c72lY1U.mjs} +15 -16
  102. package/dist/{skills-D1II1Juz.mjs → skills-BPQUGClu.mjs} +1 -1
  103. package/dist/{subcommand-prompt-CY1C4fvl.mjs → subcommand-prompt-Dhom39bd.mjs} +40 -32
  104. package/dist/sveltekit.d.mts +1 -1
  105. package/dist/sveltekit.mjs +4 -9
  106. package/dist/{wrangler-7K-bW_DL.mjs → wrangler-DhUerFkW.mjs} +10 -15
  107. package/package.json +22 -23
  108. package/sandbox.Dockerfile +1 -1
  109. package/skills/void/SKILL.md +6 -1
  110. package/skills/void/docs/guide/ai.md +24 -86
  111. package/skills/void/docs/guide/auth.md +0 -2
  112. package/skills/void/docs/guide/database/d1.md +7 -7
  113. package/skills/void/docs/guide/deployment.md +58 -102
  114. package/skills/void/docs/guide/edge/headers.md +1 -1
  115. package/skills/void/docs/guide/email/domains.md +5 -1
  116. package/skills/void/docs/guide/email/sending.md +1 -1
  117. package/skills/void/docs/guide/env-vars.md +1 -5
  118. package/skills/void/docs/guide/index.md +19 -18
  119. package/skills/void/docs/guide/kv.md +0 -2
  120. package/skills/void/docs/guide/pages-routing/actions-and-forms.md +49 -47
  121. package/skills/void/docs/guide/pages-routing/overview.md +2 -2
  122. package/skills/void/docs/guide/platform/administration/email.md +0 -2
  123. package/skills/void/docs/guide/platform/administration/operations.md +11 -22
  124. package/skills/void/docs/guide/platform/administration/plans.md +1 -5
  125. package/skills/void/docs/guide/platform/administration/zero-trust.md +24 -9
  126. package/skills/void/docs/guide/platform/development/schema-ci.md +7 -1
  127. package/skills/void/docs/guide/platform/installation/ci.md +1 -1
  128. package/skills/void/docs/guide/platform/installation/credentials.md +10 -3
  129. package/skills/void/docs/guide/platform/installation/domains.md +8 -3
  130. package/skills/void/docs/guide/platform/installation/first-deployment.md +2 -2
  131. package/skills/void/docs/guide/platform/installation/maintenance.md +37 -5
  132. package/skills/void/docs/guide/platform/installation/prerequisites.md +87 -14
  133. package/skills/void/docs/guide/platform/installation/setup.md +80 -10
  134. package/skills/void/docs/guide/quickstart.md +37 -80
  135. package/skills/void/docs/guide/remote-dev.md +1 -1
  136. package/skills/void/docs/guide/sandboxes.md +36 -46
  137. package/skills/void/docs/guide/self-hosted-platform.md +20 -0
  138. package/skills/void/docs/guide/websockets.md +0 -2
  139. package/skills/void/docs/integrations/frameworks/overview.md +2 -2
  140. package/skills/void/docs/integrations/frameworks/sveltekit.md +40 -25
  141. package/skills/void/docs/integrations/nodejs-bun-deno.md +7 -2
  142. package/skills/void/docs/reference/api/resources.md +27 -0
  143. package/skills/void/docs/reference/api.md +1 -1
  144. package/skills/void/docs/reference/cli/auth.md +4 -3
  145. package/skills/void/docs/reference/cli/database.md +1 -1
  146. package/skills/void/docs/reference/cli/deploy.md +21 -1
  147. package/skills/void/docs/reference/cli/platform-installation.md +42 -27
  148. package/skills/void/docs/reference/cli/platform-operations.md +4 -8
  149. package/skills/void/docs/reference/cli/platform-zero-trust.md +14 -0
  150. package/skills/void/docs/reference/cli/platform.md +5 -0
  151. package/skills/void/docs/reference/config.md +1 -1
  152. package/skills/void/docs/reference/resource-inference.md +11 -8
  153. package/dist/auth-CCjt0hcq.mjs +0 -2
  154. package/dist/cf-build-output-_0HNWysu.mjs +0 -2
  155. package/dist/client-Cu7jWiF1.mjs +0 -2
  156. package/dist/deploy-bjXdFCtn.mjs +0 -2
  157. package/dist/dist-BuDuKZJv.mjs +0 -2
  158. package/dist/dist-CTBk70IR.mjs +0 -1310
  159. package/dist/gen-BVaUUumi.mjs +0 -2
  160. package/dist/help-DofyZuY7.mjs +0 -2
  161. package/dist/log-ChfPKsVd.mjs +0 -26
  162. package/dist/login-DYt_An22.mjs +0 -2
  163. package/dist/migrate-8_2u55MD.mjs +0 -2
  164. package/dist/platform-args-D3RXyR6h.mjs +0 -2
  165. package/dist/platform-management-CnyTdcWX.mjs +0 -2
  166. package/dist/prepare-cgvDMtSb.mjs +0 -2
  167. package/dist/project-BuUwfj6f.mjs +0 -2
  168. package/skills/void/docs/guide/env-migration.md +0 -109
  169. package/dist/{cf-build-output-BPqOT964.mjs → cf-build-output-U8o1Gl6X.mjs} +1 -1
@@ -4,65 +4,51 @@ outline: deep
4
4
 
5
5
  # Quickstart
6
6
 
7
- Create a Void app, run it locally, and deploy it. You can also [add Void to an existing Vite app](#adding-to-an-existing-vite-app). Use Node.js 24.21.0 or later.
7
+ Create a Void app, run it locally, and deploy it. You can also [add Void to an existing Vite app](#adding-to-an-existing-vite-app).
8
8
 
9
- ## Start in an Empty Directory
9
+ ## Create an app
10
10
 
11
- Install Void in an empty project directory:
11
+ In an empty directory, install Void and run setup:
12
12
 
13
13
  ::: code-group
14
14
 
15
15
  ```sh [npm]
16
16
  npm install -D void
17
+ npx void init
17
18
  ```
18
19
 
19
20
  ```sh [pnpm]
20
21
  pnpm add -D void
22
+ pnpm void init
21
23
  ```
22
24
 
23
25
  ```sh [yarn]
24
26
  yarn add -D void
27
+ yarn void init
25
28
  ```
26
29
 
27
30
  ```sh [bun]
28
31
  bun add -D void
32
+ bunx void init
29
33
  ```
30
34
 
31
35
  :::
32
36
 
33
- Run setup:
34
-
35
- ::: code-group
36
-
37
- ```sh [npm]
38
- npx void init
39
- ```
37
+ Choose your UI framework, a starter, and a deployment target. Vite+ is the default build tool. D1 is a good first database: it runs locally without a separate database server. Choose Cloudflare to deploy to your own account, or skip deployment setup for now.
40
38
 
41
- ```sh [pnpm]
42
- pnpm void init
43
- ```
39
+ With pnpm, `pnpm create void my-app` also creates the project directory and configures native build permissions for you.
44
40
 
45
- ```sh [yarn]
46
- yarn void init
47
- ```
41
+ ## Run locally
48
42
 
49
- ```sh [bun]
50
- bunx void init
43
+ ```sh
44
+ npm run dev
51
45
  ```
52
46
 
53
- :::
54
-
55
- Void asks you to choose Vite+ or Vite, a UI framework, a starter, and a deployment target. Vite+ is the default. D1 needs no local database server; choose PostgreSQL or MySQL if you use an external database. You can skip deployment setup and decide later.
56
-
57
- With pnpm, you can start with `pnpm create void my-app`. It configures native build permissions before installing Void.
58
-
59
- The examples below use `void` for brevity. Outside package scripts, run the local binary with `npx void`, `pnpm void`, `yarn void`, or `bunx void`. Keep Void installed in the project so the CLI and app use the same version.
47
+ Open `http://localhost:5173`. In a Pages starter, `pages/` contains your UI and companion `.server.ts` files contain its server loaders and actions. Loaders return data to page components as typed props.
60
48
 
61
- ## Run and deploy
49
+ ## Call a server route
62
50
 
63
- ### 1. Edit the generated API route
64
-
65
- Database-backed starters include `routes/api/hello.ts`. You can edit its `GET` handler, or create this file if you started with Static Pages:
51
+ Edit `routes/api/hello.ts`, or create it if your starter doesn't include it:
66
52
 
67
53
  ```ts
68
54
  import { defineHandler } from 'void';
@@ -72,75 +58,46 @@ export const GET = defineHandler(() => {
72
58
  });
73
59
  ```
74
60
 
75
- ### 2. Run locally
76
-
77
- ```sh
78
- npm run dev
79
- ```
61
+ Visit `http://localhost:5173/api/hello` to see the response. From your client code, call it with Void's typed fetch:
80
62
 
81
- Then visit:
63
+ ```ts
64
+ import { fetch } from 'void/client';
82
65
 
83
- - App: `http://localhost:5173`
84
- - API route: `http://localhost:5173/api/hello`
66
+ const { message } = await fetch('/api/hello');
67
+ ```
85
68
 
86
- ### 3. Deploy
69
+ The file path defines the URL, and the handler defines the response type. Change `message` in the handler and TypeScript checks the client against the new shape.
87
70
 
88
- If you chose a deployment target during setup, run:
71
+ Database starters also include `db/schema.ts`. Its Drizzle schema defines your tables and query types; Void runs a local database and provisions one when you deploy.
89
72
 
90
- ```sh
91
- void deploy
92
- ```
73
+ ## Deploy
93
74
 
94
- If you skipped deployment setup, select your Cloudflare account for the first deploy:
75
+ If you chose a target during setup:
95
76
 
96
77
  ```sh
97
- void deploy --platform cloudflare
78
+ npx void deploy
98
79
  ```
99
80
 
100
- Void opens your browser to sign in when needed. To use your team's platform, connect using the API URL from your administrator, then link a project and deploy:
81
+ If you skipped setup, select your Cloudflare account:
101
82
 
102
83
  ```sh
103
- void connect https://platform.example.com
104
- void project link
105
- void deploy
84
+ npx void deploy --platform cloudflare
106
85
  ```
107
86
 
108
- Void builds the app, provisions its resources, applies pending migrations, and prints the deployed URL. If a production secret is missing, [set it](./env-vars.md) and deploy again. Later deploys use the saved target.
109
-
110
- See [Deployment](./deployment.md) for CI setup and rollback.
111
-
112
- ## Using with Coding Agents
113
-
114
- `void init` detects your coding agent and installs its instructions and skills. If no agent is detected, use the bundled docs linked in `AGENTS.md`. In agents that support it, load the `/void` skill and describe the app you want to build. See [Coding Agents](../integrations/agents) for setup details.
87
+ Void opens your browser to sign in when needed, builds the app, provisions resources, applies migrations, and prints the deployed URL. Later deploys use the saved target. See [Deployment](./deployment.md) for team platforms, CI, and rollback.
115
88
 
116
- ## Meta Frameworks
89
+ ## Adding to an existing Vite app
117
90
 
118
- Use Void's [Pages routing](./pages-routing/overview) or keep a framework such as TanStack Start, React Router, or SvelteKit. Follow the [framework guides](../integrations/frameworks/overview) for setup.
91
+ Install Void and run `void init` with your package manager as shown [above](#create-an-app). Setup adds `voidPlugin()` to your Vite config and creates the remaining project files. If the config needs a manual edit, the CLI shows the change to make.
119
92
 
120
- ## Adding to an Existing Vite App
93
+ For a meta framework such as TanStack Start, React Router, or SvelteKit, follow its [integration guide](../integrations/frameworks/overview.md).
121
94
 
122
- Install Void using the package manager command [above](#start-in-an-empty-directory).
123
-
124
- Enable the plugin in `vite.config.ts`:
125
-
126
- ```ts
127
- import { defineConfig } from 'vite';
128
- import { voidPlugin } from 'void';
129
-
130
- export default defineConfig({
131
- plugins: [voidPlugin()],
132
- });
133
- ```
134
-
135
- Then run `void init` with your package manager to configure the remaining project files.
95
+ ## Next steps
136
96
 
137
- ## Troubleshooting pnpm installs
97
+ - [Pages Routing](./pages-routing/overview.md): loaders, layouts, and forms
98
+ - [Server Routing](./server-routing.md): params, middleware, and validation
99
+ - [Database](./database.md): queries and migrations
100
+ - [Environment Variables](./env-vars.md): local values and production secrets
101
+ - [Coding Agents](../integrations/agents.md): use Void's bundled docs and skills
138
102
 
139
103
  If a manual pnpm install reports blocked build scripts, run `pnpm approve-builds` for `esbuild`, `sharp`, and `workerd`. Set `better-sqlite3: false` in `pnpm-workspace.yaml`'s `allowBuilds`; Void uses its bundled binaries.
140
-
141
- ## Next steps
142
-
143
- - To understand what kind of apps are supported: [Supported App Types](./app-types)
144
- - [Server Routing](./server-routing): dynamic params, middleware, and validation
145
- - [Database](./database): queries, migrations, and generated types
146
- - [Type Safety](./type-safety): end-to-end typed fetch client
@@ -49,7 +49,7 @@ AI requests use your platform’s account and allowance in both local and remote
49
49
  When the dev server starts with remote mode active, it prints:
50
50
 
51
51
  ```
52
- ⚡ Remote bindings active (my-project.void.app)
52
+ ⚡ Remote bindings active (my-project.apps.example.com)
53
53
  DB → remote D1
54
54
  KV → remote KV
55
55
  STORAGE → remote R2
@@ -6,6 +6,12 @@ outline: deep
6
6
 
7
7
  Use a Cloudflare Sandbox to run commands, work with files, and connect to servers from server code. Each Sandbox ID selects an isolated container.
8
8
 
9
+ ## Requirements
10
+
11
+ Cloudflare deployments require [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans) and Containers access. Run Docker for local development and direct deployments that build an image. A team platform's runtime token needs Account / Containers: Edit and Account / Cloudchamber: Edit.
12
+
13
+ ## Run a command
14
+
9
15
  ```ts
10
16
  import { defineHandler } from 'void';
11
17
  import { getSandbox } from 'void/sandbox';
@@ -23,46 +29,7 @@ export const POST = defineHandler(async (c) => {
23
29
  });
24
30
  ```
25
31
 
26
- Importing from `void/sandbox` enables the required resources. Local development, native Cloudflare deployments, and Void Platform share the same runtime API.
27
-
28
- ## Configuration
29
-
30
- The default environment provides Node.js 24 on Debian Trixie. Local development and native deploys need Docker running. Managed platform deploys use Cloudflare's managed Node.js image.
31
-
32
- Use `void.config.ts` when you need a custom image or container size:
33
-
34
- ```ts
35
- import { defineConfig } from 'void/config';
36
-
37
- export default defineConfig({
38
- sandbox: {
39
- image: './Dockerfile.sandbox',
40
- platformImage: 'registry.cloudflare.com/<account-id>/sandbox@sha256:<digest>',
41
- instanceType: 'standard-1',
42
- },
43
- });
44
- ```
45
-
46
- | Field | Default | Description |
47
- | ------------------- | --------------------------- | -------------------------------------------------------------------- |
48
- | `binding` | `SANDBOX` | Binding name for local and native Cloudflare use |
49
- | `className` | `SandboxV1` | Durable Object class for local and native Cloudflare use |
50
- | `containerName` | `void-sandbox-v1` | Cloudflare container application name |
51
- | `image` | Packaged Node.js Dockerfile | Dockerfile or digest-pinned Cloudflare registry image for native use |
52
- | `imageBuildContext` | Directory of `image` | Docker build context |
53
- | `platformImage` | `cloudflare/debian-trixie` | Image used by managed platform deploys |
54
- | `instanceType` | `lite` | `lite`, `standard-1`, `standard-2`, `standard-3`, or `standard-4` |
55
-
56
- Custom images must include the helper matching Void's installed Sandbox SDK version. The SDK image supplies this binary, but is not a runnable environment itself:
57
-
58
- ```dockerfile
59
- FROM node:24.21.0-trixie-slim
60
- COPY --from=docker.io/cloudflare/sandbox:1.0.0 /usr/local/bin/sandbox-shim /usr/local/bin/sandbox-shim
61
- WORKDIR /workspace
62
- CMD ["sleep", "infinity"]
63
- ```
64
-
65
- For a managed platform, push your custom image to that platform account's Cloudflare registry and set `platformImage` to its digest-pinned reference. If `image` is already a Cloudflare registry reference, it also becomes the default `platformImage`. External registries and mutable tags are not supported. See [Cloudflare's image management guide](https://developers.cloudflare.com/containers/guides/image-management/#push-images-to-the-cloudflare-registry).
32
+ Importing from `void/sandbox` enables the required resources. Local development, direct Cloudflare deployments, and team platforms share the same runtime API.
66
33
 
67
34
  ## Runtime API
68
35
 
@@ -109,14 +76,37 @@ The `limited` handler receives `resource: 'sandbox'`, a `reason` of `concurrency
109
76
 
110
77
  Files, running processes, and listening servers last only as long as the container. It can stop after inactivity, crash, or restart. Save anything you need to keep in your database, KV, or R2. Deleting a project on a Void platform removes both its Durable Objects and containers.
111
78
 
112
- ## Deployment
79
+ ## Configuration
113
80
 
114
- Sandboxes require [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans) and Containers access. A managed platform's runtime token needs Account / Containers: Edit and Account / Cloudchamber: Edit.
81
+ The default environment provides Node.js 24 on Debian Trixie. Managed platform deploys use Cloudflare's managed Node.js image.
115
82
 
116
- `void deploy --platform cloudflare` builds native images and deploys the Sandbox alongside the application. `void deploy` on a connected Void Platform applies the platform's Sandbox concurrency and runtime limits. Upgrade the platform before deploying an application built with this Sandbox API.
83
+ Use `void.config.ts` when you need a custom image or container size:
117
84
 
118
- ## Moving from Sandbox SDK 0.x
85
+ ```ts
86
+ import { defineConfig } from 'void/config';
119
87
 
120
- Update string commands to argument arrays, move file calls under `.files`, and consume process output and file responses as shown above. Replace `sleepAfter` and `keepAlive` with `inactivityTimeoutMs`; remove `maxInstances` from configuration. The old `Sandbox` export, sessions, code interpreter, process-list helpers, and preview-URL helpers are no longer part of this API.
88
+ export default defineConfig({
89
+ sandbox: {
90
+ image: './Dockerfile.sandbox',
91
+ platformImage: 'registry.cloudflare.com/<account-id>/sandbox@sha256:<digest>',
92
+ instanceType: 'standard-1',
93
+ },
94
+ });
95
+ ```
96
+
97
+ See the [configuration reference](../reference/config.md#sandbox) for binding names, image settings, and container sizes.
98
+
99
+ Custom images must include the helper matching Void's installed Sandbox SDK version. The SDK image supplies this binary, but is not a runnable environment itself:
100
+
101
+ ```dockerfile
102
+ FROM node:24.21.0-trixie-slim
103
+ COPY --from=docker.io/cloudflare/sandbox:1.0.0 /usr/local/bin/sandbox-shim /usr/local/bin/sandbox-shim
104
+ WORKDIR /workspace
105
+ CMD ["sleep", "infinity"]
106
+ ```
107
+
108
+ For a managed platform, push your custom image to that platform account's Cloudflare registry and set `platformImage` to its digest-pinned reference. If `image` is already a Cloudflare registry reference, it also becomes the default `platformImage`. External registries and mutable tags are not supported. See [Cloudflare's image management guide](https://developers.cloudflare.com/containers/guides/image-management/#push-images-to-the-cloudflare-registry).
109
+
110
+ ## Deployment
121
111
 
122
- Existing native 0.x Sandboxes need a new Worker configuration and namespace. Back up container files and any Durable Object data, choose a fresh `worker.name`, and remove the old Sandbox bindings, containers, and migrations from that new configuration before deploying. The new default class is `SandboxV1`; existing state does not transfer automatically. Retain the old Worker until you have validated the replacement and restored your data, then clean up its resources. See [Cloudflare's scheduling-policy migration guide](https://developers.cloudflare.com/containers/guides/migrate-to-durable-object-scheduling-policy/).
112
+ `void deploy --platform cloudflare` builds native images and deploys the Sandbox alongside the application. `void deploy` on a connected Void Platform applies the platform's Sandbox concurrency and runtime limits.
@@ -12,6 +12,26 @@ The core platform supports GitHub, Google, generic OIDC, and Cloudflare Access l
12
12
 
13
13
  The core installation includes managed Sandboxes and an email gateway; email is enabled when you configure a shared mail domain and zone. The user dashboard, GitHub builds and webhooks, build Containers, and custom project domains aren't part of the core installation. Source-built platforms that add the optional GitHub services should follow the [isolated webhook ingress setup](/guide/platform/development/runtime#optional-github-webhook-ingress-for-access-protected-apis) when Access protects the API.
14
14
 
15
+ ## Deployment features
16
+
17
+ Both targets use the same application APIs. A core platform adds shared access and retained deployment history:
18
+
19
+ | Feature | Direct Cloudflare | Core self-hosted platform |
20
+ | ------------------------------------------------ | -------------------------------- | --------------------------------------------- |
21
+ | Static sites, SPAs, and native Pages SSR | Supported | Supported |
22
+ | Routing rules, WebSockets, queues, cron, and ISR | Supported | Supported |
23
+ | D1, KV, R2, and external SQL through Hyperdrive | Supported | Supported |
24
+ | Workers AI and provider requests | Your account and gateway | Installation gateway and proxy |
25
+ | Runtime logs | Live Cloudflare tail | Retained platform logs |
26
+ | Application rollback | Worker versions | Retained platform deployments |
27
+ | Typed Durable State | Supported | Unavailable |
28
+ | Sandboxes | Requires Workers Paid and Docker | Requires Workers Paid on the platform account |
29
+ | Custom application domains | Supported | Unavailable in the core installation |
30
+ | Generated GitHub deployment workflow | Supported | Use your CI with a scoped developer token |
31
+ | User dashboard and managed GitHub builds | Not required | Not included in a standard installation |
32
+
33
+ A team platform requires Workers for Platforms and the [documented infrastructure](/guide/platform/installation/domains#cloudflare-footprint). Features depend on the installation's configuration.
34
+
15
35
  ## Installation Guides
16
36
 
17
37
  - [Prerequisites](/guide/platform/installation/prerequisites)
@@ -202,8 +202,6 @@ Both `defineRoom()` and `defineWebSocket()` accept optional `name`. Use a static
202
202
 
203
203
  By default, the instance key includes parameter names. `/chat/:room` with `room: 'general'` uses `room=general`; a route without parameters uses `default`. Multiple parameters are joined in route order, for example `team=acme&room=general`. If a multi-parameter route has a value containing `&`, its key uses a versioned encoding to keep rooms separate.
204
204
 
205
- When upgrading an existing multi-parameter route with `&` in its parameter values, those rooms start with isolated storage. The previous storage is retained, but may have been shared by multiple rooms. Migrate only data whose ownership you have verified into each new room. Single-parameter rooms and multi-parameter rooms without `&` keep their existing identities.
206
-
207
205
  If you also rename `[room]` to `[id]`, preserve the old key explicitly:
208
206
 
209
207
  ```ts
@@ -36,11 +36,11 @@ With `voidPlugin()` added to the framework's Vite config, frameworks get most of
36
36
  - **Auth:** Void-managed auth is not supported in framework mode yet. For now, use Better Auth's official integration for your framework.
37
37
  - **Cron jobs:** scheduled handlers via the `crons/` directory.
38
38
  - **Queue consumers:** typed producers and consumers via the `queues/` directory.
39
- - **Revalidation and prerendering:** configure them with [`routing.revalidate`](../../guide/edge/revalidation.md) and [`routing.prerender`](../../guide/edge/prerendering.md) in `void.config.ts`. Void apps can also set these per page in component files.
39
+ - **Revalidation and prerendering:** configure them with [`routing.revalidate`](../../guide/edge/revalidation.md) and [`routing.prerender`](../../guide/edge/prerendering.md) in `void.config.ts`. Void apps can also set these per page in companion `.server.ts` files.
40
40
 
41
41
  For framework apps, Void revalidation caches public HTML document responses with both `void deploy` and `void deploy --platform cloudflare`. Client data requests continue to use the framework's own behavior. A response with `Set-Cookie` or `Cache-Control: private`, `no-store`, or `no-cache` is never shared.
42
42
 
43
- Frameworks can also access bindings directly via the framework's own mechanisms (e.g. `platform.env` in SvelteKit, `event.context.cloudflare.env` in Nuxt, `env` from `cloudflare:workers` in Analog, `Astro.locals.runtime.env` in Astro).
43
+ Frameworks can also access bindings directly via the framework's own mechanisms (e.g. `env` from `cloudflare:workers` in SvelteKit 3 and Analog, `platform.env` in SvelteKit 2, `event.context.cloudflare.env` in Nuxt, `Astro.locals.runtime.env` in Astro).
44
44
 
45
45
  ## Configuration
46
46
 
@@ -6,6 +6,8 @@ outline: deep
6
6
 
7
7
  Use Void with [SvelteKit](https://svelte.dev/docs/kit) for resource detection, typed database queries, and migrations. SvelteKit keeps its own build and Cloudflare integration; Void plugs into its Vite configuration.
8
8
 
9
+ Void supports SvelteKit 3 and SvelteKit 2.62 or later. The setup below uses SvelteKit 3 with `@sveltejs/adapter-cloudflare` 8.
10
+
9
11
  ## Setup
10
12
 
11
13
  ### 1. Create a new project
@@ -27,10 +29,8 @@ npm install -D @sveltejs/adapter-cloudflare void
27
29
  import adapter from '@sveltejs/adapter-cloudflare';
28
30
  import { sveltekit } from '@sveltejs/kit/vite';
29
31
  import { voidPlugin } from 'void';
30
- import { withVoidTSConfig } from 'void/sveltekit';
31
- import { defineConfig } from 'vite';
32
32
 
33
- export default defineConfig({
33
+ export default {
34
34
  plugins: [
35
35
  voidPlugin(),
36
36
  sveltekit({
@@ -38,16 +38,11 @@ export default defineConfig({
38
38
  config: './.void-wrangler.jsonc',
39
39
  platformProxy: { configPath: './.void-wrangler.jsonc' },
40
40
  }),
41
- typescript: {
42
- config: withVoidTSConfig(),
43
- },
44
41
  }),
45
42
  ],
46
- });
43
+ };
47
44
  ```
48
45
 
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()`.
50
-
51
46
  ### 4. Create `void.config.ts`
52
47
 
53
48
  Point SvelteKit's adapter at Void's generated Cloudflare config as shown above. Add your Cloudflare settings to `void.config.ts`:
@@ -66,20 +61,19 @@ export default defineConfig({
66
61
 
67
62
  ### 5. Configure `tsconfig.json`
68
63
 
69
- Extend SvelteKit’s generated config. The `withVoidTSConfig()` hook in the Vite config above adds Void’s types and aliases:
70
-
71
- Keep `compilerOptions.paths` out of the root config so it does not override SvelteKit’s aliases.
64
+ Extend SvelteKit’s generated config and Void’s generated types and database aliases:
72
65
 
73
66
  ```json
74
67
  {
75
- "extends": "./.svelte-kit/tsconfig.json",
68
+ "extends": ["$app/tsconfig", "./.void/tsconfig.json"],
76
69
  "compilerOptions": {
77
- "types": ["void/env"]
78
- }
70
+ "types": ["$app/types", "void/env"]
71
+ },
72
+ "include": ["src", "db", "crons", "queues", "*.ts"]
79
73
  }
80
74
  ```
81
75
 
82
- Run `void prepare` after a fresh clone or before typechecking in CI so `.void/tsconfig.json` exists before SvelteKit syncs its config.
76
+ Run `void prepare` after a fresh clone or before typechecking in CI so `.void/tsconfig.json` exists before SvelteKit syncs its config. Use `package.json` subpath imports for aliases such as SvelteKit 3's `#lib`.
83
77
 
84
78
  ### 6. Deploy
85
79
 
@@ -116,20 +110,41 @@ Declare variables in `env.ts` and read them with `import { env } from "void/env"
116
110
 
117
111
  ## Accessing Bindings Directly
118
112
 
119
- You can also use SvelteKit's `platform.env` in server hooks and load functions:
113
+ In SvelteKit 3, use the `cloudflare:workers` module in server-side code:
120
114
 
121
115
  ```ts
122
- // src/routes/users/+page.server.ts
123
- export async function load({ platform }) {
124
- const { results } = await platform.env.DB.prepare('SELECT * FROM users').all();
125
- return { users: results };
126
- }
116
+ import { env } from 'cloudflare:workers';
117
+
118
+ const { results } = await env.DB.prepare('SELECT * FROM users').all();
127
119
  ```
128
120
 
129
- Or the `cloudflare:workers` module:
121
+ ## Existing SvelteKit 2 apps
122
+
123
+ Use SvelteKit 2.62 or later with `@sveltejs/adapter-cloudflare` 7. The Vite configuration above also works with Kit 2; add Void's tsconfig hook to the `sveltekit()` options:
130
124
 
131
125
  ```ts
132
- import { env } from 'cloudflare:workers';
126
+ import { withVoidTSConfig } from 'void/sveltekit';
133
127
 
134
- const { results } = await env.DB.prepare('SELECT * FROM users').all();
128
+ sveltekit({
129
+ adapter: adapter({
130
+ config: './.void-wrangler.jsonc',
131
+ platformProxy: { configPath: './.void-wrangler.jsonc' },
132
+ }),
133
+ typescript: {
134
+ config: withVoidTSConfig(),
135
+ },
136
+ });
137
+ ```
138
+
139
+ Keep the Kit 2 tsconfig setup:
140
+
141
+ ```json
142
+ {
143
+ "extends": "./.svelte-kit/tsconfig.json",
144
+ "compilerOptions": {
145
+ "types": ["void/env"]
146
+ }
147
+ }
135
148
  ```
149
+
150
+ If your app uses `svelte.config.js` or `svelte.config.ts`, keep its configuration and add `typescript.config: withVoidTSConfig()` under `kit`. Kit 2's `platform.env` remains available in hooks and load functions.
@@ -89,12 +89,17 @@ These Void features work identically across all targets:
89
89
  - [Typed fetch client](../guide/typed-fetch.md) (`void/client`)
90
90
  - [Custom headers](../guide/edge/headers.md) (`routing.headers`)
91
91
  - [Redirects](../guide/edge/redirects.md) (`routing.redirects`)
92
- - [Environment variables](../guide/env-vars.md) (`.env` files)
93
92
  - [Static site generation](../guide/ssg.md)
94
93
  - [Vite preview](https://vite.dev/guide/cli#vite-preview) for testing production builds locally
95
94
 
96
95
  ## What's Different
97
96
 
97
+ ### Environment variables
98
+
99
+ Supply server values through your host's environment and read them with `process.env` in Node.js or Bun, or `Deno.env.get()` in Deno. The `void/env` schema and secret workflow requires Cloudflare.
100
+
101
+ For browser code, use Vite's `import.meta.env.VITE_*` values. These are embedded at build time and must not contain secrets.
102
+
98
103
  ### No Cloudflare bindings
99
104
 
100
105
  The following imports are **not available** with a non-CF target and produce a compile-time error:
@@ -106,7 +111,7 @@ The following imports are **not available** with a non-CF target and produce a c
106
111
  | `void/storage` | R2 (blob storage) |
107
112
  | `void/auth` | Void-managed Better Auth |
108
113
  | `void/ai` | Workers AI |
109
- | `void/env` | CF env type augmentation |
114
+ | `void/env` | Typed environment schema |
110
115
 
111
116
  If you need a database or storage, use an external provider and connect via standard Node.js libraries.
112
117
 
@@ -70,6 +70,33 @@ const response = await ai
70
70
 
71
71
  **Key exports:** `ai`, `VoidAi`, provider request types. See [AI](../../guide/ai.md) for provider setup and streaming examples.
72
72
 
73
+ ### Provider keys
74
+
75
+ Default secret names for `ai.provider()`. Use `apiKeyEnv` to choose another name.
76
+
77
+ | Provider prefix | Env var |
78
+ | ------------------ | --------------------- |
79
+ | `openai` | `OPENAI_API_KEY` |
80
+ | `anthropic` | `ANTHROPIC_API_KEY` |
81
+ | `google-ai-studio` | `GOOGLE_API_KEY` |
82
+ | `deepseek` | `DEEPSEEK_API_KEY` |
83
+ | `groq` | `GROQ_API_KEY` |
84
+ | `mistral` | `MISTRAL_API_KEY` |
85
+ | `grok` | `GROK_API_KEY` |
86
+ | `openrouter` | `OPENROUTER_API_KEY` |
87
+ | `perplexity` | `PERPLEXITY_API_KEY` |
88
+ | `cohere` | `COHERE_API_KEY` |
89
+ | `cerebras` | `CEREBRAS_API_KEY` |
90
+ | `huggingface` | `HUGGINGFACE_API_KEY` |
91
+ | `replicate` | `REPLICATE_API_KEY` |
92
+ | `baseten` | `BASETEN_API_KEY` |
93
+ | `cartesia` | `CARTESIA_API_KEY` |
94
+ | `deepgram` | `DEEPGRAM_API_KEY` |
95
+ | `elevenlabs` | `ELEVENLABS_API_KEY` |
96
+ | `fal` | `FAL_API_KEY` |
97
+ | `ideogram` | `IDEOGRAM_API_KEY` |
98
+ | `parallel` | `PARALLEL_API_KEY` |
99
+
73
100
  ## ISR {#isr}
74
101
 
75
102
  Imported from `"void/isr"`.
@@ -49,7 +49,7 @@ Import Void's app-facing APIs from these paths:
49
49
  | `void/response` | `convertReturnValue` |
50
50
  | `void/validator` | `runValidation`, `ValidatorSlots`, `HandlerInput` |
51
51
  | `void/drizzle-zod` | Re-exports [`drizzle-zod`](https://orm.drizzle.team/docs/zod) for schema-derived Zod validators for Drizzle tables |
52
- | `void/drizzle-valibot` | Re-exports [`drizzle-valibot`](https://orm.drizzle.team/docs/typebox) for schema-derived Valibot validators for Drizzle tables |
52
+ | `void/drizzle-valibot` | Re-exports [`drizzle-valibot`](https://orm.drizzle.team/docs/valibot) for schema-derived Valibot validators for Drizzle tables |
53
53
  | `void/drizzle-arktype` | Re-exports [`drizzle-arktype`](https://orm.drizzle.team/docs/arktype) for schema-derived ArkType validators for Drizzle tables |
54
54
  | `void/schema-d1` | Re-exports [`drizzle-orm/sqlite-core`](https://orm.drizzle.team/docs/column-types/sqlite) for D1 table and column builders |
55
55
  | `void/schema-pg` | Re-exports [`drizzle-orm/pg-core`](https://orm.drizzle.team/docs/column-types/pg) for PostgreSQL table and column builders |
@@ -41,11 +41,12 @@ are Void account operations. Prefer `void auth status`, `void account link`, and
41
41
 
42
42
  Browser login through one of the platform's currently enabled methods. The token is saved in the operating-system keychain, scoped to the platform origin. Login fails closed when no keychain is available instead of writing the token to a plaintext file; headless environments use `VOID_TOKEN` from their secret manager.
43
43
 
44
- If an older CLI login is no longer recognized after updating Void, run `void account login` again. Your saved platform and project links remain unchanged.
44
+ Connect to a platform with `void connect <url>` before logging in. If an older project link has no platform URL, connect and run `void project link` to select its project again.
45
45
 
46
46
  Set `VOID_API_URL` alongside `VOID_TOKEN` to identify the platform that issued it.
47
- A token without an API URL is only used for Void Cloud's production API; a saved
48
- connection or project cannot forward it to another platform. To use a platform's
47
+ Both the URL and token are required for environment-based authentication, and the
48
+ URL must already be connected. In a fresh CI environment, run
49
+ `void connect "$VOID_API_URL" --no-login` before deploying. To use a platform's
49
50
  saved login instead, unset `VOID_TOKEN`.
50
51
 
51
52
  This is optional if you already completed auth during `void connect` or the interactive `void init` flow.
@@ -52,7 +52,7 @@ Run ad-hoc SQL against the database. Provide SQL inline or from a file. SELECT q
52
52
 
53
53
  By default, targets the local database. Pass `--remote` to run against the deployed database selected in `.void/project.json`:
54
54
 
55
- - **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.
55
+ - **Void platform D1 projects**: routes the query through the selected platform's registered proxy using your auth token.
56
56
  - **Direct Cloudflare D1 projects**: invokes Cloudflare against the pinned D1 binding from `void.config.ts` or `void.lock.json`.
57
57
  - **Hosted PostgreSQL and MySQL projects**: fetches the stored connection string from the platform and connects directly.
58
58
  - **Direct Cloudflare PostgreSQL and MySQL projects**: uses `DATABASE_URL` from the current shell; Cloudflare cannot return the password from Hyperdrive.
@@ -14,7 +14,13 @@ void deploy --platform cloudflare --atomic
14
14
 
15
15
  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.
16
16
 
17
- On an upgraded Void platform, an accepted deployment continues if the CLI disconnects. The CLI automatically reconnects to its progress. Pressing Ctrl+C stops observation; use `void project cancel` to request cancellation and `void project status` to inspect the result. If interrupted execution requires recovery, wait for its result before deploying again.
17
+ Deploying to a Void platform requires an explicit connection with `void connect <url>`.
18
+ A saved project URL or `VOID_API_URL` alone does not establish a connection.
19
+ In fresh CI environments, run `void connect "$VOID_API_URL" --no-login` first.
20
+
21
+ On a Void platform, an accepted deployment continues if the CLI disconnects. The CLI automatically reconnects to its progress. Pressing Ctrl+C stops observation; use `void project cancel` to request cancellation and `void project status` to inspect the result. If interrupted execution requires recovery, wait for its result before deploying again.
22
+
23
+ The CLI reports stalled progress and automatic recovery, and waits up to 30 minutes after acceptance. If it times out, the deployment can continue; check `void project status` before trying another deployment.
18
24
 
19
25
  For an existing Void Worker, `void deploy` can link the Worker and migrate its root Cloudflare config. Keep the first deployment focused on the existing app. See [Deploy an existing Worker](../../integrations/cloudflare.md#deploy-an-existing-worker) for requirements and the ISR cache choice.
20
26
 
@@ -53,6 +59,20 @@ For the Void platform, project resolution precedence is:
53
59
 
54
60
  If no project is linked and no override is provided, CLI prompts to link or create one. In CI (non-TTY), `void deploy` errors out instead — set `VOID_PROJECT` or pass `--project <slug>`.
55
61
 
62
+ To deploy to another connected Void platform for one invocation:
63
+
64
+ ```sh
65
+ void connect https://second.example.com
66
+ VOID_API_URL=https://second.example.com void deploy --platform void --project my-app
67
+ ```
68
+
69
+ `VOID_API_URL` selects the platform and `--project` selects its project. You must
70
+ name the project when overriding a different platform's saved link. Existing
71
+ project links and deployment preferences remain unchanged, even when the target
72
+ project is created. The same applies to `VOID_PROJECT` and to another project on
73
+ the current platform. A first deployment still links the project when no destination
74
+ is configured. See [Deploy to another Void platform](../../guide/deployment.md#deploy-to-another-void-platform).
75
+
56
76
  ## `void deploy --platform cloudflare` {#void-deploy-platform-cloudflare}
57
77
 
58
78
  Build and deploy to your Cloudflare account using `void.config.ts`: