Open-Source Cold Email & Warmup Platform
Warmbly 是開源的冷郵件平台:溫暖您的收件箱、發送活動、並對每個回覆進行分流。可在我們的雲端運行或自行託管整個系統。
AI 翻譯
尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
Email open & click tracking for Gmail outreach: dashboard + Chrome extension
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Know who opened your email, how often, and when. Open and click tracking for Gmail outreach.
Cold outreach from Gmail is a black box: you send, then wait. Ripple adds a tracking pixel and tracked links to each email, so you see opens, repeat opens and clicks per recipient. It was built for speaker and sponsor outreach at E-Summit, IIT Roorkee, and works for anyone sending personal outreach at small scale. It is honest about limits: proxy fetches, prefetches and your own views are flagged or filtered, not counted as reads.
Live: https://ripplemail.vercel.app
{{first_name}}, {{org}}, …), schedule, and send from your own Gmail account. Per-account daily limit (default 25).| Tool | Version | Notes |
|---|---|---|
| Bun | 1.3+ | Package manager and test runner |
| Postgres | Any recent | Built against Supabase; any Postgres works with the pg adapter |
| Google Cloud project | n/a | OAuth client with the Gmail API enabled |
| Vercel Blob store | n/a | Only needed for attachments |
git clone https://github.com/thedevkansal/ripple.git
cd ripple
bun install
cp apps/web/.env.example apps/web/.env
Fill in apps/web/.env (see Configuration), then create the database tables:
cd apps/web && bunx prisma migrate deploy
Start the dev server on http://localhost:3000:
bun run dev
All variables live in apps/web/.env.
| Name | Description | Example |
|---|---|---|
DATABASE_URL | Postgres connection string (Supabase transaction pooler, port 6543) | postgresql://postgres.<REF>:<PASSWORD>@aws-0-<REGION>.pooler.supabase.com:6543/postgres |
DIRECT_URL | Optional. Session connection for migrations (Supabase session pooler, port 5432). Defaults to DATABASE_URL | postgresql://postgres.<REF>:<PASSWORD>@aws-0-<REGION>.pooler.supabase.com:5432/postgres |
APP_URL | Public origin. Used in tracking pixels, links and OAuth redirects | http://localhost:3000 |
AUTH_SECRET | Auth.js session secret | output of openssl rand -base64 32 |
AUTH_GOOGLE_ID | Google OAuth client ID | <CLIENT_ID>.apps.googleusercontent.com |
AUTH_GOOGLE_SECRET | Google OAuth client secret | <YOUR_CLIENT_SECRET> |
TOKEN_ENCRYPTION_KEY | 32-byte base64 key that encrypts Gmail refresh tokens | output of openssl rand -base64 32 |
CRON_SECRET | Bearer secret for the send-queue endpoint | output of openssl rand -hex 32 |
BLOB_READ_WRITE_TOKEN | Vercel Blob token for attachments | vercel_blob_rw_<YOUR_TOKEN> |
Google OAuth setup
<APP_URL>/api/auth/callback/google (sign-in)<APP_URL>/api/gmail/callback (Gmail connect)gmail.send and gmail.readonly scopes to the consent screen. While the app is in Testing mode, add each user as a test user.Run from the repo root.
| Command | What it does |
|---|---|
bun run dev | Start the web app in dev mode |
bun run build | Production build of the web app |
bun run test | Run all workspace tests |
bun run lint | Lint the web app |
bun run db:generate | Regenerate the Prisma client |
bun run build:extension | Build the Chrome extension into apps/extension/dist |
Scheduled campaigns go into a queue. Something must call the queue endpoint every minute; it then also syncs replies.
curl -X POST "http://localhost:3000/api/cron/send" -H "Authorization: Bearer <CRON_SECRET>"
Expected output (counts vary; replies holds the reply-sync result):
{"sent":0,"failed":0,"deferred":0,"replies":{}}
In production an external scheduler such as cron-job.org calls it. .github/workflows/send-queue.yml is a backup that runs every 5 minutes once the RIPPLE_URL and CRON_SECRET repo secrets are set.
bun run --filter @ripple/extension build:dev
Then open chrome://extensions, turn on Developer mode, click Load unpacked and pick apps/extension/dist. Details in apps/extension/README.md.
Add <APP_URL>/api/mcp as a custom connector in your AI app. Ripple runs its own OAuth server, so the app asks you to sign in and approve. Exact steps per app are on the dashboard's Settings page.
ripple/
├── apps/
│ ├── web/ Next.js app: landing page, dashboard, API
│ │ ├── prisma/ Schema and SQL migrations
│ │ └── src/
│ │ ├── app/
│ │ │ ├── dashboard/ Campaigns, contacts, templates, replies, settings
│ │ │ ├── t/ Tracking endpoints: pixel (o) and click redirect (c)
│ │ │ └── api/ Auth, Gmail connect, cron, extension, MCP, OAuth
│ │ ├── components/ UI components by area
│ │ └── lib/ Sending, queue, tracking, analytics, Gmail, MCP tools
│ └── extension/ Chrome MV3 extension for Gmail compose
├── packages/
│ └── shared/ Event classification, templating, link instrumentation
├── docs/PLAN.md Design notes and tracking model
└── .github/workflows/ CI and send-queue backup cron
mcp-handler)gmail.readonly is a restricted scope. A public launch needs Google's security assessment; until then the OAuth app stays in Testing mode (100 test users max).Fork the repo and create a branch from main.
Set up as in Getting Started.
For schema changes, edit apps/web/prisma/schema.prisma and add a migration:
cd apps/web && bun run db:migrate
Run the same checks as CI before pushing:
bun run test
bun run lint
cd apps/web && bunx next typegen && bunx tsc --noEmit
cd apps/extension && bunx tsc --noEmit
Open a pull request against main. CI must pass.
No license yet. All rights reserved until one is added.
Built by Dev Kansal for E-Summit, IIT Roorkee.
Questions and bugs: open an issue.