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