Skip to content
View as Markdown

Label Templates ​

A label template is a JSON file in workspace/labels/ named <name>.label.json. The LabelPrinter driver renders it with the data you pass to print() and sends the result to the printer. Scripts can also pass the same object inline (print({ template: { size, elements }, data })) for fully dynamic layouts. Templates reload automatically when the file changes. You do not have to write this by hand: Tools → Label Printing → Templates → Design opens a template in the visual designer, which reads and writes exactly this schema (see the guide).

json
{
  "name": "shipping",
  "size": { "width": 62, "height": 100, "unit": "mm" },
  "dpi": 300,
  "font": "Arial",
  "fields": {
    "product": { "required": true },
    "serial":  { "required": true },
    "qty":     { "default": "1" }
  },
  "elements": [
    { "type": "text",    "x": 4, "y": 4,  "w": 54, "h": 12, "text": "{{product}}", "size": 16, "bold": true, "shrink": true },
    { "type": "text",    "x": 4, "y": 17, "w": 54, "h": 8,  "text": "Qty {{qty}} · {{date|yyyy-MM-dd}} · #{{sequence|pad:6}}", "size": 8 },
    { "type": "barcode", "x": 4, "y": 33, "w": 54, "h": 20, "symbology": "code128", "value": "{{serial}}", "showText": true },
    { "type": "barcode", "x": 4, "y": 57, "w": 30, "h": 30, "symbology": "qr", "value": "https://example.com/t/{{serial}}" },
    { "type": "image",   "x": 36, "y": 57, "w": 22, "h": 22, "src": "logo.png", "fit": "contain" },
    { "type": "rect",    "x": 1, "y": 1,  "w": 60, "h": 98, "strokeWidth": 0.3, "radius": 2 },
    { "type": "line",    "x1": 4, "y1": 30, "x2": 58, "y2": 30 }
  ]
}

Page ​

KeyTypeDefaultDescription
namestringfile stemShown in listTemplates() and the {{template}} placeholder
size.width, size.heightnumberrequiredLabel size in size.unit
size.unitstring"mm"mm | cm | in | pt | px — also the unit for every element coordinate
dpiint300Design resolution: used for px units and as the render resolution when the printer's is unknown (previews, PDF)
orientationstring"portrait"landscape rotates the finished page 90° for stock that feeds the other way (tape printers)
backgroundstring"#FFFFFF"Page colour (#RGB, #RRGGBB, #RRGGBBAA or a CSS name)
fontstring"Arial"Default font family for text and barcode captions
fontSizenumber10Default text size in points
fieldsobject—Declared data fields (see below)
elementsarray—Drawn in order; later elements paint over earlier ones

Coordinates are measured from the top-left corner; x, y, w, h are in size.unit. Every element also accepts:

KeyDescription
idName used in error messages (defaults to #index)
rotateClockwise rotation in degrees around the element's centre
whenPlaceholder expression; the element is skipped when it expands to empty, false, 0, no or null

Fields ​

fields declares what data the template expects. Undeclared placeholders still resolve from data; declaring them gives validation and defaults.

json
"fields": {
  "serial":      { "required": true },
  "destination": { "default": "" },
  "lot":         "L0"
}

A required field that is missing from data fails print() with VALIDATION_INVALID_VALUE listing every missing name. A field with a default uses it when absent. validateTemplate() warns about placeholders that are not declared and fields that are never used.

Elements ​

text ​

KeyDefaultDescription
text—The text; supports placeholders and \n
font, sizetemplate defaultsFamily and size in points
bold, italicfalseWeight / slant
color#000000Text colour
alignleftleft | center | right
valigntoptop | middle | bottom
wraptrueWord-wrap inside the box (long words break by character)
shrinkfalseReduce the size (down to 4 pt) until the text fits the box
lineHeight1.2Line spacing as a multiple of the font size

Text is clipped to its box. Fonts come from the server's operating system; a family that is not installed falls back to the default sans-serif.

barcode ​

KeyDefaultDescription
symbologycode128See the table below (type: "qr" is shorthand for symbology: "qr")
value—Encoded content; supports placeholders
showTextfalsePrint the human-readable value under 1D codes
textSize, font7 pt, template fontCaption styling
color#000000Bar colour
errorCorrectionper symbologyQR L | M | Q | H; PDF417 0–8; Aztec percentage
marginstandard quiet zoneQuiet zone in modules per side reserved inside the box (0 uses the whole box)
SymbologyKindValue rules
code1281DASCII 0–127
code391DA–Z, 0–9, space, - . $ / + % (lower case is upper-cased)
code931DSame set as Code 39
ean131D12 digits (13 with a valid check digit)
ean81D7 digits (8 with check digit)
upca1D11 digits (12 with check digit)
upce1D7 digits (8 with check digit), starting with 0 or 1
itf1DDigits, even count (a leading 0 is added to odd lengths)
codabar1DDigits and - $ : / . +; start/stop A–D added automatically
qr2DAny text (UTF-8)
datamatrix2DAny text
pdf4172D (stacked)Any text
aztec2DAny text

Modules are scaled by a whole number of device pixels and drawn without anti-aliasing so they scan reliably at 203–360 dpi. The code is centred in its box; 1D codes stretch to the box height (minus the caption). If the box is too small for one pixel per module, print() fails with a message that says how large the box needs to be at the printer's dpi. Standard quiet zones are reserved by default — 10 modules for 1D codes, 4 for QR, 2 for Data Matrix / PDF417, 1 for Aztec — because scanners reject symbols without them (UPC/EAN end guards in particular).

TIP

Barcodes render in previews on every tier. Printing them (like any label) to a real printer needs the Label Printing feature (Pro).

image ​

KeyDefaultDescription
src—File name relative to workspace/labels/ (PNG, JPEG, BMP, WebP …), a data:image/…;base64, URL, or a placeholder whose data value is base64 (a snapshot() from a camera)
fitcontaincontain (keep aspect, fit inside) | cover (keep aspect, fill and crop) | stretch

File images must live inside the templates directory; paths that escape it are rejected.

rect ​

KeyDefaultDescription
fillnoneFill colour
stroke#000000Outline colour (null/"none" for no outline)
strokeWidth0.3Outline width in template units, drawn inside the box
radius0Corner radius in template units

line ​

x1, y1, x2, y2 in template units, plus stroke (#000000) and strokeWidth (0.3).

Placeholders ​

{{name}} anywhere in text, value, src or when is replaced at print time. Look-up order: data (exact, then case-insensitive), dotted paths into nested objects ({{order.id}}), built-ins, then the field's default.

Built-inValue
{{sequence}}The connector's running counter; increments per printed label (not for previews) and persists across restarts. Set it with the sequence property
{{date}}, {{time}}, {{now}}Render time — combine with a format: `{{now
{{copy}}Copy number (1-based)
{{page}}, {{pages}}Position within a printBatch()
{{template}}, {{printer}}Template name and resolved printer name

Formatters chain with |:

FormatterExampleResult
pad:N`{{sequencepad:6}}`
padright:N`{{namepadright:10}}`
upper, lower, trim`{{nametrim
substr:start,len`{{serialsubstr:0,4}}`
default:value`{{lotdefault:n/a}}`
date:format`{{expiresdate:dd.MM.yyyy}}`
any .NET format string`{{qty000}}, {{now

Numbers print without trailing zeros; arrays and objects print as JSON.

Limits ​

Bounds that fail at validation (or refuse a single element) rather than at allocation:

WhatLimit
Page width / height2000 mm each
fontSize and a text element's size500 pt
Image (inline data: URL, bare base64 or file)8 MB encoded, 16 megapixels decoded — checked from the header before decoding
pad:N / padright:NN is capped at 256
Placeholder parsing250 ms; an unterminated {{ … with a very long formatter chain is reported as a template error
labels.preview over WebSocket5 per second per connection (security.rateLimit.previewsPerSec, minimum 1)

Sizing tips ​

  • Design at the printer's real resolution: Brother P-touch 360 dpi, Epson TM-C3500 360 dpi, most Zebra 203 or 300 dpi. The driver renders at that dpi automatically; dpi in the template only matters for px units and previews.
  • Keep 1–2 mm of margin: printer drivers have an unprintable border and tape printers cut a little off each end.
  • A 1D code needs roughly modules × 2 device pixels of width to be scannable at arm's length; when in doubt make the box wider rather than taller.
  • Use preview() (or the dashboard canvas bound to the preview stream) while iterating — it does not consume media or the sequence counter.
  • validateTemplate() reports errors and warnings without rendering; listTemplates() shows files that failed to parse.

Muxit — Hardware Orchestration Platform