Open-Source Cold Email & Warmup Platform
Warmbly 是開源的冷郵件平台:溫暖您的收件箱、發送活動、並對每個回覆進行分流。可在我們的雲端運行或自行託管整個系統。
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Everything goes live.
FullSend is an autonomous marketing/content engine for applications. Connect a GitHub repository and FullSend builds verified product intelligence, a marketing plan, Instagram content, creative, scheduling, publishing, and analytics.
Major operations are persisted as jobs. Closing the browser does not stop work. Refreshing the application does not restart completed stages. Retries resume the failed operation rather than restarting the whole pipeline.檢視完整 README ↗Everything goes live.
FullSend is an autonomous marketing/content engine for applications. Connect a GitHub repository and FullSend builds verified product intelligence, a marketing plan, Instagram content, creative, scheduling, publishing, and analytics.
GitHub repository
↓
Product Intelligence (durable)
↓
Marketing Plan (durable)
↓
Instagram Content (durable jobs)
↓
Creative / Media (durable public URLs)
↓
Review / Approval
↓
Schedule
↓
Background Worker
↓
Instagram Publishing
↓
Analytics
↓
Optimization
Major operations are persisted as jobs. Closing the browser does not stop work. Refreshing the application does not restart completed stages. Retries resume the failed operation rather than restarting the whole pipeline.
An HTTP request creates durable jobs and returns. A worker pass runs separately and is bounded three ways, each closing a different route back to a request that outlives its own invocation:
Publishing is durable in the same sense. Instagram publishes in two calls — create a media container, then publish it — and the container id is written down before the publish call, the submission timestamp immediately before it goes out. If the response is lost, the next attempt asks Instagram what actually happened rather than publishing again. A unique index on the receipt is the backstop.
Instagram is the only active production social destination. TikTok exists in the codebase but is gated off by default (FULLSEND_TIKTOK_ENABLED; see OPERATOR_ACTIONS.md). The production content, scheduling, media, and publishing flow is Instagram-focused.
Plans live in src/lib/billing/plans.ts: Free / Send ($29) / Full Send ($79) / Agency ($249).
STRIPE_SECRET_KEY → billing is off; every account gets the full product with no limits.active or trialing subscription. Checkout and the Customer Portal handle cards — FullSend never sees card numbers.FULLSEND_ADMIN_EMAILS (or users.is_admin) get unlimited plan limits while still using the app normally — they are not free-plan capped when Live billing is on. Set [email protected] on Vercel for the creator account./api/billing/webhook keep the subscriptions row in sync. In-app UI: /app/billing.Owner setup (Dashboard + Vercel env) is documented in the Stripe billing pull request checklist.
Requires Node.js 22.x.
npm ci
npm run dev
Useful commands:
npm run typecheck
npm run lint
npm test
npm run build
npm run e2e
npm run worker
Linting is the ESLint CLI against eslint.config.mjs. Next 16 removed next lint, and next build no longer lints.
FullSend uses Next.js/Vercel for the application and Supabase for persistence, authentication, and media storage.
Run the database migrations in supabase/migrations/ in order:
| Migration | What it adds |
|---|---|
0001_fullsend_init.sql | Every table, and the RLS policies that keep tenants apart. |
0002_creative_storage.sql | The public fullsend-creative bucket Instagram fetches media from. |
0003_durable_publishing.sql | The columns that make a publish recoverable, and the unique index that makes publishing the same post twice impossible. |
0004_analysis_commit.sql | The commit an analysis was derived from, so the same commit is never analysed twice. |
0005_project_brand_identity.sql | Each project's own colours, type and marks, so no product is marketed in FullSend's identity. |
0006_generation_state.sql | Whether a post actually finished being made, and the vault column for a Facebook Page token. |
A migration file in the repository is not a migration in the database. GET /api/health checks each one against the live schema — including whether the storage bucket exists and is public — and names the file to run for anything missing.
Required production configuration includes:
NEXT_PUBLIC_APP_URL
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY
SUPABASE_SERVICE_ROLE_KEY
FULLSEND_ENCRYPTION_KEY
CRON_SECRET
ANTHROPIC_API_KEY or OPENAI_API_KEY
GitHub Actions drives the background queue/heartbeat. The worker claims jobs with a lease, persists results, retries bounded failures, and recovers stale work.
.github/workflows/heartbeat.yml asks for */5 * * * *. GitHub does not honour it. Scheduled workflows are throttled hard on quiet repositories, and in practice this one fires anywhere from 45 minutes to four hours apart.
Nothing in the schedule can fix that, so the run compensates for it: the queue job stays up and sweeps continuously — polling every 15 seconds while there is work and every 60 seconds when idle — until the next firing cancels and replaces it. Coverage comes from runs being long rather than from the schedule being punctual.
On a public repository this is free: Actions minutes are unmetered. On a private repository it is not — a continuous sweep will consume your monthly Actions allowance. There, either shorten the deadline in the workflow or use an external pinger instead.
For a genuinely punctual worker, point any scheduler at the queue endpoint:
POST https://<your-app>/api/cron/queue
Authorization: Bearer <CRON_SECRET>
Every five minutes is a sensible interval; each call is a bounded worker pass and returns as soon as it has done its allowance. Free services that do this include cron-job.org, Cronitor and UptimeRobot. On Vercel Pro you can use native crons in vercel.json instead — disable the Actions workflow if you do, so the jobs are not driven twice.
Whatever drives it, treat anything other than HTTP 200 as a failure — a redirect especially. Vercel answers 308 for any origin that is not the canonical one: http:// rather than https, a www/apex mismatch, a deployment alias pointing at the production domain. Most HTTP clients neither follow a redirect by default nor call it an error, so a wrong URL returns a success with a body of Redirecting... and the queue silently never runs. This is not hypothetical: it stalled this deployment for days, wearing the exact costume of a healthy system. Point the scheduler at the origin the deployment reports as appUrl on /api/health, and alert on the status code rather than on the request failing.
FullSend does not invent product capabilities. Marketing claims must be supported by repository evidence or explicit product information. Failed jobs remain visible with their error and retry state instead of being presented as successful.