Host it yourself

Drop is a Nuxt app built on ViteHub, and it runs on Cloudflare, Vercel, Netlify, Deno Deploy, or a server of your own. One setting at build time picks the host; your drops, comments, and files stay in your accounts.

Pick a host

Cloudflare has everything Drop uses in one account. The other hosts use D1 over HTTP with a separate database per deployment. Every host but Cloudflare renders code images as SVG only.

HostDatabaseFilesRate limitsCode images
CloudflareD1R2Workers rate limitingPNG and SVG
VercelD1 over HTTPVercel BlobPer instanceSVG
NetlifyD1 over HTTPNetlify BlobsPer instanceSVG
Deno DeployD1 over HTTPR2 S3 APIPer instanceSVG
VPSD1 over HTTPLocal diskIn memorySVG

Choose the host at build time

DROP_HOST picks the host when you build. Without it, Drop builds for Cloudflare.

DROP_HOST=vercel pnpm build   # cloudflare (default), vercel, netlify, deno, or vps

nuxt.config.ts maps each host to its ViteHub preset and drivers: the database, file storage, rate limiting, and the hourly job that deletes expired code images. Your code doesn't change; ViteHub swaps the drivers behind vite-hub/database, vite-hub/blob, and the rest.

Sign-in and admins

Every Drop signs in with GitHub. Create a GitHub OAuth app with:

  • Homepage URL: https://<your-domain>
  • Authorization callback URL: https://<your-domain>/api/auth/callback/github

Then give the deployment these settings. Each host page says where they go.

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

Anyone with a GitHub account can sign in and joins as a Member. The accounts in DROP_ADMINS join as Admin, and admins change roles on the Members page. To use another sign-in provider, change the Better Auth options in server/auth.ts.

RoleWhat they can do
AdminEverything, plus members and settings.
EditorEdit and share any drop in the workspace.
MemberCreate, share, and comment on their own drops.

Database and migrations

Every host uses a separate Cloudflare D1 database. The non-Cloudflare hosts connect through D1's HTTP API. The same migrations in server/databases/migrations apply to all of them:

  • pnpm db:migrate:remote applies them to D1. pnpm run deploy runs it for you.
  • CLOUDFLARE_D1_DATABASE_NAME=vitehub-drop-… pnpm db:migrate:d1 applies them to a remote D1 database. Wrangler records each migration in d1_migrations.

After you change the schema in server/databases/, pnpm db:generate writes the next migration.

What changes between hosts

  • Code images. PNG is a Cloudflare Browser Run screenshot of the SVG, so only Cloudflare has it. Elsewhere create_code_image returns SVG, and asking for PNG fails with a clear error.
  • Rate limits. Cloudflare uses its rate limiting binding. Other hosts count in memory, per server instance, so limits are looser on serverless hosts that run many instances.
  • Expired code images. An hourly job deletes them: a Cron Trigger on Cloudflare, a Cron Job on Vercel, a scheduled function on Netlify, and a timer in the Node process on a VPS. Deno Deploy has none; expired images stop being served but stay in the bucket.
  • Caching. Rendered Markdown and the file count are cached in Workers KV on Cloudflare, and in memory elsewhere.

Check a deployment

The smoke test checks the public pages, the OAuth discovery documents, that /mcp asks agents to sign in, and the skills index:

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

Add DROP_TOKEN=<an MCP access token> to also run the signed-in flow: uploads, sharing, and MCP tools.

Develop locally

pnpm install
pnpm db:migrate   # once, and after schema changes
pnpm dev          # http://localhost:3000

Local dev runs against a local D1 and keeps files in .vitehub/data/blob. It has no GitHub app, so it also allows email and password sign-in: open /?signin=1.