Open-Source Cold Email & Warmup Platform
Warmbly 是开源的冷邮件平台:温暖您的邮箱、发送活动、并对每条回复进行分流。可在我们的云端运行,也可自行托管整套系统。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
AI-assisted brand creative studio for Auckland Council: manage brands and brand guidelines, generate on-brand creative assets (banners, social tiles, animated formats) from briefs with OpenAI, review/approve them with automated brand-compliance checks, and export the final deliverables.
pnpm monorepo, Node.js 24, TypeScript.查看完整 README ↗AI-assisted brand creative studio for Auckland Council: manage brands and brand guidelines, generate on-brand creative assets (banners, social tiles, animated formats) from briefs with OpenAI, review/approve them with automated brand-compliance checks, and export the final deliverables.
pnpm monorepo, Node.js 24, TypeScript.
artifacts/api-server — Express 5 API (/api/*), also serves the built frontend in production. Port 8080 by default.artifacts/brand-studio — React 19 + Vite frontend (Tailwind, Radix, TanStack Query, wouter).lib/db — PostgreSQL via Drizzle ORM (pg driver). Schema in lib/db/src/schema/.lib/api-spec / lib/api-zod / lib/api-client-react — OpenAPI spec + generated Zod schemas and React Query hooks (Orval).lib/integrations-openai-ai-server — OpenAI client (chat: gpt-4o-mini, images: gpt-image-1).@clerk/express + @clerk/react). First signed-in user becomes admin. Reads are public, writes require auth.OBJECT_STORAGE_DIR, default ./data/objects) or Vercel Blob (auto-selected when BLOB_READ_WRITE_TOKEN is set). Both use the same keys, so /objects/... paths in the DB are backend-agnostic. Uploads flow through /api/storage/* either way.docs/agent-notes/ — architecture and feature decision notes.| Variable | Required | Description |
|---|---|---|
DATABASE_URL | yes | Postgres connection string |
OPENAI_API_KEY | yes | OpenAI API key (creative + image generation, compliance checks) |
OPENAI_BASE_URL | no | Override OpenAI endpoint (proxy/gateway); defaults to api.openai.com |
CLERK_PUBLISHABLE_KEY | for auth | Clerk publishable key |
CLERK_SECRET_KEY | for auth | Clerk secret key |
SEED_DEMO_BRAND | no | 0 = skip the Auckland Council demo-brand seed (white-label install: the app starts with a neutral skin and takes on the first brand you create) |
DEV_AUTH_BYPASS | no | 1 = treat every request as a local admin, ONLY honoured when Clerk keys are absent. Local dev/preview only — never set in production |
PORT | no | Defaults to 8080 |
OBJECT_STORAGE_DIR | no | Uploaded/generated file storage dir (fs driver), defaults to ./data/objects — must be a persistent volume in production |
BLOB_READ_WRITE_TOKEN | on Vercel | Vercel Blob store token; its presence switches file storage to the Blob driver |
STORAGE_DRIVER | no | Force the storage backend: fs or vercel-blob (default: auto by token presence) |
BLOB_STORE_BASE_URL | no | Blob store public base URL; only needed if it can't be derived from the token |
CRON_SECRET | no | If set, /api/cron/* routes require Authorization: Bearer <secret> (Vercel Cron sends it automatically) |
FRONTIFY_PORTAL_URL | no | Public Frontify portal to sync the library from (defaults to the AC portal) |
META_ACCESS_TOKEN | no | Meta system-user token with ads_read; with META_AD_ACCOUNT_ID turns on the Meta Ads section of Performance |
META_AD_ACCOUNT_ID |
| Variable | Required | Description |
|---|---|---|
VITE_CLERK_PUBLISHABLE_KEY | yes | Same Clerk publishable key, baked in at vite build |
VITE_CLERK_PROXY_URL | no | Only if proxying Clerk's frontend API through your domain |
BASE_PATH | no | Base URL path, defaults to / |
Clerk is optional: with no keys the app runs read-only (no sign-in, writes 401). Add DEV_AUTH_BYPASS=1 to use the full app locally as an auto-provisioned admin without Clerk.
pnpm install
DATABASE_URL=postgres://localhost:5432/brand_studio pnpm --filter @workspace/db run push # create/update schema
pnpm --filter @workspace/api-server run dev # API on :8080 (env vars above)
pnpm --filter @workspace/brand-studio run dev # Vite dev server on :25611, proxies /api to :8080
pnpm run typecheck — full typecheck. pnpm run build — typecheck + build everything.
After changing the OpenAPI spec: pnpm --filter @workspace/api-spec run codegen, then rebuild libs (pnpm run typecheck:libs).
The repo is pre-configured for Vercel (vercel.json): the frontend is served as static files from Vercel's CDN, and all /api/* + /track/* traffic is handled by a single serverless function (api/index.mjs, an esbuild bundle of the Express app built from artifacts/api-server/src/vercel.ts).
One-time setup:
DATABASE_URL=... pnpm --filter @workspace/db run push.BLOB_READ_WRITE_TOKEN, which switches file storage to Blob automatically.DATABASE_URL, OPENAI_API_KEY, CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY, VITE_CLERK_PUBLISHABLE_KEY (build-time, same value as the publishable key), and optionally CRON_SECRET.npx vercel from the repo root (or connect a Git repo). Install/build commands and output directory come from vercel.json.artifacts/api-server/data/objects): BLOB_READ_WRITE_TOKEN=... pnpm --filter @workspace/scripts run migrate:blob. Migrate the database rows with your Postgres tool of choice (pg_dump/pg_restore).Vercel-specific behavior to know about:
waitUntil), capped by maxDuration — 300 s in vercel.json. A brief with many sizes can exceed that; the cron route resets briefs stuck in "generating" for 15+ min back to draft so they can be retried. On the Pro plan you can raise maxDuration to 800./api/cron/dispatch, daily in vercel.json — Hobby plan allows only daily crons; tighten the schedule on Pro)./api/storage/uploads/request-url tells the client to upload via @vercel/blob/client (token handshake at /api/storage/uploads/client-token), bypassing Vercel's ~4.5 MB request-body limit. Cap is 500 MB per file. The server-relayed PUT route still exists for filesystem deployments.The API server serves the built frontend:
pnpm install
VITE_CLERK_PUBLISHABLE_KEY=pk_... pnpm run build
node artifacts/api-server/dist/index.mjs # with runtime env vars set
Requirements:
OBJECT_STORAGE_DIR (uploaded brand assets and generated images live there). On ephemeral/autoscale platforms, mount a volume, a persistent path — or set BLOB_READ_WRITE_TOKEN to use Vercel Blob storage from any host.html_banner/animated_social. Every asset passes a brand-compliance gate (deterministic colour/font parse for HTML, GPT-4o vision for images) with one automatic retry on failure..html creatives plus a static PNG fallback; hosted ad tags (iframe snippet sized to the creative) track impressions/clicks via /track/*.Generated banners are finalized deterministically (artifacts/api-server/src/lib/htmlBanner.ts), so regardless of model output they always carry:
<meta name="ad.size" content="width=X,height=Y">clickTag wiring (global var + full-size click layer)The hosted /track/serve/:token route resolves window.clickTag to the click-tracking redirect, exactly like an ad server does.
Colour compliance honours every hex listed in the brand's guidelines text (the extended palette), not just the five brand colour fields.
tailwindcss({ optimize: false }) in the frontend vite config is required — Clerk CSS layers get reordered in prod builds without it.@layer theme, base, clerk, components, utilities; must appear before @import "tailwindcss" in index.css.templateSizes is stored as a JSON string in Postgres./api/storage/...), never inline base64 (1 MB JSON body cap).sharp to 0.34.x (0.35.0 breaks TS resolution).| no |
Meta ad account (act_…) whose insights /api/cron/meta-sync pulls daily |
FRONTIFY_SYNC_MAX_NEW | no | Max new assets fetched per /api/cron/frontify-sync run (default 100; runs daily) |
FRONTIFY_SYNC_SOURCES | no | Comma-separated folder allowlist for the sync (e.g. Logos,Illustrations); default all |
FRONTIFY_BRAND_NAME | no | Brand whose library the sync targets (default Auckland Council) |
STATIC_DIR | no | Frontend build dir; defaults to ../brand-studio/dist/public relative to the server bundle |
LOG_LEVEL | no | pino log level |