Uploaded Merge Templates

Print a form from an uploaded Word merge template: choose a print mode, upload a .docx, read the lint report, preview, and export a PDF

What This Feature Does

Every form has one print mode. You either design the PDF in the built-in Document Templates editor, or you upload a Word (.docx) merge template that uses merge tags such as {$site_location}. Switching modes deactivates the other template but keeps the file — you can switch back without re-uploading or rebuilding it.

When the form is in uploaded mode, Preview and Export fill those tags from the submission and return a PDF. Tag mistakes never block an export: a broken tag is printed as written. Only a corrupt file or a system failure stops the merge.

Authoring details — syntax, every supported modifier, and lint codes — live in Merge Tag Authoring.

Choosing a Print Mode

  1. Open the form in the Form Builder
  2. Open the Templates tab
  3. Choose one of the two cards:
CardWhat it usesWhen to pick it
In-app editorThe built-in page editor (${field_name} placeholders)New forms, or layouts you want to design in Pay
Uploaded merge templateA Word .docx you upload ({$field_name} tags)Existing Word templates you want to keep

A form can only print from one of these at a time. The other artefact stays on the form.

Switching when the other mode already has content

If the other mode already has a template, a confirmation dialog appears:

The existing template is deactivated but retained. You can switch back anytime without re-uploading or rebuilding it.

Click Switch to change modes, or Cancel to stay put.

You cannot switch to Uploaded merge template until a file has been uploaded for that form. Save the form first if it is new.

Uploading a Template

  1. Save the form (the dropzone is disabled until the form has an id)
  2. Select Uploaded merge template
  3. Drop a .docx file on the dropzone, or click the dropzone to browse
  4. Wait for the upload to finish
  5. Read the lint report that appears under the dropzone

Available variables

The uploaded-template panel lists every tag this form can fill. System tags are {$id}, {$date}, {$title}, and {$submitted_at} (ISO timestamp — use with date_format; the other date keys are display strings). Project, client, and workpack tags ({$project_name}, {$client_name}, {$workpack_name}, and their number variants) are empty when the submission has no linked project, client, or workpack, so {if $project_name} and |default:'…' behave as expected. Form fields use the field Name from the builder ({$scope_notes}). Names may contain hyphens (auto-generated names like textarea-6c5 are valid). Click a tag to copy it.

Tag with Milo reads the uploaded Word letterhead, proposes which existing slots should get which tags, and waits for you to apply. It does not invent new sections.

Accepted files

  • Extension: .docx
  • Size: 25 MB or smaller
  • The file must be a real Word document (a zip with [Content_Types].xml)
  • PDF files are refused: merge templates are Word documents, and fillable (AcroForm) PDF templates are not supported

Uploading a new file deactivates the previous upload and stores the new one. Switching back to the in-app editor does not delete the uploaded file.

Reading the Lint Report

After upload (and again under Preview), Pay lists every tag it found, plus any problems.

Errors describe tags that will print verbatim in the PDF (the merge still succeeds):

CodeWhat it means for you
MISSING_SIGILThe tag is missing $. {site} will print as {site}; write {$site}.
SMART_QUOTESWord curled the quotes. {$id|pad:5:”0”} will print as written; retype with straight " or '.
UNKNOWN_MODIFIERThat modifier is not in the supported list. The whole tag prints as written.
UNKNOWN_FOREACH_MODIFIERThe modifier on a {foreach} source is not in the supported list. The loop prints nothing; the finding shows the opening tag to search for.
UNBALANCED_BLOCKAn {if} / {foreach} is missing its matching close, or a close/else has no open. Those tags print as written.
BAD_ARGA modifier argument could not be read (often a smart quote inside the argument). The tag prints as written.
UNPARSEABLEThe tag could not be understood at all. It prints as written.

Warnings never change the PDF:

CodeWhat it means for you
EMPTY_TAGAn empty {} was found. Harmless, but remove it.
SPLIT_TAG_RESIDUEWord split the tag across differently formatted runs. The tag may print as fragments. Re-type the whole tag in one style.
UNRESOLVED_PATHShown on preview/export when a path is missing from the sample or submission data. The merge still succeeds.

Lint is advisory. Fix errors so the PDF looks right; they will not stop Preview or Export.

Previewing

  1. With an uploaded template in place, click Preview PDF
  2. Pay fills the template with sample data built from this form (text fields get Sample <label>, numbers 42, dates today, table fields two sample rows, signature fields a bundled signature image)
  3. The merged PDF opens in the preview pane
  4. Any render-time lint findings appear under the preview

Preview and export use the same merge payload shape — the same field keys, column slugs, display strings, and signature data URLs. Preview is not a layout mock; it is the real merge pipeline with sample answers instead of a submission.

The merged Word document is converted to PDF on our servers, so page breaks and fonts can differ slightly from what desktop Word shows.

What Happens on Export

When the form's print mode is Uploaded merge template:

  1. Open the submission (or select submissions and choose Export to PDF)
  2. Pay builds a merge payload from the submission:
    • One key per form field Name (not the label, not the field id). Hyphens in auto-generated names (e.g. textarea-6c5) are valid.
    • Table / repeat fields become arrays of row objects. Each row is keyed by the column header in lower snake case (Used for whole shiftused_for_whole_shift). Nested sub-tables repeat the same pattern. Internal row ids (_rowId, _rowIndex, _createdAt) are not exposed.
    • Cell values are display strings (Resource fields show the name, booleans show Yes or nothing, date cells stay ISO so date_format works). A header that starts with a digit gets a leading underscore (1st Shift_1st_shift). Signature and drawing answers are data: URLs — use {$field|insert_image:W:H} to embed them; a bare {$field} prints the raw URL as text.
    • Reserved extras: {$id} (submission id), {$date} / {$submission_date} (formatted submitted-at display strings), {$submitted_at} (raw ISO timestamp — use with date_format), and {$title} (form title). Do not name a form field id, date, title, or submitted_at.
  3. The active uploaded template is merged
  4. The result is converted to PDF and downloaded (or prepared in the background for larger jobs)

When the form's print mode is In-app editor, export uses the Document Templates path unchanged.

A broken or unresolvable tag never fails the export. The tag is left as written (or, for a missing field, rendered as blank — see passthrough). Only a corrupt template file or an infrastructure failure (timeout, storage, converter) fails the job.

Switching Back (Rollback)

  1. Open the form → Templates tab
  2. Click In-app editor
  3. Confirm the switch

The uploaded file stays on the form, deactivated. Click Uploaded merge template later to reactivate the same file — no re-upload.

Switching the other way keeps the in-app editor template as well.

Limitations

  • One print mode per form. A form prints from either its uploaded Word template or the in-app editor. Switching keeps both.
  • Uploads are Word .docx files and the output is PDF. PDF, Excel, PowerPoint and HTML files are not accepted as form print templates; fillable PDF forms need rebuilding as Word merge templates.
  • {assign}, {math}, and {include} are not supported. If they appear, they print as written.

Troubleshooting

The dropzone says to save the form first

Create and save the form, then return to the Templates tab. Uploads need a form id.

I cannot switch to Uploaded merge template

Upload a .docx first. Switching to uploaded mode with no file on the form is rejected.

The lint report shows SMART_QUOTES

Word replaced "0" with ”0”. Delete the quotes and type straight " characters, then re-upload.

The lint report shows MISSING_SIGIL

A tag is missing $. {crew_lead} must be {$crew_lead}.

Preview is empty or the PDF looks wrong

  • Confirm the print mode card is Uploaded merge template
  • Confirm the field Name in the form builder matches the tag path
  • Read the lint report — errors print verbatim
  • Re-type any tag Word split across bold/italic runs (SPLIT_TAG_RESIDUE)

Export still uses the in-app editor layout

The form is still in In-app editor mode. Switch to Uploaded merge template (this requires an uploaded file).

My table renders nothing

  • Confirm the {foreach} wraps a whole table row and the open/close tags sit in the first and last cells.
  • Row tags must use the column header in lower snake case, not the label as typed in Word. Example: header Used for whole shift{$row.used_for_whole_shift}, not {$row.Used for whole shift}.
  • Copy column tags from the uploaded-template panel — they match the payload keys.
  • For nested sub-tables, repeat {foreach $nested_field as $subrow}{$subrow.<column>}{/foreach} inside the parent row.

My signature prints as text

Signature and drawing answers arrive as data:image/… URLs (photo and file-upload answers are file names, not images). A bare {$sign} tag prints that URL as text. Use {$sign|insert_image:200:80} (adjust width and height in pixels). The uploaded-template panel advertises the recommended tag for image field types.

What's Next