Banata

Infrastructure

Email Templates

Block-based email template editor with 9 block types, variable interpolation, and 6 built-in auth templates.

Banata Auth includes a block-based email template system for building, customizing, and sending transactional emails. Templates are composed of ordered arrays of typed blocks, edited visually in the dashboard, and rendered to HTML at send time using React Email. All templates inherit your project's branding configuration (colors, fonts, logo).

For auth flows, these templates are the default runtime path. Once a provider is active, Banata automatically uses the built-in auth templates for verification, password reset, magic-link, OTP, invitation, and welcome emails. The SDK email helpers are for programmatic sends and custom workflows, not for the baseline auth wiring.


Block Types

Each email template is an ordered array of 9 block types. Blocks map 1:1 to React Email components and support the shared EmailBlockStyle properties for inline styling.

Heading

Renders an <h1> through <h6> element.

PropertyTypeDescription
type"heading"Block discriminator
as"h1" | "h2" | ... | "h6"Heading level
textstringHeading text. Supports {{variable}} interpolation
styleEmailBlockStyleOptional inline styles

Text

A paragraph of body text. Supports basic inline HTML (e.g., <strong>, <em>).

PropertyTypeDescription
type"text"Block discriminator
textstringParagraph content. Supports {{variable}} interpolation and inline HTML
styleEmailBlockStyleOptional inline styles

Button

A call-to-action button rendered as a linked element.

PropertyTypeDescription
type"button"Block discriminator
textstringButton label
hrefstringLink URL. Supports {{variable}} interpolation
variant"primary" | "secondary" | "outline"Visual variant (defaults to "primary")
styleEmailBlockStyleOptional inline styles

Image

An inline image element.

PropertyTypeDescription
type"image"Block discriminator
srcstringImage source URL
altstringAlt text for accessibility
widthnumberOptional width in pixels
heightnumberOptional height in pixels
styleEmailBlockStyleOptional inline styles

Divider

A horizontal rule separator.

PropertyTypeDescription
type"divider"Block discriminator
styleEmailBlockStyleOptional inline styles

Spacer

Empty vertical space with configurable height.

PropertyTypeDescription
type"spacer"Block discriminator
heightnumberHeight in pixels

Code

Monospace-styled text, designed for OTP codes, tokens, and inline code snippets.

PropertyTypeDescription
type"code"Block discriminator
textstringCode content. Supports {{variable}} interpolation
styleEmailBlockStyleOptional inline styles

An inline hyperlink.

PropertyTypeDescription
type"link"Block discriminator
textstringLink text
hrefstringLink URL. Supports {{variable}} interpolation
styleEmailBlockStyleOptional inline styles

Columns

A multi-column layout (2 to 4 columns). Each column contains its own nested array of blocks.

PropertyTypeDescription
type"columns"Block discriminator
columnsColumnDef[]Array of 2-4 column definitions

Each ColumnDef:

PropertyTypeDescription
widthstringCSS width (e.g., "50%", "200px")
blocksEmailBlock[]Nested blocks within this column

EmailBlockStyle

All blocks that accept a style property use the shared EmailBlockStyle interface:

typescript
interface EmailBlockStyle {
  color?: string;
  backgroundColor?: string;
  fontSize?: number;
  fontWeight?: "normal" | "bold" | "600" | "700";
  fontStyle?: "normal" | "italic";
  textAlign?: "left" | "center" | "right";
  lineHeight?: number | string;
  padding?: string;
  margin?: string;
  borderRadius?: number;
  width?: string;
  maxWidth?: string;
}

Variable Interpolation

Templates support {{variableName}} placeholders in text, URLs, and subject lines. Variables are replaced at send time with the data passed in the API call.

typescript
// In a template block:
{ type: "text", text: "Hi {{userName}}, welcome to {{appName}}!" }
 
// At send time:
await banata.emails.send({
  to: "jane@example.com",
  template: "welcome",
  data: { userName: "Jane", appName: "Acme" },
});
// Renders: "Hi Jane, welcome to Acme!"

Unmatched variables are left as-is (e.g., if {{promoCode}} is in the template but not provided in data, the literal string {{promoCode}} appears in the output).

Extracting Variables

The extractVariables utility scans a block array and returns all referenced variable names:

typescript
import { extractVariables } from "@banata-auth/shared";
 
const vars = extractVariables(template.blocks);
// ["userName", "verificationUrl", "appName"]

Built-in Auth Templates

Banata Auth ships with 6 built-in templates for standard auth flows. These are created automatically and can be customized in the dashboard editor. Built-in templates cannot be deleted.

verification

Sent when a user signs up and needs to verify their email address.

Variables: userName, verificationUrl, token

Default blocks: Heading, greeting, explanation text, "Verify Email" button, divider, fallback URL link.

password-reset

Sent when a user requests a password reset.

Variables: userName, resetUrl, token

Default blocks: Heading, greeting, explanation text, "Reset Password" button, divider, expiration notice.

Sent for passwordless sign-in via magic link.

Variables: email, magicLinkUrl, token

Default blocks: Heading, greeting, explanation text with 10-minute expiry, "Sign In" button, divider, safety notice.

email-otp

Sent for email-based one-time password verification.

Variables: email, otp

Default blocks: Heading, explanation text, large monospace OTP code block, divider, safety notice.

invitation

Sent when a user is invited to join an organization.

Variables: email, invitationId, organizationName, inviterName, acceptUrl

Default blocks: Heading, invitation text with inviter/org names in bold, "Accept Invitation" button, divider, fallback URL link.

welcome

Sent after successful account creation.

Variables: userName, dashboardUrl, appName

Default blocks: Heading with app name, greeting, confirmation text, "Go to Dashboard" button, divider, support notice.


Template Categories

Templates are organized into 6 categories:

CategoryDescription
authAuthentication-related emails (verification, password reset, etc.)
marketingPromotional and marketing emails
transactionalOrder confirmations, receipts, notifications triggered by user actions
onboardingUser onboarding sequences and getting-started guides
notificationSystem notifications, alerts, and status updates
customAny other template type

Branding Integration

All email templates automatically inherit the project's branding configuration when rendered. Branding is set in the dashboard under Settings and includes:

  • Primary color — Applied to buttons, links, and headings
  • Background color — Email body background
  • Font family — Applied to all text blocks
  • Logo URL — Displayed in the email header
  • Border radius — Applied to buttons and containers
  • Dark mode — Optional dark mode rendering

This means you configure your brand once, and every email (built-in and custom) uses it consistently.


Dashboard Design Studio

The dashboard includes a visual email editor for building and editing templates:

  1. Block palette — Drag blocks from the sidebar into the canvas. The palette includes all 9 block types with labels and descriptions.
  2. Live preview — See the rendered email update in real time as you edit blocks.
  3. Block properties — Click a block to edit its properties (text, URL, style, etc.) in the inspector panel.
  4. Variable hints — The editor highlights {{variable}} placeholders and shows available variables for built-in templates.
  5. Reorder — Drag blocks to reorder them within the template.
  6. Preview/Test — Send a test email to yourself using the current template and sample data.

SDK / API Usage

Sending Emails

typescript
import { BanataAuth } from "@banata-auth/sdk";
 
const banata = new BanataAuth({
  apiKey: "sk_live_...",
  baseUrl: "https://your-deployment.convex.site",
});
 
// Send a built-in auth email
await banata.emails.send({
  to: "user@example.com",
  template: "verification",
  data: {
    userName: "Jane Doe",
    verificationUrl: "https://app.example.com/verify?token=abc123",
    token: "abc123",
  },
});
 
// Send a custom template by slug
await banata.emails.send({
  to: "user@example.com",
  template: "marketing-welcome",
  data: { userName: "Jane", promoCode: "WELCOME10" },
});

Previewing a Template

Render a template with sample data without sending it:

typescript
const preview = await banata.emails.preview("welcome", {
  userName: "Jane Doe",
  dashboardUrl: "https://app.example.com",
});
 
console.log(preview.subject); // "Welcome to My App"
console.log(preview.html);    // Full rendered HTML
console.log(preview.text);    // Plain text version

Listing Templates

typescript
// List all templates
const allTemplates = await banata.emails.templates.list();
 
// Filter by category
const authTemplates = await banata.emails.templates.list("auth");
const marketingTemplates = await banata.emails.templates.list("marketing");

Getting a Template

typescript
// By ID
const template = await banata.emails.templates.get("etpl_01HXYZ...");
 
// By slug
const template = await banata.emails.templates.get("marketing-welcome");

Creating a Custom Template

typescript
import { createDefaultBlock } from "@banata-auth/shared";
import type { EmailBlock } from "@banata-auth/shared";
 
const blocks: EmailBlock[] = [
  createDefaultBlock("heading"),  // Default h1 heading
  createDefaultBlock("text"),     // Default paragraph
  createDefaultBlock("button"),   // Default CTA button
  createDefaultBlock("divider"),  // Horizontal rule
];
 
// Customize the blocks
blocks[0] = { ...blocks[0], text: "Welcome, {{userName}}!" } as EmailBlock;
 
const template = await banata.emails.templates.create({
  name: "Marketing Welcome",
  slug: "marketing-welcome",
  subject: "Welcome to {{appName}}, {{userName}}!",
  previewText: "Your account is ready",
  category: "marketing",
  description: "Sent to new marketing leads after signup",
  blocksJson: JSON.stringify(blocks),
  variablesJson: JSON.stringify([
    { name: "userName", description: "User's display name", required: true },
    { name: "appName", description: "Application name", required: true },
  ]),
});
 
console.log(template.id); // "etpl_01HXYZ..."

Updating a Template

typescript
const updated = await banata.emails.templates.update("etpl_01HXYZ...", {
  subject: "Welcome aboard, {{userName}}!",
  previewText: "Let's get started",
});

Deleting a Template

typescript
await banata.emails.templates.delete("etpl_01HXYZ...");

Built-in templates (verification, password-reset, magic-link, email-otp, invitation, welcome) cannot be deleted. They can only be customized.


Template Data Model

typescript
interface EmailTemplate {
  id: string;                   // e.g., "etpl_01HXYZ..."
  name: string;                 // "Marketing Welcome"
  slug: string;                 // "marketing-welcome"
  subject: string;              // "Welcome, {{userName}}!"
  previewText?: string | null;  // Inbox preview text
  category: string;             // "auth" | "marketing" | ...
  description?: string | null;  // Template description
  blocksJson: string;           // JSON-serialized EmailBlock[] array
  variablesJson?: string | null; // JSON-serialized EmailTemplateVariable[]
  builtIn: boolean;             // true for the 6 auth templates
  builtInType?: string | null;  // "verification" | "password-reset" | ...
  createdAt: number;
  updatedAt: number;
}

API Endpoints

EndpointMethodDescription
/api/auth/banata/emails/sendPOSTSend an email using a built-in or custom template
/api/auth/banata/emails/previewPOSTPreview a rendered template
/api/auth/banata/emails/templates/listPOSTList all templates (optionally filtered by category)
/api/auth/banata/emails/templates/getPOSTGet a template by ID or slug
/api/auth/banata/emails/templates/createPOSTCreate a new custom template
/api/auth/banata/emails/templates/updatePOSTUpdate an existing template
/api/auth/banata/emails/templates/deletePOSTDelete a custom template

Sending Test Emails

Verify your email provider configuration by sending a test email:

typescript
const result = await banata.emails.sendTest("you@example.com");
 
if (result.success) {
  console.log("Email sent successfully");
} else {
  console.log("Failed:", result.message);
}
 
// Optionally specify a template to test
await banata.emails.sendTest("you@example.com", "password-reset");

What's Next

  • Emails — Configure email providers (SendGrid, Resend, Postmark, etc.)
  • SDK Reference — Complete API reference for the Emails resource
  • Settings — Configure project branding used by email templates