Native Shell
Native Shell:AI 生成的 UI,在你的應用中原生呈現,涵蓋每個平台。iOS、Android、macOS、Windows 與 Linux 上的應用、GPUI 應用與網頁在執行時載入已簽名、沙箱隔離的 TSX 模組並繪製 th
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Email Sender API, deploy in your Free Cloudflare Accont to user like a service
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗A self-hosted transactional email service for Cloudflare Workers. Your backends call one authenticated REST API, and notify-flow renders the email from a template and sends it over plain SMTP to Gmail, Microsoft 365 or any other SMTP server. It does not depend on Resend, SendGrid, Mailgun or similar platforms. It can also send Web Push notifications to your users' phones and computers, opt-in per client.
[!IMPORTANT] There is no shared public instance. Each person or team deploys their own notify-flow, in their own Cloudflare account, with their own D1 database, queue and SMTP mailbox, and connects their own apps to it. The author's deployment is private and is not offered as a service: don't point your apps at it. The AI integration prompt walks you through your own deploy and the integration into your site.
[!NOTE] The MVP is implemented: emails are sent by template name or by event, synchronously or asynchronously through Cloudflare Queues, and data lives in Cloudflare D1. The Roadmap lists what comes next.
[!TIP] Adding email to your web app? Follow the web app integration guide: a step-by-step walkthrough with backend code samples. Or paste the AI integration prompt into a coding agent and let it do the work, then the AI management page prompt to get an admin page with statistics and template editing. For push notifications only, without email, use the AI Web Push prompt.
Every app ends up sending the same emails: welcome, email verification, password reset, login alerts. notify-flow keeps those emails in one place:
it, en and pt-BR.Frontend ──► Your backend ──► notify-flow (Worker) ──► SMTP server ──► Recipient
│ │
│ ├─ authenticate the client (API key)
│ ├─ validate payload and rate limit
│ ├─ pick the template (by name or event), render subject, HTML, text
│ ├─ send over TLS / STARTTLS, now or from a queue, retrying transient errors
│ └─ log the delivery in D1
└─ owns auth logic (tokens, reset URLs, user checks)
notify-flow only delivers mail. Security logic such as generating reset tokens stays in your backend.
You need Node.js 20+ and your own Cloudflare account (sign up): every deployment is independent, so the commands below create the Worker, database and queue in your account.
npm install
cp wrangler.jsonc.example wrangler.jsonc # git-ignored: fill in your database_id before deploying
npm run db:migrate:local
npm run client:create -- my-app # prints the API key once
cp .dev.vars.example .dev.vars # fill in your SMTP credentials
npm run dev # admin dashboard: http://localhost:8787/admin/ (not 127.0.0.1)
To deploy:
npx wrangler d1 create notify-flow # copy the database_id into wrangler.jsonc
npm run db:migrate:remote # on upgrades too: migrate before npm run deploy
npx wrangler queues create notify-flow-emails # once: the async send queue
npx wrangler secret put SMTP_USERNAME # repeat for SMTP_PASSWORD, SMTP_FROM_EMAIL, SMTP_FROM_NAME
npx wrangler secret put ADMIN_SETUP_TOKEN # long random string, used once to register the /admin account
npm run deploy
npm run client:create -- my-app --remote
For development:
npm test # vitest inside workerd, with a local D1
npm run typecheck # regenerates worker types, then tsc
A web app sends email through your own deployment (see Getting started) in three steps:
npm run client:create -- <app-name> --remote once per app, then store the key and your Worker's URL as secrets in the app's backend.POST /v1/email/send with a template, a recipient and the template's variables, or POST /v1/notifications with an event instead of a template. The frontend never calls notify-flow.429 and 500 with the same Idempotency-Key. Treat 4xx as integration bugs.The web app integration guide covers the details: architecture, Node.js and Python clients, password reset and sign-up flows, custom templates, retry rules, asynchronous sending and a production checklist.
Web Push is optional and opt-in per client: notify-flow can also notify a user's phone or computer while your app is closed, with a title and a short body from a built-in template, never user-written text. The operator sets the VAPID keys once and switches push on per client (setup). Your backend then registers each device and calls POST /v1/push/send. The Web Push guide has the browser, service worker and backend code.
The Worker also serves a monitoring page at /admin/: delivery stats and search, a log of errors and rejected requests, a SQL console on the D1 database, and a Clients panel with the per-client Web Push switch. There is one admin account, registered on the first visit with the ADMIN_SETUP_TOKEN secret and kept separate from client API keys. The admin dashboard guide covers setup, upgrades of an existing deployment, and what each section shows.
Every /v1/* route needs an API key, sent as Authorization: Bearer <key> or X-API-Key: <key>. A send is one call:
POST /v1/email/send
Authorization: Bearer <API_KEY>
Idempotency-Key: password-reset:user-123:request-456
Content-Type: application/json
{
"template": "password-reset",
"to": "[email protected]",
"locale": "it",
"variables": {
"appName": "Acme",
"name": "Mario",
"resetUrl": "https://app.example.com/reset-password?token=..."
}
}
{ "id": "msg_…", "status": "submitted" }
The API Reference documents every endpoint, field rule, error code and status: sending, events, templates and health, and the opt-in Web Push.
Credentials are stored as Cloudflare Secrets, never in the repository or in code.
| Name | Where | Value |
|---|---|---|
SMTP_PROVIDER | vars in wrangler.jsonc | gmail, microsoft or generic |
SMTP_HOST, SMTP_PORT, SMTP_SECURITY | vars, optional | Override the preset (SMTP_SECURITY is tls or starttls) |
SMTP_AUTH_TYPE | vars, optional | plain or login (default: per preset) |
SMTP_USERNAME, SMTP_PASSWORD | secret | SMTP account credentials |
SMTP_FROM_EMAIL, SMTP_FROM_NAME | secret | Sender identity |
| Preset | Host | Port, security and auth |
|---|---|---|
gmail | smtp.gmail.com | 465 with TLS, AUTH PLAIN; needs an app password |
microsoft | smtp.office365.com | 587 with STARTTLS, AUTH LOGIN |
generic | set SMTP_HOST | 587 with STARTTLS, AUTH PLAIN |
[!WARNING] Microsoft 365 requires SMTP AUTH to be enabled on the sending mailbox, and Security Defaults block it. Microsoft is also retiring basic authentication for SMTP AUTH. If you use this preset, plan for OAuth2 (XOAUTH2 is on the roadmap).
Idempotency-Key never sends a duplicate email or push./v1/push/*, a separate budget), RECIPIENT_LIMIT_PER_HOUR (default 5) emails per recipient and template for each client, and PUSH_LIMIT_PER_HOUR (default 60) pushes per user and conversation. Failed sends do not count.src/
├── index.ts # Worker entry point and router
├── admin/ # dashboard API: setup, login, sessions, stats, logs, SQL, clients
├── push/ # Web Push: VAPID and encryption, subscriptions, sender
├── routes/ # email, notifications, events, templates, health
├── security/ # auth, payload validation, rate limiting
├── services/ # email-service (idempotency, retries, delivery log), queue-consumer (async sends), logger (app_logs)
├── templates/ # renderer, built-in defaults, built-in events
├── smtp/ # SMTP client + provider presets
└── types/
public/admin/ # dashboard pages, served as static assets
migrations/ # D1 schema
scripts/ # create-client.mjs, vapid-keys.mjs
test/ # vitest, runs inside workerd
docs/ # docs site (VitePress): guides, API Reference; specs and plans are not published
The docs/ folder doubles as a VitePress site: Home, Documentation and API Reference, built from these Markdown files (specs, plans and handoffs are not published).
npm run docs:dev # local site with hot reload
npm run docs:build # static build in docs/.vitepress/dist; fails on dead links
npm run docs:preview # serve the build
To publish it, connect the repository to Cloudflare Pages with these settings:
| Setting | Value |
|---|---|
| Project name | notify-flow-docs |
| Production branch | main |
| Build command | npm run docs:build |
| Build output directory | docs/.vitepress/dist |
| Environment variable | NODE_VERSION=22 |
These items come from the spec and are planned after the MVP:
X-Client-Id, X-Timestamp, X-Signature)