← All posts

The easiest way to send email from a JavaScript app

Adding email to a JavaScript or TypeScript app usually means DNS, provider dashboards, and SDK boilerplate. Here's the easy way — send your first email in one line with Postboi.

If you've ever tried to add email to a JavaScript or TypeScript project, you know the drill: choose a provider, create an account, verify a domain, wrangle DNS records, read the SDK docs, and finally write some boilerplate to send a single message. It's a lot of yak-shaving for what should be one line of code.

This is a short guide to the easy way to set up email in a JavaScript app — no DNS to configure yourself, no provider dashboard to babysit, no email HTML to hand-write.

The hard way (for comparison)

A typical provider SDK looks something like this. It works, but the provider is now baked into your code, and you own all the wiring:

the usual boilerplate
import { Resend } from 'resend'

const resend = new Resend(process.env.RESEND_API_KEY)

await resend.emails.send({
	from: 'no-reply@example.com',
	to: 'contact@example.com',
	subject: 'Hi',
	html: '<p>Hello</p>'
})

Switch providers later and every one of those call sites changes.

The easy way with Postboi

Postboi puts one small API in front of every provider — and out of the box you don't even pick one. Here's the whole thing.

1. Install and configure in one command

The CLI signs you in, writes a token to your .env, and installs Postboi. Prefer your own provider? It'll collect those credentials instead and write a committed postboi.config.ts:

terminal
bunx postboi init

2. Send an email

anywhere in your app
import { mail } from 'postboi'

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

That's the entire integration. The token (or provider config) comes from your environment; mail() never needs to know what's behind it.

3. Turn a form into an email — for free

Most "send email" use cases are really "email me what someone typed into a form." Postboi parses FormData straight into a tidy HTML table, so you don't write any email markup — and body accepts the request.formData() promise as-is, so you don't even await it:

form endpoint
export async function POST({ request }) {
	await mail({ to: 'you@example.com', subject: 'New enquiry', body: request.formData() })
	return new Response('Thanks!')
}

See the FormData guide for grouped fields and attachments.

Never locked in

Because the provider is a config value, moving from the default to your own Resend, Postmark, Mailgun, SendGrid (or any of 20+ providers) is a one-line change — no code edits:

postboi.config.ts
// postboi.config.ts
import { config } from 'postboi'

export default config({
	provider: 'postmark', // was: 'resend'
	default: { from: 'no-reply@example.com' }
})

Frequently asked questions

Does this work outside SvelteKit?

Yes. Postboi is framework-agnostic and ships guides for Next.js, Astro, Nuxt, Remix, Hono, Express, and Cloudflare Workers. The core mail() API is identical everywhere.

Does it run on the edge?

Yes — Postboi works on Node, Bun, and edge runtimes such as Cloudflare Workers.

Do I have to use the CLI?

No. You can write postboi.config.ts and set the credential env vars by hand — see Manual setup.

Is it production-ready?

Postboi is in pre-release (pre-1.0). It's stable enough to build on, but pin your version and check the changelog before upgrading, as minor releases may include small breaking changes until 1.0.

Next steps

Ready to send your first email? Start free, then explore the quick start and providers.

The Postboi mascot

Put the boi to work.

One command between you and your first delivered email.

Start sending — free