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
| Placeholder | Description |
|---|
{{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
| Placeholder | Description |
|---|
{{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.:
| Placeholder | Description |
|---|
{{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.
| Placeholder | Description |
|---|
{{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:
| Flag | When 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}}
| Placeholder | Description |
|---|
{{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}}
| Placeholder | Description |
|---|
{{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}})
| Placeholder | Description |
|---|
{{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}})
| Placeholder | Description |
|---|
{{producedQuantity}} | Total produced quantity |
{{scrappedQuantity}} | Total scrapped quantity |
{{yieldPercentage}} | Yield percentage |
Vendor & warehouses (inside {{#workOrders}})
| Placeholder | Description |
|---|
{{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).
| Placeholder | Description |
|---|
{{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}})
| Placeholder | Description |
|---|
{{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}})
| Flag | When 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
| Goal | Loop to use | Key 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}}.
Related articles