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.
| Host | Database | Files | Rate limits | Code images |
|---|---|---|---|---|
| Cloudflare | D1 | R2 | Workers rate limiting | PNG and SVG |
| Vercel | D1 over HTTP | Vercel Blob | Per instance | SVG |
| Netlify | D1 over HTTP | Netlify Blobs | Per instance | SVG |
| Deno Deploy | D1 over HTTP | R2 S3 API | Per instance | SVG |
| VPS | D1 over HTTP | Local disk | In memory | SVG |
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 vpsnuxt.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.
| 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 |
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.
| Role | What they can do |
|---|---|
| Admin | Everything, plus members and settings. |
| Editor | Edit and share any drop in the workspace. |
| Member | Create, 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:remoteapplies them to D1.pnpm run deployruns it for you.CLOUDFLARE_D1_DATABASE_NAME=vitehub-drop-… pnpm db:migrate:d1applies them to a remote D1 database. Wrangler records each migration ind1_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_imagereturns 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:deployedAdd 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:3000Local 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.