Host it yourself
Run your own Drop on Cloudflare, Vercel, Netlify, Deno Deploy, or a VPS.
Start with the button for your host. You still supply GitHub sign-in and your admin user id. The steps below cover those values and the database.
Sign-in and admins
Drop signs in with GitHub. You can also reuse an existing GitHub oauth2-proxy. For native sign-in, 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 |
By default, anyone with a GitHub account can sign in and joins as a Member. Set DROP_GITHUB_ORG to require active organization membership for publishing and viewing, including shared links and MCP. GitHub sign-in then requests read:org. 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
Docker and VPS builds default to local SQLite on persistent disk. The other hosts use separate Cloudflare D1 databases, with D1's HTTP API outside Cloudflare. The same migrations in server/databases/migrations apply to all of them:
For a deployment that uses D1 outside Cloudflare, create it from a machine with Node.js:
npx wrangler login
npx wrangler d1 create my-dropCopy its id and name, your Cloudflare account id, and an account API token with Account, D1, Edit permission into the host's settings. Limit the token to your account.
From your cloned repository, pnpm db:migrate:d1 needs CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN, and CLOUDFLARE_D1_DATABASE_ID in its environment. It records migrations in d1_migrations and skips those already applied.
- Cloudflare's button runs
pnpm run deploy, which applies migrations by theDBbinding. Existing Workers Builds usingnpx wrangler deploystill needpnpm db:migrate:remoteafter schema changes. - Vercel and Netlify run
pnpm db:migrate:d1after building, before publishing. - Deno runs it as a pre-deploy command. Docker Compose uses Drizzle for SQLite, or this command for an explicit D1 build, before starting Drop.
Use a separate D1 database for previews, or disable preview deployments. A build with production D1 credentials migrates that database.
After you change the schema in server/databases/, pnpm db:generate writes the next migration.
Pick a host
Cloudflare has everything Drop uses in one account. VPS builds can keep all data on local disk; the serverless 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 | Local SQLite or D1 | Local disk | In memory | SVG |
Choose the host at build time
DROP_HOST explicitly picks the host when you build. Otherwise Drop detects NITRO_PRESET or SERVER_PRESET, then Vercel, Netlify, or Deno environment markers. A local DROP_DATABASE_URL selects VPS when no host is selected. With no signal, it builds for Cloudflare. Docker always selects VPS.
DROP_HOST=vercel pnpm build # explicit override: cloudflare, vercel, netlify, deno, or vpsUse DROP_DATABASE=sqlite or DROP_DATABASE=d1 to choose the database at build time. SQLite requires the VPS preset and persistent disk. An existing D1 database id keeps a VPS build on D1. Rebuild to change drivers and migrate data separately.
nuxt.config.ts maps each host to its ViteHub preset and drivers: the database, file storage, rate limiting, and the 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.
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 on Cloudflare, Netlify, and a VPS. Vercel runs cleanup daily so it works on Hobby. 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.