Feature: Message Templating
Relevant source files
The following files were used as context for generating this wiki page:The Message Templating feature is a core component of MessageJS that allows developers to create, manage, and use reusable message formats. Templates contain a predefined message body with placeholders (variables) that can be dynamically populated with data when a message is sent. This system simplifies sending personalized messages at scale, such as OTPs, welcome messages, or notifications.
Templates are created and managed per-project through the Dashboard API and are identified by a unique templateId. When sending a message via the SDK, instead of providing a raw message string, a developer can specify a templateId and a corresponding set of templateVars to populate the placeholders.
Data Model and Schema
The foundation of the templating feature is the Template data model, which is stored in the PostgreSQL database and defined in the Prisma schema.
Sources: packages/core/prisma/schema.prisma, packages/core/src/types/dataModels.ts
ER Diagram
The following diagram illustrates how the Template model relates to the Project model. Each template must belong to a single project.
Template Model Fields
The Template model contains the necessary fields to define a reusable message.
| Field | Type | Description |
|---|---|---|
id | String | A unique identifier for the template (e.g., tpl_abc123). |
projectId | String | A foreign key linking the template to a Project. |
name | String | A user-defined name for the template (e.g., "Welcome Message"). |
body / content | String | The template content with placeholders, e.g., "Your OTP is {{code}}.". |
variables | Record<string, any> | An object containing example or default variables. |
connectorType | ConnectorType | The type of connector the template is associated with (e.g., whatsapp). |
createdAt | DateTime | The timestamp when the template was created. |
Sources: packages/core/prisma/schema.prisma:67-75, packages/core/src/types/dataModels.ts:100-108, API_REFERENCE.md:364-370
The TypeScript interface for this model is defined as:
// Source: packages/core/src/types/dataModels.ts:100-108
export interface Template {
id: string;
projectId: string; // Foreign key to Project
name: string;
connectorType: ConnectorType;
content: string; // The template body, e.g., "Your code is {{otp}}"
variables: Record<string, any> | null; // Example/default variables
createdAt: Date;
}
Template Management via API
Templates are managed via a set of RESTful endpoints under /api/v1/projects/:projectId/templates. These endpoints are intended to be used by the MessageJS Dashboard for CRUD (Create, Read, Update, Delete) operations.
Sources: API_REFERENCE.md:347-414
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /api/v1/projects/:projectId/templates | Creates a new template within a project. |
GET | /api/v1/projects/:projectId/templates | Lists all templates for a given project. |
GET | /api/v1/projects/:projectId/templates/:id | Retrieves a single template by its ID. |
PUT | /api/v1/projects/:projectId/templates/:id | Updates an existing template's content or variables. |
DELETE | /api/v1/projects/:projectId/templates/:id | Deletes a template. |
Sources: API_REFERENCE.md:347-414
Creating a Template
To create a template, a POST request is sent with the template's details.
Request Body (POST /.../templates)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | A descriptive name for the template. |
connectorType | string | Yes | The connector type, e.g., whatsapp. |
content | string | Yes | The message body with {{variable}} placeholders. |
variables | string[] | Yes | An array of variable names found in the content. |
Sources: API_REFERENCE.md:364-370
The following sequence diagram shows the flow for creating a template.
Sources: API_REFERENCE.md:359-376
Sending a Message with a Template
The primary use of templates is to send messages through the SDK or the core sendMessage API endpoint. Instead of passing a raw message, the client provides a templateId and a variables object.
Data Flow for Sending a Templated Message
The following diagram illustrates the sequence of events when a client sends a message using a template.
SDK Usage
The client SDK provides a simple sendMessage method. To use a template, the templateId and templateVars (or variables) parameters are used.
SDK sendMessage Parameters
| Parameter | Type | Description |
|---|---|---|
to | string | The recipient's identifier (e.g., phone number). |
templateId | string | The ID of the template to use (e.g., welcome). |
templateVars | object | Key-value pairs to replace variables in the template. |
connector | string | The connector to use (e.g., whatsapp). |
Sources: QUICK_START.md:131-142, packages/client/src/index.ts:41-59
Here is an example of how to use it in the SDK:
// Source: QUICK_START.md:131-142
const result = await messagejs.sendMessage({
to: '+1234567890',
templateId: 'welcome',
templateVars: {
name: 'John',
company: 'MyCompany',
code: '12345'
},
connector: 'whatsapp'
});
API Request Body
The SDK call translates to a POST request to /api/v1/messages. The SendMessageRequest interface defines the structure of this request.
// Source: packages/core/src/types/apiTypes.ts:35-44
export interface SendMessageRequest {
connectorId: string;
templateId: string;
to: string;
variables: Record<string, any>;
metadata?: Record<string, any>;
}
Upon receiving this request, the sendMessage controller in the core API is responsible for fetching the template, creating a message log, and queuing the message for delivery.
Sources: packages/core/src/api/controllers/messageController.ts:21-25
Summary
The Message Templating feature is integral to MessageJS, providing a robust mechanism for sending dynamic and personalized messages. It separates message content from application logic by storing templates in the database, which are managed via a dedicated API. When sending a message, the client SDK uses a templateId and variables, which the backend then processes to queue the final, rendered message for delivery through the appropriate connector. This architecture promotes reusability, maintainability, and scalability.