Templates
The Templates system provides email and document content templates that can be used for system emails, session and assignment notifications, study-closed emails, and pre-filled document content. Templates are edited in the same Quill-based Editor as documents; placeholder resolution is done by the backend when the template is used.
Key features include:
Template types with fixed placeholder sets and usage locations (see table below).
Multi-language content stored in
template_content; default language on thetemplaterow.TemplateEditor and TemplateConfigurator (Placeholders sidebar) shown when the Editor is opened with a template (
templateIdprovided).Toolbar and editor behavior controlled by the same settings as the document editor (see Editor Settings).
Overview
Templates are listed and created from Dashboard → Templates. See the dashboard documentation for navigation details.
Location: frontend/src/components/dashboard/Templates.vue
When you open a template for editing, the Editor loads with templateId provided; it renders the Quill Editor (TemplateEditor) for the main content and, for email types (1, 2, 3, 6), a Placeholders sidebar so you can insert allowed placeholders (e.g. ~username~, ~link~) into the text.
Location: frontend/src/components/editor/sidebar/TemplateConfigurator.vue
Backend storage:
template — name, type, public, defaultLanguage, userId.
template_content — content (Quill Delta) per template and language.
template_edit — draft edits per template and language.
placeholder — placeholder keys and labels per template type (used by the frontend sidebar; resolution rules live in the resolver).
Location: backend/utils/templateResolver.js
Placeholder resolution is implemented there: resolveTemplate (returns HTML for emails) and resolveTemplateToDelta (returns Delta for document creation).
Only placeholders listed in PLACEHOLDERS_BY_TYPE for the template’s type are substituted at runtime.
Implementing the Template Editor
The main Editor provides templateId via provide and conditionally shows the Placeholders sidebar when the document is a template with placeholders.
TemplateEditor and TemplateConfigurator are used inside this Editor when editing a template. When the user leaves the editor (e.g. topbar back), draft edits are merged from
template_edit into template_content so that the next resolution uses the latest saved content. See Leaving the template editor below.
Location:
frontend/src/components/editor/Editor.vuefrontend/src/components/editor/template/TemplateEditor.vuefrontend/src/components/editor/sidebar/TemplateConfigurator.vue
<TemplateEditor v-if="templateId" />
<template v-if="templateId && template && !readOnlyOverwrite && hasPlaceholders" #templateConfigurator>
<TemplateConfigurator />
</template>
Leaving the template editor (unsaved changes)
Templates use the same debounced autosave as documents (see Debounce Behaviour). While editing, ops are stored as drafts in template_edit; stable content used by Settings and email resolution lives in template_content.
Save-on-leave: In-app navigation (topbar back, dashboard links) runs beforeRouteLeave in frontend/src/components/Template.vue. The guard calls flushPendingEdits on TemplateEditor (cancels debounce and sends buffered ops), then emits templateClose, which calls saveTemplate in backend/webserver/sockets/template.js to merge drafts into template_content.
Required placeholders: For email types (1, 2, 3, 6, 7), stable template_content in every language must include all required placeholders (getMissingRequiredPlaceholders in backend/utils/templateResolver.js). Enforcement points:
Editor save:
saveTemplaterejects merges that omit required placeholders. The user may confirm discard;templateDiscardDraftssoft-deletes draft rows without updatingtemplate_content.Publish: The
templatemodelbeforeUpdatehook callsassertStableEmailTemplateContentwhenpublicbecomestrue.Settings:
validateEmailTemplateSettingsinbackend/webserver/utils/settingSave.jsruns before persistingemail.template.*keys (missing placeholders in any language row blocks assignment).
Tab close / full reload: beforeunload on TemplateEditor shows the browser’s generic leave warning; the route guard does not run. Orphan drafts may remain until the next visit.
Template Types, Placeholders, and Usage
At resolution time, only the placeholder keys listed in the following table are substituted.
Adding a New Template Type or Placeholder
Note
Placeholders marked with * in the table above are required for that type.
If a required placeholder is missing from stable content in any language, validation
fails on editor save, publish, or Settings assignment until it is added. The set of
required placeholders is defined in the placeholder table (required: true) and
enforced via getMissingRequiredPlaceholders and assertStableEmailTemplateContent
in backend/utils/templateResolver.js.
Here is a concrete example for adding a new placeholder (e.g. studyEndDate for type 6):
Backend (DB + resolver):
Add a row to the
placeholdertable via a migration:type:6(Email - Study Close)placeholderKey:studyEndDateother metadata as needed (label, required, etc.)
Update
PLACEHOLDERS_BY_TYPE/buildReplacementMapinbackend/utils/templateResolver.jsto fillstudyEndDatefrom context, for example:In the resolver, when
context.templateType === 6, setreplacements["~studyEndDate~"] = <value from study or session>.
If the new placeholder is driven by a specific feature (e.g. study close emails), ensure the call site (e.g.
sendStudyClosedEmailsinstudy.js) passes whatever additional data is needed into the resolver context.
Frontend (editor + sidebar):
Add the placeholder to the template configurator configuration so it appears in the Placeholders sidebar with a name/description (e.g. update
placeholderConfigs/longDescriptionsinfrontend/src/components/editor/sidebar/TemplateConfigurator.vue).
Access / type visibility:
If the new placeholder is tied to a new template type, also update:
The template type dropdown in
frontend/src/components/dashboard/templates/TemplateModal.vue.getUserFilterinbackend/db/models/template.jsso that only the correct users (e.g. admins) see or can use that type.
Settings
The template editor uses the same toolbar and edit settings as the document editor. See Editor Settings in the Quill Editor documentation and Adding a New Setting in Settings if you need to add or change a setting key.