Skip to main content

Getting started

Quick start

postboi init picks a provider, collects credentials, writes your env vars, and installs Postboi.


One command, fully set up. The CLI picks a provider, asks for credentials, optionally sets defaults, and installs postboi if it isn’t already there.

bunx postboi init
bunx postboi init
npx postboi init
npx postboi init
pnpm dlx postboi init
pnpm dlx postboi init
yarn dlx postboi init
yarn dlx postboi init

What it does

  • Prompts you to choose one of the supported providers.
  • Collects that provider’s credentials (e.g. an API key, plus a domain for Mailgun).
  • Optionally collects from / to and other defaults applied to every send.
  • Writes only secrets (API keys, tokens) to your env file.
  • Writes everything else — the provider, defaults, and non-secret options like a Mailgun domain or SES region — to a committed postboi.config.ts.
  • Installs postboi if it isn’t installed yet.

The split means the best case (Resend, Postmark, SendGrid, Brevo, …) is a single env var — the API key — with the rest in version control.

// postboi.config.ts  (committed)
import { config } from 'postboi';

export default config({
	provider: 'resend',
	default: { from: 'no-reply@example.com' }
});
// postboi.config.ts  (committed)
import { config } from 'postboi';

export default config({
	provider: 'resend',
	default: { from: 'no-reply@example.com' }
});
# .env  (gitignored — secrets only)
RESEND_API_KEY=re_xxxxxxxx
# .env  (gitignored — secrets only)
RESEND_API_KEY=re_xxxxxxxx

After it finishes, mail() picks all of this up on every call — no further wiring needed.

import { mail } from 'postboi';

await mail({ to: 'contact@example.com', subject: 'Hi', body: '<p>Hello</p>' });
import { mail } from 'postboi';

await mail({ to: 'contact@example.com', subject: 'Hi', body: '<p>Hello</p>' });

Prefer to do it yourself?

Skip the CLI and write the config file plus the credential env vars by hand, or construct a provider instance directly. See Manual setup and Providers.