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
- 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>
}
- 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.