Open-Source Cold Email & Warmup Platform
Warmbly 是開源的冷郵件平台:溫暖您的收件箱、發送活動、並對每個回覆進行分流。可在我們的雲端運行或自行託管整個系統。
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Live: https://growos-ai.vercel.app — open the demo with no sign-up. When the AWS backend is switched on, upload your own CSV and the agent runs in ~60 seconds. See DEPLOYMENT.md for how the always-on demo and the on-demand backend fit together.
Traditional CRMs make the marketer do all the thinking: build a segment, write a message, pick a channel, schedule a send. GrowthOS inverts this.
A scheduled growth agent prepares the work while the marketer keeps execution control:
The marketer's job shifts from building to steering.
Three independently deployable services:
┌─────────────────────────────────────────────────────────────┐
│ Frontend — Next.js App Router (Vercel) │
│ Onboarding · Dashboard · Opportunities · Campaigns · Analytics │
└────────────────────────┬────────────────────────────────────┘
│ REST + Auth JWT
┌────────────────────────▼────────────────────────────────────┐
│ Backend API — Express.js (Render) │
│ Ingestion · RFM Engine · AI Orchestrator · Campaign API │
│ requireAuth + resolveCompanyMiddleware on every route │
└──────────┬──────────────────────────────┬───────────────────┘
│ │ PostgreSQL + RLS
┌──────────▼──────────┐ ┌─────────────▼───────────────────┐
│ BullMQ Worker │────▶│ Channel Service │
│ Recipient outbox │ │ Twilio / Resend / Simulator │
└──────────┬──────────┘ └─────────────┬───────────────────┘
│ Redis │ HMAC callbacks
└───────────────────────────────┘
graph TD
subgraph CLIENT["Frontend — Next.js (Vercel)"]
ONB[Onboarding Wizard]
OPP[Opportunities Page]
CAM[Campaigns Page]
ANA[Analytics Page]
end
subgraph BACKEND["Backend API — Express.js (Render)"]
ING[Data Ingestion + RFM Engine]
PER[AI Persona Engine]
OPP_SVC[AI Opportunity Engine]
CAM_SVC[AI Campaign Generator]
LAUNCH[Campaign Launcher]
WH[Webhook Receiver]
end
subgraph CHANNEL["Channel Service — Node.js (Render)"]
QUEUE[Message Queue]
PROV[Twilio / Resend / Simulator]
CB[HMAC Webhook Emitter]
end
subgraph DB["Supabase — PostgreSQL (RLS on all tables)"]
T1[(customers · orders · products)]
T2[(personas · opportunities)]
T3[(campaigns · communications · events)]
end
CSV[CSV Upload] -->|multipart| ONB
ONB -->|POST /api/process-ingestion| ING
ING --> T1
T1 --> PER
PER -->|LLM| T2
T2 --> OPP_SVC
OPP_SVC -->|LLM| T2
T2 --> OPP
OPP --> CAM
CAM -->|LLM| CAM_SVC
CAM_SVC --> T3
CAM -->|launch| LAUNCH
LAUNCH --> T3
LAUNCH -->|transactional recipient outbox| QUEUE
QUEUE --> PROV
PROV --> CB
CB -->|POST /webhooks/channel-status| WH
WH --> T3
T3 --> ANA
requireAuth middleware on every Express route — rejects requests without a valid JWTresolveCompanyMiddleware resolves companyId exclusively from the authenticated user's DB profile — never trusted from the client requestPersisted AI generation uses a prompt → JSON parse → schema validate → DB write contract. Analytics uses deterministic aggregation and a safe fallback when an optional narrative call fails.
| Step | Schema enforced | Fallback |
|---|---|---|
| Persona Engine | { persona_name, description, reasoning } | Skip assignment, log |
| Opportunity Engine | Full typed opportunity object with numeric revenue fields | Discard, continue |
| Campaign Generator | { name, message_content, channel, objective, offer } | Return error to frontend |
QUEUED → SENT → DELIVERED → READ → CLICKED / FAILEDprocessed_webhook_events dedup table prevents duplicate processingsequenceNumber ensures status only advances forwardPromise.all, not sequentiallymain (root directory: frontend) plus the Actions backuprender.yaml links both services to Mithurn/GROWTH-OS main, deploys only after CI checks pass, and runs prisma migrate deploy before the backend starts| Concern | What I did | What I'd do at scale |
|---|---|---|
| Message delivery | Simulator fallback when no provider keys set; Twilio/Resend wired and ready | Add provider keys; no code changes needed |
| Job queue | BullMQ backed by required Redis; a separate worker entrypoint is ready, while the free-tier manifest runs workers in the API process | Enable the dedicated worker service before production traffic |
| Analytics realtime | 5s polling on campaign analytics page | Supabase Realtime subscriptions |
| Webhook ingestion | Transactional Prisma write with deduplication | Stream events when measured volume requires it |
| Cold starts | Health ping pre-warms the Render API | Paid always-on API and worker instances |
| Delivery guarantee | Durable at-least-once jobs; Resend receives a provider idempotency key | Add a provider-side dedup key for Twilio if its API supports one |
companies
└── profiles (user → company mapping, enforces multi-tenancy)
└── customers (external_id, RFM scores, persona assignment)
└── orders → order_items → products
└── personas (AI-generated behavioural archetypes)
└── opportunities (AI-detected, linked to persona distribution)
└── opportunity_customers (audience join table)
└── campaigns (AI-generated copy, channel, status)
└── communications (one row per recipient, status tracked)
└── communication_events (full delivery timeline)
└── processed_webhook_events (idempotency dedup)
└── agents (goal, guardrails, involvement level)
└── agent_actions (activity log — powers the live feed)
└── ingestion_sessions (upload progress tracking)
xeno-grow/
├── frontend/ # Next.js App Router · Tailwind · TypeScript
│ ├── app/
│ │ ├── page.tsx # Dashboard — opportunities + live agent activity
│ │ ├── onboarding/ # CSV upload + ingestion progress wizard
│ │ ├── opportunities/ # AI opportunity browser + goal input
│ │ ├── campaigns/ # Campaign builder + channel refiner
│ │ ├── analytics/ # Live campaign funnel + delivery stats
│ │ ├── personas/ # Customer persona breakdown
│ │ └── intelligence/ # AI intelligence brief
│ ├── lib/
│ │ ├── api.ts # All API calls + SWR cache layer
│ │ └── supabase/ # Auth client + token helpers
│ └── components/
│
├── backend/ # Express.js · Prisma · PostgreSQL · BullMQ · LangGraph
│ ├── src/
│ │ ├── server.ts # API process
│ │ ├── worker.ts # BullMQ worker process
│ │ ├── routes/ # Authenticated HTTP boundaries
│ │ ├── middleware/auth.ts # JWT verification + company resolution
│ │ ├── services/
│ │ │ ├── customer-attributes.ts # RFM + attribute engine
│ │ │ ├── personas.ts # AI persona generation
│ │ │ ├── opportunity-discovery.ts # AI opportunity engine
│ │ │ ├── campaigns.ts # Campaign CRUD + launch + state machine
│ │ │ ├── agent-logger.ts # Activity feed writes
│ │ │ └── agent-orchestrator.ts # Scheduled, overlap-safe agent runs
│ │ └── __tests__/ # Unit and real PostgreSQL integration suites
│ └── prisma/schema.prisma
│
├── channel-service/ # Standalone delivery service · Node.js
│ └── src/
│ ├── server.ts # POST /send endpoint
│ ├── queue.ts # Async message processor
│ ├── webhook.ts # HMAC-signed callback emitter
│ └── providers/
│ ├── twilio.ts # WhatsApp + SMS
│ ├── resend.ts # Email
│ └── simulator.ts # Fallback — QUEUED→SENT→DELIVERED→READ progression
│
├── .github/workflows/ci.yml # Typecheck + test pipeline (3 parallel jobs)
├── render.yaml # Declarative Render deployment config
└── scripts/start-all.sh # Local dev: starts all 3 services
Prerequisites: Node.js 22+, PostgreSQL with pgvector, Redis, Supabase Auth, and an OpenRouter API key
git clone https://github.com/Mithurn/xeno-grow
cd xeno-grow
chmod +x scripts/start-all.sh && ./scripts/start-all.sh
| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| Backend API | http://localhost:3001 |
| Channel Service | http://localhost:5001 |
backend/.env
NEXT_PUBLIC_SUPABASE_URL=
SUPABASE_ANON_KEY=
DATABASE_URL=
OPENROUTER_API_KEY=
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
OPENROUTER_MODEL=openrouter/free
CHANNEL_SERVICE_URL=http://localhost:5001
WEBHOOK_SECRET= # openssl rand -base64 32
FRONTEND_URL=http://localhost:3000
channel-service/.env
CRM_WEBHOOK_URL=http://localhost:3001/api/webhooks/channel-status
WEBHOOK_SECRET= # must match backend exactly
FAILURE_RATE=10 # % of simulated sends that fail
# Optional — real sends when set:
# RESEND_API_KEY=
# TWILIO_ACCOUNT_SID=
# TWILIO_AUTH_TOKEN=
# TWILIO_PHONE_NUMBER=
# TWILIO_WHATSAPP_NUMBER=
frontend/.env.local
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
NEXT_PUBLIC_API_URL=http://localhost:3001/api
cd backend
TOTAL_CUSTOMERS=500 TOTAL_ORDERS=3000 npm run generate:data
# Outputs: backend/generated-data/customers.csv + orders.csv
# Upload both via the onboarding wizard at http://localhost:3000/onboarding
The agent will process your data and surface opportunities in ~60 seconds.
./scripts/verify-local.sh
This applies local migrations, regenerates Prisma, runs backend unit and
Testcontainers integration tests, then lints/builds the frontend and channel
service. If Docker is unavailable, use SKIP_INTEGRATION=1 to run everything
else. Remote databases are refused unless ALLOW_REMOTE_DB=1 and
CONFIRM_REMOTE_DB=I_UNDERSTAND are explicitly set.
./scripts/dev-local.sh
Open http://localhost:3000. Press Ctrl-C to stop all services.