Headless LMS
Email

React Email

Render transactional emails from React Email components with the email-templates adapter.

@headless-lms/adapter-email-templates implements the TemplateRenderer port with React Email. Given a template id and its params, it renders subject, HTML, and plain text at call time; the email adapter then delivers the result.

main.ts
import { ReactEmailTemplateRenderer } from "@headless-lms/adapter-email-templates";

const container = await createContainer(config, {
  adapters: { templates: new ReactEmailTemplateRenderer() },
});

The adapter needs no configuration of its own — branding comes from the server config (see below).

The template catalog

The catalog is closed and typed: every template id in EmailTemplateParams (from @headless-lms/types) must have an entry, or the adapter fails to typecheck. The server ships these templates:

TemplateSent when
magicLinkA user signs in with a magic link
emailVerificationA user must verify their email address
passwordResetA user requests a password reset
studentInviteA student is invited to the student portal
memberInviteA staff member is invited to an organization
accessGrantedA student is granted access to content
accessRevokedA student's access to content is revoked
courseCompletedA student completes a course

Branding

Every template receives a TemplateContext — brand name, base URL, student portal URL, and an optional logo — threaded in from the server config. The reference installation maps these from env:

VariableMaps toNotes
BRAND_NAMEbrandNameShown in every email. Defaults to Headless LMS.
EMAIL_LOGO_URLlogoUrlOptional logo at the top of each email.
ADMIN_APP_URLbaseUrlOrigin staff-facing links resolve against.
STUDENT_PORTAL_URLstudentPortalUrlOrigin student-facing links resolve against.

Previewing templates

The package ships React Email's dev server for previewing templates in the browser:

pnpm --filter @headless-lms/adapter-email-templates dev

Using your own templates

Implement the TemplateRenderer port from @headless-lms/types — one render(id, ctx, params) method returning { subject, html, text } — and pass it in the templates slot. The typed catalog guarantees you handle every email the server can send.

On this page