Deploy to Deno Deploy
Drop on Deno Deploy, with a Cloudflare D1 database and an S3-compatible bucket for files, like Cloudflare R2 or Amazon S3.
| Database | D1 over HTTP |
| Files | R2 S3 API |
| Rate limits | Per instance |
| Code images | SVG |
| Code image cleanup | None |
| Live | Not deployed yet |
What you need
- A Deno Deploy organization, and Deno 2.4 or newer signed in to it, for
deno deploy. - A Cloudflare account and Wrangler (
pnpm exec wrangler login). - An S3-compatible bucket and an access key for it. Deno Deploy has no file storage of its own.
- Node.js 24 and pnpm, to build.
- A GitHub OAuth app with the callback
https://<your-app-domain>/api/auth/callback/github.
Deploy
Get the code:
npx giget gh:vite-hub/drop my-drop cd my-drop pnpm installCreate the D1 database and apply its migrations:
pnpm exec wrangler d1 create vitehub-drop-deno # copy the id into CLOUDFLARE_D1_DATABASE_IDCLOUDFLARE_D1_DATABASE_NAME=vitehub-drop-deno pnpm db:migrate:d1Create a bucket. With Cloudflare R2:
pnpm exec wrangler r2 bucket create vitehub-drop-denoThen create an R2 API token with Object Read and Write on that bucket, under R2, Manage API tokens. It gives you an access key id and a secret.
Build for Deno. The bucket's name and endpoint are read at build time:
DROP_HOST=deno S3_BUCKET=vitehub-drop-deno S3_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com pnpm buildDeploy. ViteHub writes
.output/deploy.mjs, which creates the app on the first run (entrypointserver/index.mjs, with the tracednode_modules) and deploys it to production:DENO_DEPLOY_ORG=<your-org> DENO_DEPLOY_APP=my-drop node .output/deploy.mjsAdd the settings, then deploy again so the app picks them up:
deno deploy env add --org <your-org> --app my-drop CLOUDFLARE_ACCOUNT_ID "…" deno deploy env add --org <your-org> --app my-drop CLOUDFLARE_API_TOKEN "…" --secret deno deploy env add --org <your-org> --app my-drop CLOUDFLARE_D1_DATABASE_ID "…" deno deploy env add --org <your-org> --app my-drop CLOUDFLARE_D1_DATABASE_NAME "vitehub-drop-deno" deno deploy env add --org <your-org> --app my-drop AWS_ACCESS_KEY_ID "…" deno deploy env add --org <your-org> --app my-drop AWS_SECRET_ACCESS_KEY "…" --secret deno deploy env add --org <your-org> --app my-drop GITHUB_CLIENT_ID "…" deno deploy env add --org <your-org> --app my-drop GITHUB_CLIENT_SECRET "…" --secret deno deploy env add --org <your-org> --app my-drop BETTER_AUTH_SECRET "$(openssl rand -base64 32)" --secret deno deploy env add --org <your-org> --app my-drop DROP_ADMINS "…"Run the smoke test:
DROP_URL=https://my-drop.<your-org>.deno.net pnpm test:e2e:deployed
Settings
| Variable | What it is |
|---|---|
| GITHUB_CLIENT_ID | Your GitHub OAuth app's client ID. |
| GITHUB_CLIENT_SECRET | A client secret from the same app. |
| BETTER_AUTH_SECRET | Signs sessions and agent tokens. One per deployment: openssl rand -base64 32 |
| DROP_ADMINS | GitHub user ids that join as Admin, comma-separated: gh api users/<login> --jq .id |
| CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN | Cloudflare account id and an account API token with D1 edit access. |
| CLOUDFLARE_D1_DATABASE_ID, CLOUDFLARE_D1_DATABASE_NAME | The id and name of vitehub-drop-deno. |
| S3_BUCKET, S3_ENDPOINT, S3_REGION | The bucket, its endpoint, and its region (auto for R2). Read at build time. |
| AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY | The bucket's access key. |
Database
Cloudflare D1 over HTTPS. pnpm db:migrate:d1 applies new migrations and skips the ones already applied; run it before you deploy a schema change.
On Deno Deploy
- Code images are SVG only: PNG needs Cloudflare Browser Run.
- Rate limits count in memory per isolate, so they're looser than on Cloudflare.
- Nothing deletes expired code images: ViteHub has no scheduled jobs on Deno Deploy yet. They stop being served after five minutes, but stay in the bucket; a lifecycle rule on
code-images/cleans them up.