Documents Template

This manual is intended for designers and developers who need to modify the HTML templates used to generate medical documents (treatment letters, aligner labels, order labels).

How the Template System Works

At a high level, the document generation process follows these steps:

  1. The selected HTML template is loaded.
  2. The system scans the HTML for tags (e.g. [PATIENT_NAME], [INTRAORAL_FRONTAL_PHOTO], etc.).
  3. Text tags are replaced with treatment data.
  4. Legend tags are replaced using the definitions inside the HTML comment block.
  5. Special tags are converted into embedded images.
  6. The final HTML is generated and sent to the browser for printing.

Default Templates

Titan includes three built-in document templates. Download them as a starting point and modify the HTML to create your own custom designs.

Document Description Download
Treatment Letter Full treatment summary with tooth diagrams, intraoral photos, IPR values, attachment ranges, and legend icons. Uses all tag types (simple, special, and legend). Titan Default Template
Aligner Label Compact 3×4 in label for individual aligner bags. Displays lab, doctor, patient name, and aligner details. Titan Default Template
Patient Label 4×6 in order label shipped with a batch of aligners. Shows doctor address, patient info, upper/lower aligner counts, and attachment templates. Titan Default Template

Tags

Type Description Example
Simple Plain text that is directly replaced. [PATIENT_NAME]
Special Take photos of the teeth [INTRAORAL_FRONTAL_PHOTO]
Legend Are defined within HTML comments and are used for icons or symbols MISSING_TOOTH

Simple Tags

These tags are replaced with plain text from the treatment database.

Tag Description
[PATIENT_NAME] Full name of the patient.
[DOCTOR_NAME] Name of the treating doctor.
[LAB_NAME] Name of the lab.
[DATE] Creation date of the document (format: yyyy-MM-dd).
[TOTAL_PAGES] Total number of pages in the document.
[ACTIVE_ALIGNER] Ranges of active aligners.
[OVERCORRECTIONS] Ranges of overcorrection aligners.
[ACTIVE_RETAINERS] Ranges of active retainers.
[ATTACHMENT_LINGUAL] List of teeth with lingual attachments.
[ATTACHMENT_ARCH] Ranges of attachment templates provided.
[TWIN_BLOCKS] Aligner range covered by twin block attachments (e.g. 0-20). Empty when the treatment has none.
[TREATMENT_NOTES] Custom notes written by the doctor for the treatment.
[ADDRESS] Lab's address.
[MAXILLA_RANGE] Maxillary arch range.
[MANDIBLE_RANGE] Mandibular arch range.
[MAX_RANGE_MAXILLA] Total number of maxillary aligners.
[MAX_RANGE_MANDIBLE] Total number of mandibular aligners.
[ALIGNER_DETAILS] Additional aligner-specific info.
[MORE_DETAILS] Extra details like split info.
[MADE_IN] Country of manufacture.

Example

<p>Patient: [PATIENT_NAME]</p>
<p>Doctor: [DOCTOR_NAME]</p>
<p>Date: [DATE]</p>

Output

<p>Patient: John Doe</p>
<p>Doctor: Dr. James Wilson</p>
<p>Date: 2021/12/05</p>

You can wrap simple tags inside any HTML element. The system only replaces the tag text, it does not modify your layout.

Required Rules

  • Tags must include square brackets.
  • Tag names must match exactly (case-sensitive).
  • Tags can be placed inside any HTML element.
  • Every occurrence is replaced, including inside <script> blocks and HTML comments. Do not write a tag name in a script to check whether it was replaced; match the bracketed form instead (for example /^\[.*\]$/).

Special Tags

These tags are used to take photos of the teeth in different views.

Tag Description
[INTRAORAL_FRONTAL_PHOTO] Frontal intraoral photo of the patient.
[INTRAORAL_RIGHT_LATERAL_PHOTO] Right lateral intraoral photo.
[INTRAORAL_LEFT_LATERAL_PHOTO] Left lateral intraoral photo.
[INTRAORAL_UPPER_PHOTO] Photo of the upper arch.
[INTRAORAL_LOWER_PHOTO] Photo of the lower arch.
[INTRAORAL_UPPER_OCCLUSAL_PHOTO] Occlusal photo of the upper arch.
[INTRAORAL_LOWER_OCCLUSAL_PHOTO] Occlusal photo of the lower arch.
[INTRAORAL_OVERJET_VIEW_PHOTO] Overjet view photo.

Required Rules

  • Must be inside an element with class image-placeholder.
  • Do not wrap the tag inside additional nested elements.
  • Do not rename the class image-placeholder.
  • Only one special tag per placeholder container.

If these rules are not followed, the image may not render.

Example usage in HTML

<div class="image-container">
    <div class="image-placeholder image filled">[INTRAORAL_RIGHT_LATERAL_PHOTO]</div>
</div>

Legend Tags

Legend tags are used for icons and visual tooth indicators. These tags are defined in a special comment block at the end of the template.

Location in HTML

<!--
----------------------------------------------------------------------
Custom Legend Tags:
----------------------------------------------------------------------
<div data-legend-key="MISSING_TOOTH">
    <span class="material-icons">close</span>
</div>
<div data-legend-key="EXTRACTION_TOOTH">
    <span class="material-icons red">close</span>
</div>
... (more definitions) ...
----------------------------------------------------------------------
End of Custom Legend Tags:
----------------------------------------------------------------------
-->

How it works

  1. The system scans the HTML for this comment block.
  2. It extracts each <div> with the attribute data-legend-key="KEY_NAME".
  3. The inner HTML of that <div> becomes the replacement template for the legend key KEY_NAME.

Required Rules

  • Must be inside an HTML comment block.
  • Must use data-legend-key="KEY_NAME".
  • The key must match the query name exactly.
  • Do not remove the comment delimiters.
  • The legend block must remain at the end of the template.

If the legend block is removed, all conditional icons will fail.

Treatment Letter Processing Rules

Tooth Features

Each tooth in the treatment plan is evaluated for a set of visual features. These features can be either global (apply to the entire tooth) or side-specific (apply only to the buccal or lingual view).

Feature Type Query Key Description
Missing Tooth Global MISSING_TOOTH The tooth is not present in the treatment.
Extraction Tooth Global EXTRACTION_TOOTH The tooth is scheduled for extraction.
Pontics Global PONTICS A pontic is present in this position.
Tunnel Side-Specific TUNNEL A tunnel attachment is present on the specified side.
Attachments Side-Specific ATTACHMENTS A standard attachment is present on the specified side.
Bite Ramps Side-Specific BITE_RAMPS A bite ramp is present on the specified side.
Cutouts Side-Specific CUTOUTS Precision cuts are present on the specified side.
Elastic Cuts Side-Specific ELASTIC_CUTS Cuts for elastic hooks are present on the specified side.
Power Ridges Side-Specific POWER_RIDGES Power ridges are present on the specified side.
Pressure Points Side-Specific PRESSURE_POINTS Pressure points are present on the specified side.

How it works in the HTML

  • A tooth element is defined with a tag attribute (e.g., tag="TOOTH_UR8").
  • Conditional queries are placed inside the element (e.g., [ATTACHMENTS?][BITE_RAMPS?]).
  • The system uses the CSS class of the parent container (buccal-view or lingual-view) to determine which side-specific features to evaluate.
  • If a feature is present, its legend template (from the Custom Legend Tags comment block) is rendered. If not, the query is removed, leaving the element empty (and thus hidden).

Required Structure (Tooth Containers)

<div class="tooth-state buccal-view" tag="TOOTH_UR4" hidden>
    [ATTACHMENTS?]
</div>

Required Rules

  • Must include tag="TOOTH_XXX".
  • Must include either buccal-view or lingual-view for side features.
  • Must include hidden attribute initially.
  • Tag names must follow exact tooth naming convention.

If a container becomes empty after processing, it will be removed.

[OVERVIEW] Feature

The [OVERVIEW?] query is a special conditional feature used in Treatment Letter templates. It displays a single visual indicator per tooth, automatically selecting the highest-priority feature present for that tooth. This is useful when you want a simplified representation instead of rendering multiple icons.

Instead of writing multiple conditional queries like:

[EXTRACTION_TOOTH?][MISSING_TOOTH?][ATTACHMENTS?][BITE_RAMPS?]

You can simply use:

[OVERVIEW?]

The system will decide which feature to display.

Conditional Query

Conditional queries control whether a feature renders.

Syntax

[FEATURE_KEY + ?]

Example usage in HTML

<div class="tooth-state buccal-view" tag="TOOTH_UR8" hidden>
    [ATTACHMENTS?]
</div>

If the feature exists:

  • hidden is removed

  • The legend template is inserted

If not:

  • The container is removed

Required Rules

  • Must include the question mark ?.
  • Must be inside a container with a valid tag attribute.
  • Container must start with hidden.
  • Must use valid tooth tag format (e.g., TOOTH_UR8).

IPR

IPR information is displayed in the spaces between teeth.

How it works in the HTML

  • An IPR space is defined as a div with class="container-ipr" and a tag attribute (e.g., tag="TOOTH_UR5-UR4").
  • The container must also have a class of ipr-above (for upper arch) or ipr-below (for lower arch) to control the layout.
  • The placeholder [IPR] inside the .grid-area div is replaced with the final IPR values and the horizontal lines.

Required Rules

  • Must include class container-ipr.
  • Must include either ipr-above or ipr-below.
  • Must include valid adjacent tooth tag format.
  • Must contain [IPR] inside .grid-area.

If no IPR exists for that space, the entire container is removed from the final document.

Example usage in HTML

<div class="container-ipr ipr-above" tag="TOOTH_UR5-UR4">
    <div class="grid-area">[IPR]</div>
</div>

Aligner Ranges

Aligner ranges show the stages for which a feature (like an attachment) is active on a specific tooth.

Key Rules

  • Side-Specific: The range displayed depends on the view (buccal-view or lingual-view). The system will show the range for attachments on the relevant side.
  • Combined Ranges: If a tooth has attachments on both sides, the ranges are combined and displayed in the overview ([OVERVIEW?]) query.

How it works in the HTML

  • An aligner range indicator is a div with class="container-line", a tag attribute (e.g., tag="TOOTH_UR8"), and a view class (e.g., class="buccal-view").
  • The query [ALIGNER_RANGE?] inside this container is replaced with the text of the range (e.g., 3-14).
  • If no range exists for that tooth and side, the entire container-line block is removed from the document.

If a range exists:

  • hidden is removed

  • Range text (e.g. 3-14) is inserted

If no range exists:

  • The entire container is removed

Example usage in HTML

<div class="container-line buccal-view" tag="TOOTH_UR8" hidden>
    <div>[ALIGNER_RANGE?]</div>
</div>

General Customization Guidelines

You may safely:
- Modify CSS
- Change layout
- Resize icons
- Change fonts
- Move containers
- Add page breaks

Do NOT:
- Rename required classes (image-placeholder, container-ipr, container-line)
- Remove the legend comment block
- Remove tag attributes
- Remove hidden from conditional containers
- Change tag keys

If these structural elements are modified or removed, certain features may not render correctly.

Internationalization (Multi-language)

Templates can render their static text in multiple languages. Translation runs in the browser/headless renderer via a small shared script; the template is self-contained (it references the script itself). English is the source language and stays inline in the HTML — you only add translations for the other languages.

Supported language codes: es, pt-BR, fr, ja, ko (English needs no entry).

How it works

  1. The template's <head> references the shared translation script.
  2. A JSON block maps each exact English text to its translations.
  3. Every translatable element is marked with class="tr"; the script looks up its trimmed text in the JSON and replaces it.
  4. The language is chosen from data-lang (the app fills the [DOC_LANG] token with the current app language). On older app builds that don't fill the token, the script falls back to the browser language.

The script only translates. Auto-print is handled separately, so you never add print code to the template.

What to add to a template

1. Reference the script in <head>:

<script src="https://server.titandentaldesign.com/cloud/downloads/templates/titan-doc-i18n.js"></script>

(Use the absolute URL — the printed document is opened from a temp file, so relative paths do not work. Mirror the host used by the template images.)

2. Add the translations block (anywhere in the body; keep id, type and the data-lang token exactly):

<script id="titan-translations" type="application/json" data-lang="[DOC_LANG]">
{
  "Upper:":        { "es": "Superior:", "pt-BR": "Superior:", "fr": "Supérieur :", "ja": "上顎:", "ko": "상악:" },
  "Patient Name:": { "es": "Paciente:", "pt-BR": "Paciente:", "fr": "Patient :", "ja": "患者名:", "ko": "환자 이름:" }
}
</script>

3. Mark each static text with class="tr":

<p class="patient-title tr">Orthodontic Aligner Appliances for:</p>

Required rules

  • Mark only fully-static text. Data tags ([PATIENT_NAME], etc.) are replaced before the browser runs, so an element like of [MAX_RANGE_MAXILLA] would no longer match its key. Wrap just the static word in its own span:
    ```html

    of [MAX_RANGE_MAXILLA]

`` - The JSON key must be the English text **exactly and trimmed**, identical to what the element shows. - Do **not** put data tags ([...]) inside translation values. - Do **not** remove or renamedata-lang="[DOC_LANG]", theid="titan-translations", or theclass="tr"` markers.
- If the block or the script is missing, the document still prints — just untranslated (English).

Consistency with the app UI

For clinical/appliance terms, reuse the app's existing translations (I2 term path TreatmentOverview Popup/*) so the printed document matches the on-screen wording — e.g. Attachment → Atache, Power Ridge → Cresta de Poder, Bite Ramp → Rampa Mordida.

Deployment note

titan-doc-i18n.js lives in the shared cloud/downloads/templates/ folder on each server (that is the URL every template points to). The default template HTML files are served per environment (Dev from the shared folder; QA/EA/Live from their versioned folder). These assets are uploaded manually (not by the standard PHP deploy), so a template/JS change must be copied to the server’s downloads/templates locations to take effect. Template files are served without a Cache-Control header, so after updating one, bypass caches when verifying (e.g. append ?v=123).