The email development toolkit for the 21st century



Brail provides batteries-included tooling for creating, generating and delivering email templates. It aims to bring email development into the 21st century by providing a modern, developer-friendly experience.


npx @brail/create-app




βš›οΈ

Idiomatic React

Write email templates using React syntax you know and love.

πŸ”’

Built-in Type-safety

Enjoy end-to-end type-safety, from React through to the server.

πŸ’Œ

Framework Agnostic

Brail integrates with your favourite meta-frameworks.

{ }

Developer-first

Enjoy first-in-class DX and rich devtools. Live-reloading out-of-the-box.

🌈

Theming

Easily theme email templates using a stitches-like API.

✨

Instant APIs

Instantly serve your templates via type-safe APIs and/or SDKs.

Overview

Create a template

  1. Create a template view using idiomatic React.
/* πŸ“„ my-template.tsx */
import Brail from "@brail/react";
import z from "zod";
 
const b = Brail.init();
 
	/** πŸ‘‡ Create your template */
const MyTemplateView = (props) => {
	return <Email>
		<Container>
			<Row>
				<Column>
					<Typography>Welcome, {props.name}</Typography>
				</Column>
			</Row>
		</Container>
	</Email>
}
  1. Define validation schema and sending logic (optional).
export default b.template
		/** πŸ‘‡ Define meta schema (optional) */
	.meta(z.object({ to: z.string(), sendGridApiKey: z.string() }))
		/** πŸ‘‡ Define props schema (optional) */
	.props(z.object({ name: z.string() }))
	/** πŸ‘‡ Define a send function (optional) */
	.onSend(async (args) => {
		const { meta, html } = args;
		const res = await sendGrid.send(html, {
			to: meta.to,
			apiKey: meta.sendGridApiKey,
		});
		return { ok: res.status === 200 };
	})
	.view(MyTemplateView); /** πŸ‘ˆ Register template view */

Use your template

You can now generate templates directly...

// Use your template directly
const html = myTemplate.render({/** Props */})
const sendResponse = await myTemplate.send({/** data: {}, meta: {} */})

Or serve them via a tRPC (opens in a new tab) API.

/* πŸ“„ lib/trpc.ts */
import { createTrpcRouter } from "brail/trpc";
import { initTrpc } from "@trpc/server";
 
const appRouter = createTrpcRouter({
	templates: { myTemplate },
	t: initTrpc.create()
});
/* πŸ“„ pages/api/trpc/[trpc].ts */
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
 
// Serve templates via edge runtime function
export default async function handler(req: NextRequest) {
	return fetchRequestHandler({
		endpoint: "/api/trpc",
		router: appRouter,
		req,
		createContext: () => ({}),
	});
}

Keep working with your favourite tools

Brail sits on top of your favourite meta-frameworks and uses tools you already know, including Zod (opens in a new tab) and tRPC (opens in a new tab).

Get started

npx @brail/create-app

Development status

🚦

Brail is currently in Beta, as any last bugs are ironed out. We're looking for feedback and contributions.