Deploy to Cloudflare

Drop's default host. One Worker with D1, R2, KV, rate limiting, Browser Run, and a Cron Trigger, all in your Cloudflare account.

Deploy with the button

The button clones Drop into your GitHub account, creates D1, R2, and KV, and asks for the four sign-in settings below. It builds, applies migrations, and deploys the Worker. Enable R2 and Browser Run in your Cloudflare account first; they may require billing.

  1. Choose a Worker name and note its https://<worker>.<subdomain>.workers.dev address.
  2. Create a GitHub OAuth app with that address and callback <origin>/api/auth/callback/github. Supply its client id and secret, BETTER_AUTH_SECRET from openssl rand -base64 32, and DROP_ADMINS from gh api users/<login> --jq .id.
  3. Accept pnpm build as the build command and pnpm run deploy as the deploy command. If you add a custom domain later, update the OAuth app's homepage and callback.

The root wrangler.jsonc describes resources for the button. Cloudflare writes their new ids there. ViteHub generates .output/server/wrangler.json during the build; Drop carries the template's resource names and ids into that file. CLOUDFLARE_D1_DATABASE_ID still takes priority, so existing Workers Builds keep their current database.

DatabaseD1
FilesR2
Rate limitsWorkers rate limiting
Code imagesPNG and SVG
Code image cleanupCron trigger
Hosted instancedrop.vitehub.dev

What you need

  • A Cloudflare account.
  • Node.js 24 and pnpm.
  • A GitHub OAuth app with the callback https://<your-domain>/api/auth/callback/github. Use your workers.dev address until you add a domain.

Deploy from the terminal

  1. Get the code and sign in to Cloudflare:

    npx giget gh:vite-hub/drop my-drop
    cd my-drop
    pnpm install
    pnpm exec wrangler login
  2. Create the database and the bucket. Copy the database id into CLOUDFLARE_D1_DATABASE_ID in the next step.

    pnpm exec wrangler d1 create vitehub-drop   # prints the database id
    pnpm exec wrangler r2 bucket create vitehub-drop

    The KV namespace for Drop's render cache has no id to fill in. Wrangler creates it on the first deploy.

  3. Fill .env with the settings below. Uncomment the D1 database id and name:

    cp .env.example .env
  4. Deploy. It builds, applies the D1 migrations, and publishes the Worker with .env as its secrets:

    pnpm build && pnpm run deploy
  5. Add your domain to the Worker (Workers and Pages, your Worker, Settings, Domains and Routes), and make sure the GitHub app's callback uses it.
  6. Run the smoke test:

    DROP_URL=https://<your-domain> pnpm test:e2e:deployed

To deploy on every push instead, connect the repository in Workers Builds with CLOUDFLARE_D1_DATABASE_ID as a build variable. Keep its existing pnpm build and npx wrangler deploy commands. That deploy command does not run migrations, so apply new ones with pnpm db:migrate:remote.

Settings

VariableWhat it is
GITHUB_CLIENT_IDYour GitHub OAuth app's client ID.
GITHUB_CLIENT_SECRETA client secret from the same app.
BETTER_AUTH_SECRETSigns sessions and agent tokens. One per deployment: openssl rand -base64 32
DROP_ADMINSGitHub user ids that join as Admin, comma-separated: gh api users/<login> --jq .id
CLOUDFLARE_D1_DATABASE_IDThe id wrangler d1 create printed. Read at build time.
CLOUDFLARE_D1_DATABASE_NAMEThe D1 database name, vitehub-drop by default.

Database

D1. pnpm run deploy applies new migrations before it publishes; pnpm db:migrate:remote applies them on their own.

On Cloudflare

  • Code images come as PNG (the default) or SVG. PNG uses Browser Run.
  • Rate limits use Cloudflare's rate limiting binding, namespaced to the Worker's name.
  • An hourly Cron Trigger deletes expired code images.
  • Workers Logs is on, so every request's log line is searchable in the dashboard.