Skip to main content

ITemplateStore

ITemplateStore is the optional interface that powers the dynamic email template and UI i18n systems in awesome-node-auth. Implement it against your database to:

  • Override any built-in transactional email (password reset, magic link, welcome, etc.) with custom HTML/text and per-language translations
  • Inject page-specific UI translation strings into the built-in login/register pages at render time

Types

MailTemplate

export interface MailTemplate {
/** Template identifier. Built-in IDs: 'magic-link' | 'password-reset' | 'welcome' | 'verify-email' | 'email-changed' */
id: string;

/** HTML body. Use {{T.key}} for translated strings and {{VAR}} for data variables. */
baseHtml: string;

/** Plain-text fallback body. Same placeholder syntax. */
baseText: string;

/** Per-language translation map: lang → { key: value } */
translations: Record<string, Record<string, string>>;
}

UiTranslation

export interface UiTranslation {
/** Page identifier. Built-in pages: 'login' | 'register' | 'forgot-password' | 'reset-password' | 'magic-link' | 'verify-email' | '2fa' | 'link-verify' | 'account-conflict' */
page: string;

/** Per-language translation map: lang → { data-i18n-key: text } */
translations: Record<string, Record<string, string>>;
}

Interface definition

export interface ITemplateStore {
/** Retrieve a mail template by ID. Returns null if not found (built-in fallback is used). */
getMailTemplate(id: string): Promise<MailTemplate | null>;

/** List all stored mail templates. */
listMailTemplates(): Promise<MailTemplate[]>;

/** Create or update a mail template. */
updateMailTemplate(id: string, template: Partial<MailTemplate>): Promise<void>;

/** Retrieve UI translations for a specific page. Returns null if not found. */
getUiTranslations(page: string): Promise<UiTranslation | null>;

/** List all stored UI translation sets. */
listUiTranslations(): Promise<UiTranslation[]>;

/** Create or update UI translations for a page. */
updateUiTranslations(page: string, translations: Record<string, Record<string, string>>): Promise<void>;
}

Built-in implementation

MemoryTemplateStore is a zero-dependency in-memory implementation ready for development and testing:

import { MemoryTemplateStore } from 'awesome-node-auth';

const templateStore = new MemoryTemplateStore();

Replace it with a database-backed implementation in production (see Mailer → Dynamic templates).


Wiring

Pass templateStore to both AuthConfigurator and createAdminRouter:

import { AuthConfigurator, createAdminRouter, MemoryTemplateStore, buildUiRouter } from 'awesome-node-auth';

const templateStore = new MemoryTemplateStore();

const auth = new AuthConfigurator(
{
// ... JWT secrets & mailer config ...
templateStore, // ← enables dynamic email templates
},
userStore,
);

// (optional) Enable i18n injection into built-in UI pages
app.use('/auth/ui', buildUiRouter({
authConfig,
apiPrefix: '/auth',
templateStore,
}));

// (optional) Enable the 📧 Email & UI tab in the Admin Panel
app.use('/admin', createAdminRouter(userStore, {
accessPolicy: 'first-user',
jwtSecret: process.env.ACCESS_TOKEN_SECRET!,
templateStore,
}));

Interpolation reference

Email templates

SyntaxSourceExample output
{{T.key}}MailTemplate.translations[lang][key]"Reset your password"
{{URL}}Reset / magic-link / verify URL"https://app.com/reset?token=…"
{{newEmail}}New email address (email-changed template)"new@example.com"
{{loginUrl}}Login page URL (welcome template)"https://app.com/login"

A missing key renders as [key] to help with debugging.

UI translations

Each data-i18n attribute value on a built-in HTML element is looked up in UiTranslation.translations[lang]. The key must exactly match the attribute value:

<h2 data-i18n="title">Sign in</h2>
<!-- resolved by: translations["en"]["title"] → "Sign in" -->

Admin REST API

When templateStore is provided to createAdminRouter, the following endpoints are activated:

MethodPathDescription
GET/admin/api/templates/mailList all mail templates
POST/admin/api/templates/mailCreate or update a mail template (body: { id, baseHtml, baseText, translations })
GET/admin/api/templates/uiList all UI translation sets
POST/admin/api/templates/uiCreate or update UI translations (body: { page, translations })