---
title: "Bill of lading template for JavaScript — quario"
description: "A ready-made quario bill of lading for JavaScript. Shipper, consignee and carrier, the handling units with their weights, a hazardous-goods flag, and three signatures. Copy the definition, point it at your shipment, and render to PDF, Word, Excel, or HTML."
url: "https://getquario.com/templates/bill-of-lading"
---

# Bill of lading template for JavaScript

A bill of lading is the carrier’s receipt for the goods. It names who sends them, who receives them,
and who pays for the freight. It lists what the carrier loaded by handling unit and weight. The
shipper, the driver, and the consignee each sign it. When a pallet arrives damaged, it’s the document everyone
reaches for. This is a ready-made quario bill of lading — copy it, point it at your shipment, and
render to PDF, Word, Excel, or HTML.

## The template

The whole bill is a definition — data you can version and review. The three parties, the carrier
line, the handling units, the hazardous-goods notice and the signature blocks are all in here. This
is the exact file the preview below renders:

```json title="bill-of-lading.report.json"
{
  "data": "$.bol.units[*]",
  "aggregates": {
    "units": "sum:=@.qty",
    "kg": "sum:=@.kg",
    "hazmat": "sum:=@.hazmat ? 1 : 0"
  },
  "style": { "family": "sans", "size": 10 },
  "header": [
    {
      "type": "split",
      "style": { "spaceAfter": 18 },
      "slots": [
        { "type": "image", "source": "=logo()", "fit": "width", "alt": "{{ $.input.bol.shipper.name }} logo", "width": 28 },
        { "type": "text", "value": "", "style": { "size": 8 } }
      ]
    },
    {
      "type": "split",
      "slots": [
        { "type": "text", "value": "Bill of lading", "width": 60,
          "style": { "family": "serif", "size": 19, "bold": true, "color": "#1e1f22" } },
        { "type": "text", "value": "No. {{ $.input.bol.number }}",
          "style": { "family": "mono", "size": 10, "bold": false, "color": "#1e1f22", "align": "right" } }
      ]
    },
    {
      "type": "split",
      "slots": [
        { "type": "text", "value": "Straight bill of lading, not negotiable", "width": 60,
          "style": { "size": 8, "bold": false, "color": "#989a97" } },
        { "type": "text", "value": [{ "value": "Issued " }, { "value": "{{ $.input.bol.issued }}" }],
          "style": { "size": 8, "bold": false, "color": "#989a97", "align": "right", "format": "date" } }
      ]
    },
    {
      "type": "grid",
      "columns": [{ "width": 34 }, { "width": 33 }, {}],
      "rows": [
        {
          "style": { "family": "mono", "size": 7, "bold": false, "uppercase": true, "color": "#989a97", "paddingTop": 40 },
          "slots": [{ "type": "text", "value": "Shipper" }, { "type": "text", "value": "Consignee" }, { "type": "text", "value": "Bill freight to" }]
        },
        {
          "style": { "size": 10, "bold": true, "color": "#1e1f22" },
          "slots": [
            { "type": "text", "value": "{{ $.input.bol.shipper.name }}" },
            { "type": "text", "value": "{{ $.input.bol.consignee.name }}" },
            { "type": "text", "value": "{{ $.input.bol.billTo.name }}" }
          ]
        },
        {
          "style": { "size": 10, "bold": false, "color": "#5e6062" },
          "slots": [
            { "type": "text", "value": "{{ $.input.bol.shipper.street }}\n{{ $.input.bol.shipper.city }}\n{{ $.input.bol.shipper.country }}" },
            { "type": "text", "value": "{{ $.input.bol.consignee.street }}\n{{ $.input.bol.consignee.city }}\n{{ $.input.bol.consignee.country }}" },
            { "type": "text", "value": "{{ $.input.bol.billTo.street }}\n{{ $.input.bol.billTo.city }}\n{{ $.input.bol.billTo.country }}" }
          ]
        }
      ]
    },
    {
      "type": "grid",
      "columns": [{ "width": 25 }, { "width": 25 }, { "width": 25 }, {}],
      "rows": [
        {
          "style": { "family": "mono", "size": 7, "bold": false, "uppercase": true, "color": "#989a97", "paddingTop": 30 },
          "slots": [
            { "type": "text", "value": "Carrier" },
            { "type": "text", "value": "Trailer" },
            { "type": "text", "value": "Seal" },
            { "type": "text", "value": "Freight terms" }
          ]
        },
        {
          "style": { "size": 10, "bold": false, "color": "#1e1f22", "paddingBottom": 40 },
          "slots": [
            { "type": "text", "value": "{{ $.input.bol.carrier.name }}" },
            { "type": "text", "value": "{{ $.input.bol.carrier.trailer }}" },
            { "type": "text", "value": "{{ $.input.bol.carrier.seal }}" },
            { "type": "text", "value": "{{ $.input.bol.terms }}" }
          ]
        }
      ]
    }
  ],
  "detail": {
    "header": {
      "style": { "family": "mono", "size": 7, "uppercase": true, "color": "#989a97",
        "borderBottomWidth": 0.5, "borderBottomStyle": "solid", "borderBottomColor": "#1e1f22" }
    },
    "row": { "style": { "color": "#5e6062" } },
    "columns": [
      { "header": { "value": "Units", "style": { "align": "right" } }, "value": "{{ @.qty }}", "width": 8,
        "style": { "align": "right", "color": "#1e1f22" } },
      { "header": "Package", "value": "{{ @.package }}", "width": 12 },
      { "header": "Description", "value": "{{ @.description }}", "width": 42, "style": { "color": "#1e1f22" } },
      { "header": "Dims (cm)", "value": "{{ @.dims }}", "width": 16 },
      { "header": "HM", "value": "{{ @.hazmat ? 'X' : '' }}", "width": 5, "style": { "bold": true, "color": "#1e1f22" } },
      { "header": { "value": "Weight (kg)", "style": { "align": "right" } }, "value": "{{ @.kg }}", "width": 17,
        "style": { "align": "right", "color": "#1e1f22", "format": { "kind": "number", "digits": 1 } } }
    ],
    "total": {
      "style": { "bold": true, "color": "#1e1f22", "paddingTop": 6,
        "borderTopWidth": 0.5, "borderTopStyle": "solid", "borderTopColor": "#1e1f22" },
      "rows": [
        {
          "cells": [
            { "value": "{{ $.units }}", "style": { "align": "right" } },
            { "value": "Handling units", "span": 4 },
            { "value": "{{ round($.kg, 1) }}", "style": { "align": "right", "format": { "kind": "number", "digits": 1 } } }
          ]
        }
      ]
    }
  },
  "footer": [
    {
      "type": "text",
      "value": "HM marks hazardous material: {{ $.hazmat }} {{ $.hazmat == 1 ? 'line' : 'lines' }}. The shipper's dangerous goods declaration travels with the driver.",
      "visible": "=$.hazmat > 0",
      "style": { "size": 8, "color": "#5e6062", "spaceBefore": 8 }
    },
    {
      "type": "split",
      "style": { "spaceBefore": 30 },
      "slots": [
        { "type": "text", "value": "Instructions", "width": 22,
          "style": { "family": "mono", "size": 7, "uppercase": true, "color": "#989a97" } },
        { "type": "text", "value": "{{ $.input.bol.instructions }}", "style": { "color": "#5e6062" } }
      ]
    },
    {
      "type": "split",
      "slots": [
        { "type": "text", "value": "Order", "width": 22,
          "style": { "family": "mono", "size": 7, "uppercase": true, "color": "#989a97" } },
        { "type": "text", "value": "{{ $.input.bol.orderRef }}", "style": { "color": "#5e6062" } }
      ]
    },
    {
      "type": "grid",
      "columns": [{ "width": 30 }, { "width": 5 }, { "width": 30 }, { "width": 5 }, {}],
      "rows": [
        {
          "style": { "paddingTop": 96 },
          "slots": [
            { "type": "text", "value": "", "style": { "borderBottomWidth": 0.5, "borderBottomStyle": "solid", "borderBottomColor": "#1e1f22" } },
            { "type": "text", "value": "" },
            { "type": "text", "value": "", "style": { "borderBottomWidth": 0.5, "borderBottomStyle": "solid", "borderBottomColor": "#1e1f22" } },
            { "type": "text", "value": "" },
            { "type": "text", "value": "", "style": { "borderBottomWidth": 0.5, "borderBottomStyle": "solid", "borderBottomColor": "#1e1f22" } }
          ]
        },
        {
          "style": { "family": "mono", "size": 7, "uppercase": true, "color": "#989a97", "paddingTop": 4 },
          "slots": [
            { "type": "text", "value": "Shipper, signature and date" },
            { "type": "text", "value": "" },
            { "type": "text", "value": "Carrier, signature and date" },
            { "type": "text", "value": "" },
            { "type": "text", "value": "Consignee, signature and date" }
          ]
        }
      ]
    }
  ],
  "page": {
    "footer": [
      {
        "type": "text",
        "value": "Received in apparent good order and condition, except as noted, for carriage to the consignee named above. Report loss or damage on delivery, quoting {{ $.input.bol.number }}.",
        "style": { "size": 8, "color": "#989a97", "paddingTop": 10,
          "borderTopWidth": 0.5, "borderTopStyle": "solid", "borderTopColor": "#1e1f22" }
      }
    ]
  }
}
```

The three parties sit on one **grid**. It states its column widths once, and each row lays the
label, the name, and the address across them. A second grid does the same for the carrier, the
trailer, the seal, and the freight terms. Neither one needs a coordinate.

The table’s total row reads three report aggregates. `$.units` sums the handling units, and `$.kg`
sums the weights, which `round($.kg, 1)` brings back to the one decimal the scale reads. `$.hazmat`
counts the lines flagged as dangerous goods. The notice under the table declares
`"visible": "=$.hazmat > 0"`, so a load without one prints no empty warning.

Weights present through `{ "kind": "number", "digits": 1 }`, so `212` reads _212.0_ beside
_486.5_ and the column lines up. The cell still holds a number, which the Excel render keeps.

## The data

A definition renders nothing on its own — you hand it a document. This is the sample the preview
below uses. `$.bol.units[*]` in the definition selects its rows, and `$.input` reads the rest:

```json title="bill-of-lading.data.json"
{
  "bol": {
    "number": "BL-2026-0418",
    "issued": "2026-08-27",
    "orderRef": "SO 2026-1042",
    "terms": "Prepaid",
    "carrier": { "name": "PostNL Cargo", "trailer": "NL 48-TRB-2", "seal": "0047721" },
    "shipper": {
      "name": "Quire Press Ltd.",
      "street": "Binnenkant 42",
      "city": "1011 BM Amsterdam",
      "country": "Netherlands"
    },
    "consignee": {
      "name": "Folio & Sons",
      "street": "12 Marlborough Street",
      "city": "Dublin 1",
      "country": "Ireland"
    },
    "billTo": {
      "name": "Quire Press Ltd.",
      "street": "Accounts payable, Binnenkant 42",
      "city": "1011 BM Amsterdam",
      "country": "Netherlands"
    },
    "instructions": "Tail-lift delivery. Keep dry; stack no more than two pallets high.",
    "units": [
      { "qty": 2, "package": "Pallet", "description": "Case-bound books, quarter cloth, shrink-wrapped", "dims": "120 × 80 × 110", "kg": 486.5, "hazmat": false },
      { "qty": 1, "package": "Pallet", "description": "Type specimen books, boxed", "dims": "120 × 80 × 90", "kg": 212.0, "hazmat": false },
      { "qty": 6, "package": "Carton", "description": "Proof copies and loose dust jackets", "dims": "60 × 40 × 40", "kg": 41.6, "hazmat": false },
      { "qty": 1, "package": "Drum", "description": "Printing ink, oil-based, 25 L", "dims": "Ø 30 × 40", "kg": 27.4, "hazmat": true }
    ]
  }
}
```

Each unit line carries its own weight, not a weight per piece. That’s what goes on the weighbridge
ticket, and it’s what the carrier reconciles against.

## What it renders

This isn’t a screenshot. quario compiles the definition and data above, and `@quario/viewer` renders
them in your browser, right here. The PDF button hands you the same bill as real `@quario/pdf`
bytes, one A4 page with the terms on its baseline. The DOCX button beside it hands the same
definition to `@quario/docx`, where Word paginates and resolves the faces itself:

*Preview: the page renders this definition and its sample data live, with downloads — [see it rendered](https://getquario.com/templates/bill-of-lading).*

## Use it

```bash title="shell"
npm install quario @quario/pdf
```

```ts title="bill-of-lading.ts"
import { readFileSync, writeFileSync } from 'node:fs'
import { quario } from 'quario'
import { pdf } from '@quario/pdf'
import billOfLading from './bill-of-lading.report.json' with { type: 'json' }

const logo = () => readFileSync('logo.png')          // your logo, as PNG bytes
const report = quario({ locale: 'en-IE' }).report(billOfLading, { logo })

const data = await getShipment(id)                   // your shipment
const bytes = await report.render(pdf({ page: { size: 'A4', margin: 54 } }), data)

writeFileSync('bill-of-lading.pdf', bytes)
```

Print three copies, one for each signature, or render once and let each party sign its own. The
issue date presents through the instance’s locale, and nothing on the bill is money, so the
instance needs no currency.

## Make it yours

Because the bill is declarative, changing it means changing data. A straight bill for American freight,
with an NMFC class per line, is one more column. A declared value is one more field and a `format: "currency"`
cell. An ocean bill swaps the trailer and seal for a vessel and container number. A CMR consignment
note for road freight inside Europe keeps the same shape under different labels. It renders
**without `eval`**, so a description copied from a supplier’s packing list never becomes code.
[Security →](https://getquario.com/docs/diving-deeper/security.md)

## FAQ

### Is this a legal bill of lading?

It’s the layout and the data, not the legal terms. The terms a bill carries depend on the mode of
transport, the country and the carrier’s own conditions. Put the wording your carrier or your
freight forwarder gives you in the page footer, where the sample’s short receipt clause sits.

### How’s this different from a packing slip?

A [packing slip](https://getquario.com/templates/packing-slip.md) goes inside the box and lists its contents for the
recipient. A bill of lading travels with the driver and records what the carrier took on, by
handling unit and weight, with signatures at both ends. Same shipment, different obligation.

### Can I export the bill of lading to Excel?

Yes — `@quario/xlsx` renders the same definition to a workbook. The units and the weights stay
numbers, so a warehouse can reconcile the loads against its own records. [Full example
→](https://getquario.com/guides/json-to-excel.md)

### Can I use this bill of lading template commercially?

The definition is yours — the report definitions, data, and output you create with quario belong to
you. quario is free to evaluate with no time limit. Shipping real freight is past evaluation, so
that needs a license for each production deployment. Its users, agents, and renders are never
counted. [Pricing →](https://getquario.com/pricing.md)

### Where are the other templates?

[Browse the template gallery →](https://getquario.com/templates.md) — shipping labels, packing slips, delivery notes, and
more.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://getquario.com/"},{"@type":"ListItem","position":2,"name":"Templates","item":"https://getquario.com/templates"},{"@type":"ListItem","position":3,"name":"Bill of lading","item":"https://getquario.com/templates/bill-of-lading"}]}
```
