DataMagik Documents

Updated Mar 28, 2026
DataMagik Documents

Document Designer Guide

Create, manage, and version professional PDF document templates using HTML, CSS, and Go template syntax.

Table of Contents

  1. Overview
  2. Creating a Template
  3. The Template Editor
  4. Go Template Syntax
  5. Working with Data
  6. Barcodes & QR Codes
  7. ZPL Label Creation & Test Printing
  8. User Defined Tables in Templates
  9. Serial Number Series
  10. Charts & Visualizations
  11. Version Control & Branches
  12. Approval Workflow
  13. Generating Documents
  14. Best Practices

1. Overview

The Document Designer allows you to create professional PDF documents using familiar web technologies (HTML & CSS) combined with Go's powerful templating system. Documents can include:

  • Dynamic data from your ERP, scripts, or APIs
  • Barcodes and QR codes
  • Charts and visualizations
  • Tables with repeating data
  • Conditional content
  • Custom styling and branding

Key Features:

  • Visual Preview — See your template rendered with sample data
  • Version Control — Track changes with branch-based versioning
  • Approval Workflow — Require approval before templates go to production
  • Audit Trail — Full history of who changed what and when

2. Creating a Template

Step 1: Open Document Designer

Navigate to DataMagik → Document Designer in the main menu.

Step 2: Click "New Template"

Click the New Template button in the toolbar.

Step 3: Configure Template Settings

FieldDescriptionExample
NameTemplate identifierInvoice - Standard
CategoryGrouping for organizationInvoices
DescriptionWhat this template is forStandard customer invoice with line items

Step 4: Start Editing

After creation, click Edit to open the template editor.

3. The Template Editor

The template editor provides a full-featured HTML/CSS editing environment.

Editor Layout

  • Left Panel — Code editor with syntax highlighting
  • Right Panel — Live preview with sample data
  • Top Toolbar — Save, preview, settings, and help

Editor Tabs

  • HTML — Template structure and Go template tags
  • CSS — Styling for your document
  • Sample Data — JSON data for preview

Keyboard Shortcuts

ShortcutAction
Ctrl+SSave template
Ctrl+Shift+PPreview with current data
Ctrl+SpaceShow autocomplete
Ctrl+/Toggle comment
Ctrl+?Open help modal

4. Go Template Syntax

DataMagik templates use Go's template syntax. Here's a comprehensive reference:

Basic Output

<!-- Output a field value -->
<p>Customer: {{.CustomerName}}</p>

<!-- Access nested fields -->
<p>City: {{.Address.City}}</p>

<!-- Access array elements -->
<p>First Item: {{index .Items 0}}</p>

Variables

<!-- Define a variable -->
{{$total := .OrderTotal}}
<p>Total: ${{$total}}</p>

<!-- Assign from calculation -->
{{$discounted := mul .Price 0.9}}
<p>Discounted: ${{$discounted}}</p>

Conditionals

<!-- Simple if -->
{{if .IsRush}}
  <div class="rush-banner">RUSH ORDER</div>
{{end}}

<!-- If-else -->
{{if .IsPaid}}
  <span class="status paid">PAID</span>
{{else}}
  <span class="status unpaid">UNPAID</span>
{{end}}

<!-- If-else if-else -->
{{if eq .Status "shipped"}}
  <span>Shipped</span>
{{else if eq .Status "processing"}}
  <span>Processing</span>
{{else}}
  <span>Pending</span>
{{end}}

Comparison Operators

OperatorDescriptionExample
eqEqual{{if eq .Status "active"}}
neNot equal{{if ne .Count 0}}
ltLess than{{if lt .Quantity 10}}
leLess than or equal{{if le .Age 18}}
gtGreater than{{if gt .Total 1000}}
geGreater than or equal{{if ge .Score 70}}

Logical Operators

<!-- AND -->
{{if and .IsActive .IsVerified}}
  <p>User is active and verified</p>
{{end}}

<!-- OR -->
{{if or .IsAdmin .IsModerator}}
  <p>User has elevated permissions</p>
{{end}}

<!-- NOT -->
{{if not .IsDeleted}}
  <p>Record is active</p>
{{end}}

<!-- Combined -->
{{if and .IsActive (or .IsAdmin .IsModerator)}}
  <p>Active user with permissions</p>
{{end}}

Loops

<!-- Simple loop -->
<ul>
{{range .Items}}
  <li>{{.Name}} - ${{.Price}}</li>
{{end}}
</ul>

<!-- Loop with index -->
{{range $index, $item := .Items}}
  <tr>
    <td>{{add $index 1}}</td>
    <td>{{$item.Name}}</td>
  </tr>
{{end}}

<!-- Loop with else (empty case) -->
{{range .Items}}
  <div>{{.Name}}</div>
{{else}}
  <div>No items found</div>
{{end}}

Built-in Functions

FunctionDescriptionExample
lenLength of array/string{{len .Items}}
indexGet item at index{{index .Items 0}}
printfFormatted string{{printf "%.2f" .Price}}
upperUppercase{{upper .Code}}
lowerLowercase{{lower .Email}}
titleTitle case{{title .Name}}
trimTrim whitespace{{trim .Input}}

Math Functions

<p>Subtotal: ${{add .Price .Tax}}</p>
<p>Discount: ${{sub .Total .Discount}}</p>
<p>Extended: ${{mul .Quantity .UnitPrice}}</p>
<p>Average: {{div .Total .Count}}</p>

Date Formatting

<p>Date: {{formatDate .OrderDate "January 2, 2006"}}</p>
<p>Date: {{formatDate .OrderDate "2006-01-02"}}</p>
<p>Printed: {{now | formatDate "2006-01-02 15:04:05"}}</p>

Comments

{{/* This is a comment - won't appear in output */}}

5. Working with Data

Sample Data Structure

Your sample data should mirror the structure of real data:

{
  "OrderNumber": "ORD-2025-001234",
  "OrderDate": "2025-12-05",
  "CustomerName": "Acme Corporation",
  "BillTo": {
    "Name": "Acme Corporation",
    "Address": "123 Main Street",
    "City": "Detroit",
    "State": "MI",
    "Zip": "48201"
  },
  "Items": [
    {
      "LineNumber": 1,
      "PartNumber": "WIDGET-001",
      "Description": "Standard Widget",
      "Quantity": 100,
      "UnitPrice": 12.50,
      "ExtendedPrice": 1250.00
    }
  ],
  "Subtotal": 2500.00,
  "TaxRate": 0.06,
  "TaxAmount": 150.00,
  "Total": 2650.00
}

Building a Document

Header Section:

<div class="header">
  <h1>INVOICE</h1>
  <p>Invoice #: {{.OrderNumber}}</p>
  <p>Date: {{formatDate .OrderDate "January 2, 2006"}}</p>
</div>

Line Items Table:

<table class="line-items">
  <thead>
    <tr>
      <th>Part #</th>
      <th>Description</th>
      <th>Qty</th>
      <th>Unit Price</th>
      <th>Extended</th>
    </tr>
  </thead>
  <tbody>
    {{range .Items}}
    <tr>
      <td>{{.PartNumber}}</td>
      <td>{{.Description}}</td>
      <td>{{.Quantity}}</td>
      <td>${{printf "%.2f" .UnitPrice}}</td>
      <td>${{printf "%.2f" .ExtendedPrice}}</td>
    </tr>
    {{end}}
  </tbody>
  <tfoot>
    <tr>
      <td colspan="4">Subtotal:</td>
      <td>${{printf "%.2f" .Subtotal}}</td>
    </tr>
    <tr>
      <td colspan="4"><strong>Total:</strong></td>
      <td><strong>${{printf "%.2f" .Total}}</strong></td>
    </tr>
  </tfoot>
</table>

6. Barcodes & QR Codes

Generate barcodes directly in your templates.

Supported Barcode Types

1D Barcodes: Code 128, Code 39, EAN-13, EAN-8, UPC-A, UPC-E, Codabar

2D Barcodes: QR Code, Data Matrix, PDF417, Aztec

Barcode Functions

<!-- Code 128 (most common) -->
<img src="data:image/png;base64,{{barcode128 .OrderNumber}}" alt="Barcode" />

<!-- Code 128 with custom size -->
<img src="data:image/png;base64,{{barcode128 .OrderNumber 300 60}}" alt="Barcode" />

<!-- QR Code -->
<img src="data:image/png;base64,{{qrcode .TrackingURL}}" alt="QR Code" />

<!-- QR Code with size -->
<img src="data:image/png;base64,{{qrcode .TrackingURL 150}}" alt="QR Code" />

<!-- EAN-13 -->
<img src="data:image/png;base64,{{ean13 .ProductEAN}}" alt="EAN" />

<!-- Data Matrix -->
<img src="data:image/png;base64,{{datamatrix .SerialNumber}}" alt="Data Matrix" />

Barcode Best Practices

  • Test scanning — Always test generated barcodes with actual scanners
  • Adequate size — Ensure barcodes are large enough for reliable scanning
  • Quiet zones — Leave white space around barcodes
  • Proper contrast — Use dark barcodes on light backgrounds

7. ZPL Label Creation & Test Printing

Create ZPL (Zebra Programming Language) labels for thermal printers with integrated test printing.

ZPL Template Syntax

ZPL templates use the same Go template syntax as PDF documents:

^XA
^FO50,50^A0N,40,40^FD{{.PartNumber}}^FS
^FO50,100^A0N,30,30^FD{{.Description}}^FS
^FO50,150^BY3^BCN,100,Y,N,N^FD{{.Barcode}}^FS
^FO50,280^A0N,25,25^FDQty: {{.Quantity}}^FS
^FO50,320^A0N,20,20^FD{{formatDate .PrintDate "2006-01-02"}}^FS
^XZ

Common ZPL Commands

CommandDescriptionExample
^XAStart label formatAlways first
^XZEnd label formatAlways last
^FOField origin (x,y position)^FO50,100
^FDField data (text content)^FD{{.Text}}^FS
^FSField separator (end field)Required after data
^A0Font selection^A0N,40,40
^BCCode 128 barcode^BCN,100,Y,N,N
^BQQR Code^BQN,2,5
^BYBarcode defaults^BY3
^GBGraphic box (lines/borders)^GB400,3,3^FS

Test Printing

  1. Open your ZPL template
  2. Click Test Print in the toolbar
  3. Select a printer from the dropdown
  4. Review the preview
  5. Click Print

Printing from Scripts

function main(context) {
  const zplCode = zpl.fromTemplate("PartLabel", {
    partNumber: context.partNumber,
    description: context.description,
    barcode: context.partNumber,
    quantity: context.qty
  });
  
  manufacturing.printLabel("Warehouse-Zebra-01", zplCode);
  
  return { success: true, script_message: "Label printed" };
}

8. User Defined Tables in Templates

Access data from User Defined Tables in your document generation scripts.

Using Table Data in Scripts

function main(context) {
  const customer = tables.get("customers", context.customerId);
  const shippingOptions = tables.list("shipping_methods");
  
  documents.generate("Order Confirmation", {
    orderNumber: context.orderNumber,
    customer: customer.value,
    shippingOptions: shippingOptions
  });
  
  return { success: true };
}

Common Table Patterns

// Customer master data for invoices
const customer = tables.get("customers", invoiceData.customerCode);

// Product catalog with pricing
const product = tables.get("products", lineItem.productId);

Table Functions Available

FunctionDescription
tables.get(tableName, key)Get single record by key
tables.getValue(tableName, key)Get just the value
tables.list(tableName)Get all records
tables.exists(tableName, key)Check if record exists

9. Serial Number Series

Integrate with Traceability serial number series for automatic serial generation in documents.

Generating Serials

function main(context) {
  const sn = serial.next("ProductSerials", {
    workOrder: context.workOrderNumber,
    partNumber: context.partNumber
  });
  
  documents.generate("Product Label", {
    serialNumber: sn,
    partNumber: context.partNumber,
    date: new Date().toISOString()
  });
  
  return { success: true, data: { serial: sn } };
}

Batch Serial Generation

function main(context) {
  const serials = serial.batch("ProductSerials", context.quantity, {
    workOrder: context.workOrderNumber,
    partNumber: context.partNumber
  });
  
  for (const sn of serials) {
    documents.generate("Product Label", {
      serialNumber: sn,
      partNumber: context.partNumber
    });
  }
  
  return {
    success: true,
    script_message: "Generated " + serials.length + " serial numbers"
  };
}

Serial Number Format Tokens

TokenDescriptionExample
{YYYY}4-digit year2025
{YY}2-digit year25
{MM}Month06
{DD}Day15
{JJJ}Julian day166
{####}Sequence0042

Example format: SN-{YYYY}{JJJ}-{####}SN-2025166-0042

10. Charts & Visualizations

Create dynamic charts using built-in charting functions.

Supported Chart Types

  • Line Chart
  • Bar Chart
  • Pie Chart
  • Doughnut Chart

Chart Syntax

<!-- Bar chart -->
{{chart "bar" .SalesData "Month" "Revenue"}}

<!-- Pie chart -->
{{chart "pie" .CategoryBreakdown "Category" "Amount"}}

<!-- Line chart with title -->
{{chart "line" .TrendData "Date" "Value" "title=Sales Trend"}}

Chart Data Format

{
  "SalesData": [
    { "Month": "Jan", "Revenue": 45000 },
    { "Month": "Feb", "Revenue": 52000 },
    { "Month": "Mar", "Revenue": 48000 }
  ]
}

11. Version Control & Branches

Document Designer includes Git-like version control for templates.

Branches

  • main — Production-ready templates
  • draft — Work-in-progress changes
  • Custom branches — Feature development or customer-specific versions

Creating a Version

  1. Make changes in the editor
  2. Click Commit in the toolbar
  3. Enter a commit message describing your changes
  4. Select the branch to commit to
  5. Click Commit Changes

Viewing Version History

  1. Select a template
  2. Click the Versions tab in the preview panel
  3. View all versions with timestamps and authors
  4. Click a version to view its content

Comparing Versions

  1. Select two versions in the history
  2. Click Compare
  3. View side-by-side diff of changes

Rolling Back

  1. Find the version you want to restore
  2. Click Rollback to this version
  3. Confirm the rollback
  4. A new version is created with the restored content

12. Approval Workflow

For production environments, templates can require approval before use.

Requesting Approval

  1. Commit your changes to a version
  2. Click Request Approval
  3. Select the version to approve
  4. Add any notes for the approver
  5. Submit the request

Approving a Template

  1. Go to the Approvals tab
  2. Review pending approval requests
  3. Click on a request to see details
  4. Review the template content and changes
  5. Click Approve or Reject
  6. Add approval notes if needed

Approval Status

StatusDescription
PendingWaiting for approval
ApprovedTemplate can be used in production
RejectedChanges needed before approval

13. Generating Documents

From Scripts

function main(context) {
  documents.generate("Invoice - Standard", {
    OrderNumber: context.orderNumber,
    CustomerName: context.customerName,
    Items: context.lineItems,
    Total: context.total
  });
  
  return { success: true };
}

From Automations

Documents can be triggered from:

  • Webhook automations
  • Scheduled tasks
  • Browser extension actions
  • N8N workflows

Generation Options

// Async generation (fire and forget)
const requestId = documents.generate("Template Name", data);

// Sync generation (wait for result)
const result = documents.generateSync("Template Name", data, {
  returnType: "url",    // "url" or "binary"
  timeout: 60000        // milliseconds
});

// Check status
const status = documents.getStatus(requestId);

Viewing Generated Documents

  1. Select a template
  2. Click the Documents tab
  3. View list of generated documents
  4. Click to download or preview

14. Best Practices

Template Organization

  • Use categories — Group related templates (Invoices, Packing Slips, Labels)
  • Descriptive names — "Invoice - Standard" not "inv1"
  • Document in description — Explain when/how template is used

Code Quality

  • Keep it simple — Break complex templates into sections
  • Use variables — Store calculated values for reuse
  • Comment your code — Use {{/* comments */}} to explain complex logic
  • Consistent styling — Use CSS classes, not inline styles

Testing

  • Test with edge cases — Empty arrays, null values, long text
  • Test printing — PDF rendering may differ from screen preview
  • Test barcodes — Verify they scan correctly

Performance

  • Optimize images — Use appropriate sizes, compress when possible
  • Limit complexity — Very complex templates may be slow to render
  • Test with real data volume — Large tables may need pagination

CSS Tips for PDF

/* Force page breaks */
.page-break { page-break-before: always; }

/* Prevent element from breaking across pages */
.keep-together { page-break-inside: avoid; }

/* Set page size and margins */
@page { size: letter; margin: 0.5in; }

/* Page numbers */
@page {
  @bottom-right { content: "Page " counter(page) " of " counter(pages); }
}
Was this page helpful?