Native Shell
Native Shell은 모든 플랫폼의 앱 안에서 만들어지는 AI UI입니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기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)