Overview

Production Run HTML export templates use Mustache syntax. The data context has two levels:

  • Run-level fields and loops — available directly in the template (batch header, summary, consolidated BOM, boolean flags).
  • Work-order-level fields and loops — available only inside the {{#workOrders}} loop; each iteration exposes the full set of Work Order template placeholders.

Run-level placeholders

Production Run details

PlaceholderDescription
{{batchNumber}}Production run / batch number
{{batchId}}Production run ID
{{batchName}}Production run name
{{status}}Production run status
{{notes}}Production run notes
{{alternateIds}}Comma-separated alternate IDs
{{orderDate}}Date/time the run was created (formatted)
{{orderDate.date}}Date portion only
{{orderDate.time}}Time portion only
{{expectedCompletionDate}}Expected completion date (formatted)

Co-manufacturer (vendor) & warehouse

PlaceholderDescription
{{vendorName}}Vendor / co-manufacturer name
{{vendorEmail}}Vendor email
{{vendorAddress}}Vendor address (single comma-separated line)
{{productionWarehouseName}}Production warehouse name
{{productionWarehouseAddress}}Production warehouse address (single line)

Summary block

All prefixed with summary.:

PlaceholderDescription
{{summary.totalWorkOrders}}Total work orders in the run
{{summary.completedWorkOrders}}Completed work orders
{{summary.inProgressWorkOrders}}In-progress work orders
{{summary.plannedWorkOrders}}Planned work orders
{{summary.draftWorkOrders}}Draft work orders
{{summary.progressPercentage}}Overall progress percentage
{{summary.totalPlannedQty}}Total planned quantity
{{summary.totalCompletedQty}}Total completed quantity
{{summary.totalServiceCost}}Total service cost (formatted currency)

Company & branding

These are the same on Production Run, Work Order, and other document types.

PlaceholderDescription
{{company.name}}Your company name
{{company.logoUrl}}Company logo URL — use in <img src="{{company.logoUrl}}">
{{company.address}}Ship-from / invoice address (plain text; falls back to Company Address if blank)
{{{company.address.html}}}Same address formatted with line breaks and an HTML <address> wrapper (use triple braces)
{{company.email}}Accounting email
{{company.website}}Company website
{{company.phone}}Company phone
{{{poweredByLuminousImg}}}Luminous footer logo (base64 data URI — use triple braces in an <img>)

Note on company.address: This placeholder is present on Production Run templates, identical in shape to other document types. It sources from your Ship-from / Invoice Address setting, falling back to the general Company Address.


Boolean (conditional) flags at the run level

Use these to show or hide entire sections:

FlagWhen it is true
{{#hasConsolidatedBom}}The consolidated BOM has at least one component row
{{#hasWorkOrders}}The run has at least one work order
{{#hasWorkOrdersWithBomComponents}}At least one work order in the run has BOM components

hasWorkOrdersWithBomComponents is the correct run-level gate for a cross-work-order BOM table. Wrap the entire section — including the {{#workOrders}}{{#bomComponents}} inner loop — in this flag so the header and table disappear cleanly when no work order has components.


Consolidated BOM loop — {{#consolidatedBom}} (run level)

This loop aggregates component requirements summed across all work orders in the run. It is the right choice when you want a single run-level material requirements table.

{{#hasConsolidatedBom}}
<table>
  {{#consolidatedBom}}
  <tr>
    <td>{{internalSku}}</td>
    <td>{{productName}}</td>
    <td>{{totalQty}}</td>
    <td>{{uom}}</td>
    <td>{{availableQty}}</td>
  </tr>
  {{/consolidatedBom}}
</table>
{{/hasConsolidatedBom}}
PlaceholderDescription
{{internalSku}}Component SKU
{{productName}}Component product name
{{uom}}Unit of measure
{{isSubAssembly}}True if the component is itself an assembly
{{availableQty}}Current on-hand available quantity for this SKU
{{totalQty}}Total required quantity summed across the entire run
{{workOrderCount}}Number of work orders that require this component
{{workOrderNumbers}}Comma-separated list of those work order numbers
{{skuCustomFields.*}}Dynamic SKU custom fields (keyed by field name)
{{variantAttributes.*}}Dynamic variant attributes (keyed by attribute name)

Sorting: Rows are sorted by internalSku alphabetically.


Work Orders loop — {{#workOrders}} (run level)

Each iteration of this loop renders one work order using the full Work Order view model — every Work Order placeholder is available inside. This is how per-work-order appendices and BOM breakdowns per work order are built.

{{#workOrders}}
  <h2>Work Order {{workOrderNumber}}</h2>
  <p>{{producedSku}} — Planned: {{plannedQuantity}}</p>

  {{#hasBomComponents}}
  <table>
    {{#bomComponents}}
    <tr>
      <td>{{componentSku}}</td>
      <td>{{componentDescription}}</td>
      <td>{{requiredQty}}</td>
      <td>{{availableQty}}</td>
    </tr>
    {{/bomComponents}}
  </table>
  {{/hasBomComponents}}
{{/workOrders}}

Work order header fields (inside {{#workOrders}})

PlaceholderDescription
{{workOrderNumber}}Work order number
{{workOrderId}}Work order ID
{{status}}Work order status
{{notes}}Work order notes
{{alternateIds}}Comma-separated alternate IDs
{{orderDate}}Date/time the work order was created
{{expectedCompletionDate}}Expected completion date

Produced product (inside {{#workOrders}})

PlaceholderDescription
{{producedSku}}Produced (assembly) SKU
{{producedSkuDescription}}Produced product name
{{sourceSku}}The co-manufacturer's own SKU for this product
{{unitName}}Unit of measure name
{{plannedQuantity}}Planned production quantity
{{serviceFeePerUnit}}Service fee per unit (currency)
{{totalServiceCost}}Total service cost — planned qty × service fee (currency)

Completions (inside {{#workOrders}})

PlaceholderDescription
{{producedQuantity}}Total produced quantity
{{scrappedQuantity}}Total scrapped quantity
{{yieldPercentage}}Yield percentage

Vendor & warehouses (inside {{#workOrders}})

PlaceholderDescription
{{vendorName}}Co-manufacturer name
{{vendorEmail}}Co-manufacturer email
{{vendorPhone}}Co-manufacturer phone
{{vendorAddress}}Co-manufacturer address (single line)
{{productionWarehouseName}}Production warehouse name
{{productionWarehouseAddress}}Production warehouse address
{{destinationWarehouseName}}Destination warehouse name

BOM components loop — {{#bomComponents}} (inside {{#workOrders}})

This loop lists the individual BOM component rows for that specific work order (not aggregated).

PlaceholderDescription
{{componentSku}}Component SKU
{{componentDescription}}Component description / product name
{{supplyMode}}Component supply mode
{{qtyPerUnit}}Component quantity required per unit of output
{{requiredQty}}Total required quantity (qty per unit × planned qty for this work order)
{{availableQty}}Current on-hand available quantity for this component SKU
{{skuCustomFields.*}}Dynamic SKU custom fields
{{variantAttributes.*}}Dynamic variant attributes

Production steps loop — {{#productionSteps}} (inside {{#workOrders}})

PlaceholderDescription
{{sequence}}Step sequence number
{{outputSku}}Step output SKU
{{outputName}}Step output product name
{{status}}Step status
{{isOutsideProcessing}}True if the step uses an outside vendor
{{vendorName}}Outside-processing vendor name
{{plannedQuantity}}Step planned quantity
{{completedQuantity}}Step completed quantity
{{remainingQuantity}}Step remaining quantity

Per-work-order boolean flags (inside {{#workOrders}})

FlagWhen it is true
{{#hasBomComponents}}This work order has at least one BOM component
{{#hasProductionSteps}}This work order has at least one production step

Work order custom fields (inside {{#workOrders}})

Access work order-level custom fields by name using {{orderCustomFields.YourFieldName}}.


Quick reference: which loop / field to use for BOM components

GoalLoop to useKey field for SKU
One table with totals across the entire run{{#consolidatedBom}} (run level){{internalSku}}
Per-work-order breakdown (one table per WO){{#workOrders}} → {{#bomComponents}}{{componentSku}}
Hide entire BOM section when nothing exists{{#hasConsolidatedBom}} or {{#hasWorkOrdersWithBomComponents}}—
Hide BOM table for one specific work order{{#hasBomComponents}} (inside {{#workOrders}})—

Common mistake: There is no top-level bomComponents loop, no sharedComponents section, and no hasBomComponents flag at the run level. The run-level aggregated BOM is always under consolidatedBom, and the per-work-order BOM is always bomComponents nested inside {{#workOrders}}.