AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
앱용 이메일 API, npx postboi init 로 mail() 호출 시 DNS·카드 없이 월 3천 통 무료, 수신·리스트·웹훅·폼 포함
An email API for apps. Run npx postboi init and mail() sends: no DNS, no card, 3,000 emails a month free. Receiving, lists, webhooks and forms included.
개발 도구mdsvex · TypeScriptGitHub @postboi-mail온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
Postboi is an email provider and TypeScript SDK. Email, SMS, WhatsApp, push and chat from one API.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Email for your app, set up with one command
Postboi is an email provider, and postboi is its TypeScript SDK. Run
npx postboi init and mail() sends: no DNS, no card, no other provider to sign up for.
Receiving, lists, webhooks and forms are already in the box.
3,000 emails a month are free, for good. After that it's £9 for 40,000 or £25 for 100,000,
which is less than Resend charges for the same volume
(Postboi or Resend?).README 전문 보기 ↗Email for your app, set up with one command
Postboi is an email provider, and postboi is its TypeScript SDK. Run
npx postboi init and mail() sends: no DNS, no card, no other provider to sign up for.
Receiving, lists, webhooks and forms are already in the box.
3,000 emails a month are free, for good. After that it's £9 for 40,000 or £25 for 100,000, which is less than Resend charges for the same volume (Postboi or Resend?).
Already have a provider? mail() works with Resend, SES, Postmark and 40-odd others too, so
switching is a line of config. You don't need any of them to use Postboi. And when you want
more than email, the same API sends SMS, WhatsApp, push and chat.
📖 Docs · Pricing · Postboi compared · Dashboard
bunx postboi init
Pick Postboi, sign in in the browser, and you're done. The CLI writes one secret:
# .env
POSTBOI_TOKEN=…
import { mail } from "postboi"
await mail({ to: "[email protected]", subject: "Hi", body: "<p>Hello</p>" })
Mail goes out from [email protected] until you verify your own domain. Everything
that isn't a secret (defaults, hooks, the captcha key) goes in a committed
postboi.config.ts, and from is typed to the addresses
your account can send from.
No one at the keyboard? bunx postboi init --agent sets up a project with no prompts and no
sign-in. Sends stay sandboxed until someone claims it with one click.
More on that.
mail() a FormData and it becomes a tidy HTML table, with
attachments and grouped fields/__postboi, so mail sent in
development never reaches a real personanalyze() checks client
support, Gmail clipping, alt text and links, offline, in any test suitePostboiError, whichever provider failedPick Bring your own provider in postboi init instead. Your code stays the same:
// postboi.config.ts
import { config } from "postboi"
export default config({ provider: "resend", default: { from: "[email protected]" } })
# .env
RESEND_API_KEY=re_xxxxxxxx
See all providers.
A contact form action is one line:
// +page.server.ts
import { mail } from "postboi/kit"
export const actions = { default: mail }
Or use remote functions with postboi/remote and skip
the server file. Postboi also has guides for Next.js,
Astro, Nuxt,
React Router, Hono,
Express,
Cloudflare Workers and
Effect.
Run bunx postboi init --sms (or --whatsapp, --push, --chat) and call the function:
import { sms, whatsapp, push, slack, send } from "postboi"
await sms({ to: "+447788223344", message: "Your code is 4291" })
await whatsapp({ to: "+447788223344", template: "order_shipped", variables: { name: "Ada" } })
await push({ to: subscription, title: "Order shipped", message: "On its way" })
await slack({ message: "Deploy finished" })
// or try the cheapest channel first and stop when one works
await send({
to: { push: subscription, sms: "+447788223344" },
channels: "cheapest",
message: "Your code is 4291",
})
In development, texts and WhatsApp messages are logged, not sent.
SMS · WhatsApp ·
Push · Chat ·
send()
bunx postboi skill installs a skill that teaches the whole library, at
.claude/skills/postboi/ and .agents/skills/postboi/. It also ships in the package at
node_modules/postboi/skills/postboi/SKILL.md.https://docs.postboi.app/raw/<slug>, or everything at once from
/llms-full.txt.The repo builds and tests with Bun and Node 22.22.3+, 24.15+ or 26+, the
versions its whole toolchain installs on. devEngines in package.json holds that range, and npm 10.9
or later refuses to run here on any other Node. Bun doesn't read it, so bun run goes
ahead on whatever Node is on your PATH.
bun install
bun run dev # the docs site
bun run check # types
bun run lint
bun run test
bun run build # the package
The docs are a SvelteKit site on Cloudflare Workers, described in alchemy.run.ts as an
alchemy stack: Cloudflare.Website.SvelteKit builds the site and
deploys it with no adapter. The Worker's settings (name, compatibility date and flags,
observability, workers.dev and preview URLs) come from wrangler.jsonc, which the stack
reads, so the two ways of deploying can't disagree.
bun run infra:plan -- --stage prod # what a deploy would change
bun run infra:deploy -- --stage prod # docs.postboi.app, from main
bun run infra:deploy -- --stage pr-123 # a pull request's preview, on its workers.dev URL
bun run infra:destroy -- --stage pr-123 # and take it down again
It needs CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID in the environment (or
alchemy profile). Production deploys itself: .github/workflows/deploy-docs.yml runs the
--stage prod deploy from main after CI passes on a push and after every release.
PRs are welcome, new providers especially. Match the code style (snake_case, no
semicolons), add tests, and run check and lint before pushing. Releases are covered in
RELEASING.md.