Open-Source Cold Email & Warmup Platform
Warmbly is the open-source platform for cold email: warm your mailboxes, send campaigns, and triage every reply. Run it on our cloud or self-host the whole thing.
Referrals, double opt-in, invite waves and a dashboard. Free for your first 500 signups. Open source.
MarketingHTML · GoGitHub @rohansxOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Self-hosted waitlist for every product you launch: referrals, double opt-in, invite waves and a dashboard. One Go binary, one SQLite file.
Taken from the repository README
Loading the full README.
Read the full README ↗A self-hosted waitlist for every product you're launching. One binary, one SQLite file, no monthly bill.
Lobby gives each of your products a signup form, double opt-in, a place in line, referral links that move people up, invite waves and a dashboard to run it all. Your list stays on your server.
Rather not run a server? Lobby Cloud is the same software, hosted: free for 500 signups, $5 a month after that (pricing).
/llms.txt, and the binary doubles as a CLI.docker run -d --name lobby -p 8080:8080 -v lobby-data:/data \
-e LOBBY_BASE_URL=http://localhost:8080 \
ghcr.io/rohansx/lobby:latest
Open http://localhost:8080. The first visit asks you to create the admin account. Then create a project and copy one of its snippets onto your site.
Without email settings, Lobby writes emails to the log, which is fine for trying it out. For real signups, set an email provider (see Configuration).
git clone https://github.com/rohansx/lobby && cd lobby
LOBBY_BASE_URL=https://wait.example.com RESEND_API_KEY=re_… [email protected] \
docker compose up -d
Needs Go 1.26 and Node 24.
(cd web && npm ci && npm run build) # the dashboard, embedded into the binary
go build -o lobby ./cmd/lobby
LOBBY_BASE_URL=https://wait.example.com ./lobby serve
Run the image behind your reverse proxy, mount a volume at /data and set LOBBY_BASE_URL to the public URL. blueprints/lobby/ has a docker-compose.yml and template.toml for a Dokploy template. Set LITESTREAM_REPLICA_URL to back the database up continuously to S3-compatible storage.
Each project gives you three ways in, all shown in the dashboard with your keys filled in.
Script widget. A form in a shadow DOM that won't clash with your styles. It reads ?ref= and UTM tags from the page.
<div id="waitlist"></div>
<script defer src="https://wait.example.com/v1/wl.js" data-project="pk_…" data-target="#waitlist" data-counter></script>
Options: data-button, data-placeholder, data-success, data-counter. Theme it with CSS variables on the container: --wl-accent, --wl-accent-ink, --wl-bg, --wl-ink, --wl-border, --wl-radius, --wl-muted, --wl-error. It fires a lobby:signup event you can hook analytics into.
Plain HTML form. No JavaScript at all.
<form method="post" action="https://wait.example.com/v1/w/pk_…/signup">
<input type="email" name="email" required>
<input type="text" name="website" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px">
<button>Join the waitlist</button>
</form>
Hosted page. No site yet? Share https://wait.example.com/w/your-project.
+tags fold together). Lobby stores the page, referrer, UTM tags and referral code.POST /v1/invites/redeem, or marks someone joined with POST /v1/signups/{id}/joined.Privacy. IP addresses are stored only as keyed hashes and cleared after 30 days. Public pages set no cookies. Consent text is versioned per signup. A hard delete leaves a suppression hash so a bot can't re-add the address. Broadcasts carry one-click unsubscribe headers.
| Variable | Purpose |
|---|---|
LOBBY_BASE_URL | Public URL of the instance. Links in emails and snippets use it, so get this one right |
LOBBY_FROM_EMAIL | Sender address, ideally on a sending subdomain ([email protected]) |
RESEND_API_KEY or SMTP_URL | Email provider. SMTP_URL is smtp://user:pass@host:587 or smtps://…:465. With neither set, emails go to the log |
RESEND_WEBHOOK_SECRET | Point Resend's bounce and complaint webhook at /v1/hooks/resend and those addresses are suppressed |
LITESTREAM_REPLICA_URL | e.g. s3://bucket/lobby, plus LITESTREAM_ACCESS_KEY_ID and LITESTREAM_SECRET_ACCESS_KEY. Continuous backup, restored automatically onto an empty volume |
LOBBY_DATA | Data directory (default ./data, /data in the image) |
LOBBY_ADDR | Listen address (default :8080) |
LOBBY_TRUST_PROXY | 0 if Lobby is exposed directly rather than behind a reverse proxy |
LOBBY_CHECK_MX | 0 to skip the MX lookup on signup |
LOBBY_CLOUD=1 turns an instance into a multi-tenant service, which is how Lobby Cloud runs. Anyone can sign up at /signup, confirm their email, and see only their own waitlists. Accounts get the Free, Launch or Pro limits (signups, waitlists, emails a month, webhooks and API, the "powered by Lobby" badge), and billing runs through Polar as merchant of record. Without LOBBY_CLOUD, none of this applies: one admin, every feature, no limits.
| Variable | Purpose |
|---|---|
LOBBY_CLOUD | 1 for open signup, per-account projects and plan limits |
POLAR_ACCESS_TOKEN | Polar organization access token (checkouts, customer sessions, subscriptions) |
POLAR_WEBHOOK_SECRET | Secret of the Polar webhook pointed at /v1/hooks/polar, with the subscription.* events |
POLAR_PRODUCT_LAUNCH_MONTHLY, _LAUNCH_YEARLY, _PRO_MONTHLY, _PRO_YEARLY | Polar product IDs for each plan and interval |
POLAR_SANDBOX | 1 to use Polar's sandbox while testing |
LOBBY_OPERATORS | Comma-separated emails of the people running the instance. Once verified, these accounts get an Operator page in the dashboard with instance totals, every account, and suspend/unsuspend |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | "Continue with Google". Redirect URI: {LOBBY_BASE_URL}/auth/google/callback |
GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET | "Continue with GitHub". Callback URL: {LOBBY_BASE_URL}/auth/github/callback |
Google and GitHub sign-in also work on a self-hosted instance, where they only let the existing admin in.
Per-project settings live in the dashboard: allowed origins, double opt-in, position mode, referral caps, sender name, reply-to, the new-signup notification address, page copy and consent text.
Deliverability matters more than any feature. Before launch, add the SPF, DKIM and DMARC records your provider gives you for the sending domain. Then sign up from a fresh inbox and check that the confirmation lands.
The binary is also a CLI. The Docker image links it as wl.
export LOBBY_URL=https://wait.example.com LOBBY_KEY=sk_… # the project's secret key
lobby stats
lobby signups --status confirmed
lobby invite --next 50
lobby export --format csv > list.csv
The REST API covers signups, invites, exports, webhooks and broadcasts, authenticated with the project's secret key. Every instance documents it at /llms.txt, so coding agents can run your waitlist for you.
go run ./cmd/lobby serve # API and public pages on :8080
cd web && npm run dev # dashboard with hot reload; proxies the API to :8080
go test ./...
The dashboard is a React app in web/ (Vite, Tailwind, shadcn/ui) that talks to a JSON API under /api/admin. npm run build writes it into internal/app/web/dist, which is embedded into the binary, so production stays one file. Public pages (hosted page, status page, unsubscribe) are server-rendered and work without JavaScript.
openapi.jsonIssues and pull requests are welcome.