Deploying to Cloudflare
npx flare deploywraps vinext-cloudflare deploy with the parts a Cloudflare app always
needs and almost always forgets the first time:
- Migrations before code. For every D1 database declared in
wrangler.jsonc: if it already exists (checked withwrangler d1 info), remote migrations apply before the deploy, and a failed migration aborts it — your new code never runs against an old schema. If the database doesn’t exist yet (a first deploy), Wrangler creates it during deploy and migrations run immediately after. - Build and deploy —
vinext-cloudflare deploy --config dist/server/wrangler.json. - Secrets. If
BETTER_AUTH_SECRETisn’t set on the Worker yet, Flare generates a fresh 32-byte value and uploads it over stdin — never the value from your local.dev.vars. Any other secret named in.dev.vars.examplethat’s still unset in production is listed with the exactwrangler secret putcommand to set it.
| Flag | Effect |
|---|---|
--skip-migrations |
Don’t touch D1 at all this deploy |
--skip-secrets |
Don’t check or generate secrets this deploy |
--skip-security |
Don’t push security.config.ts zone rules this deploy (see Security) |
--allow-open |
Don’t warn about resources with no policy (see below) |
--env <name> |
Forwarded to every Wrangler call (migrations, secrets, deploy) |
--preview |
Shorthand for --env preview |
--dry-run / --help |
Delegate straight through — nothing remote is touched |
Resources with no policy
Section titled “Resources with no policy”A resource with no policy file is readable and writable by any signed-in user.
flare gen resource writes an admin-only policy, so this only happens to a
resource generated before 0.11.0, or one whose policy was deleted — but when it
happens, the deploy is the moment it matters. So the deploy says so first:
⚠ 1 resource has no policy, so any signed-in user can read and write it: Payment Run `flare gen policy <Name> --roles admin` for each, or deploy with --allow-open if that is what you meant.It is a warning, not a refusal: an open resource is a legitimate choice — a
public catalogue, a form anybody may submit — and the deploy goes ahead. Pass
--allow-open once you have decided that is what you want, and it stays quiet.
Both stacks warn. The policy is enforced in the route on either, so a missing one means the same thing on Vercel as it does on Workers.
First deploy
Section titled “First deploy”You need wrangler login once. After that:
npx flare deployD1, R2, and the KV cache namespace are all auto-provisioned by name (no
IDs in wrangler.jsonc to manage), migrations apply right after
provisioning, and BETTER_AUTH_SECRET is generated for you. Your app is
live at <name>.<subdomain>.workers.dev.
Environments
Section titled “Environments”Wrangler environments (--env staging, --env production, …) work the
normal way — declare them in wrangler.jsonc, then pass --env to every
flare command that touches remote state (migrate, deploy,
role:add --remote, user:role --remote). Flare forwards it consistently
rather than requiring you to repeat Wrangler flags by hand.
Custom domains
Section titled “Custom domains”Once you attach a custom domain in the Cloudflare dashboard, set
BETTER_AUTH_URL to it (as a secret or plain var) — otherwise Better Auth
falls back to the localhost/workers.dev allowlist described in
the auth guide.
Verifying a deploy
Section titled “Verifying a deploy”The framework repo’s own scripts/e2e-crud.sh <url> and
scripts/e2e-auth.sh <url> are worth copying into your own app if you
want a repeatable smoke test against a live deploy — they exercise every
HTTP verb and the full auth flow, including the paths that are supposed
to fail (401/403/404/409/415/422).