Airpdf docs

Airpdf — Template schema

Un template Airpdf è un documento JSON strutturato che descrive la gerarchia di nodi che i nodi render Node.js (react-pdf) convertono in PDF.

Gerarchia

Document
 └── Page (una per pagina del PDF)
      └── View (contenitore con style, simile a un <div>)
           ├── Text (testo + variabili {{var}})
           ├── Image (src: statico oppure variabile)
           ├── List (ripetizione da array di `data`)
           └── Link (testo+href, href può essere variabile)

Ogni nodo ha:

  • type: uno di document | page | view | text | image | list | link
  • style: object con attributi CSS-like (vedi sotto)
  • children: array di nodi figli
  • campi specifici del tipo

Variable syntax

I campi testuali supportano il placeholder Mustache-like {{path.to.value}}:

{ "type": "text", "children": ["Ciao {{customer.name}}!"] }

Path annidati, array indexing (items.0.sku) e helpers basilari ({{#if}}, {{#each}}) sono supportati dal render.

Supported style attrs

Subset di react-pdf (flexbox):

Categoria Attributi
Layout display, flexDirection, justifyContent, alignItems, gap
Box width, height, padding(Top/Right/Bottom/Left), margin...
Border borderWidth, borderColor, borderRadius
Background backgroundColor
Text fontSize, fontFamily, fontWeight, color, textAlign, lineHeight
Page only size (A4/Letter/...), orientation, margin

Valori supportati: px (default numerico), %, percentuali per width/height.

Esempio minimo

template.json:

{
  "type": "document",
  "children": [
    {
      "type": "page",
      "style": { "size": "A4", "padding": 40, "fontFamily": "Helvetica" },
      "children": [
        {
          "type": "view",
          "style": { "flexDirection": "row", "justifyContent": "space-between" },
          "children": [
            { "type": "text", "style": { "fontSize": 18, "fontWeight": "bold" },
              "children": ["Fattura {{invoice.number}}"] },
            { "type": "image",
              "src": "{{brand.logo_url}}",
              "style": { "width": 80, "height": 80 } }
          ]
        },
        {
          "type": "list",
          "from": "items",
          "style": { "marginTop": 20 },
          "item": {
            "type": "view",
            "style": { "flexDirection": "row", "justifyContent": "space-between" },
            "children": [
              { "type": "text", "children": ["{{this.sku}} × {{this.qty}}"] },
              { "type": "text", "children": ["€ {{this.price}}"] }
            ]
          }
        }
      ]
    }
  ]
}

data:

{
  "invoice": { "number": "2026-001" },
  "brand":   { "logo_url": "https://acme.com/logo.png" },
  "items": [
    { "sku": "SKU-1", "qty": 2, "price": "19.90" },
    { "sku": "SKU-2", "qty": 1, "price": "49.00" }
  ]
}

variables_schema

Ogni Template salva un variables_schema JSON Schema Draft 2020-12 che documenta e valida il payload data in ingresso. L'editor integrato genera lo schema automaticamente; il render lo usa per errori chiari prima del rendering:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "required": ["invoice", "items"],
  "properties": {
    "invoice": {
      "type": "object",
      "required": ["number"],
      "properties": { "number": { "type": "string" } }
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["sku", "qty", "price"],
        "properties": {
          "sku":   { "type": "string" },
          "qty":   { "type": "integer", "minimum": 1 },
          "price": { "type": "string", "pattern": "^\\d+(\\.\\d{1,2})?$" }
        }
      }
    }
  }
}

Violazioni producono un 422 VALIDATION_FAILED con path + messaggio per ciascun campo non conforme.

Spotted a typo or stale claim? Open an issue or ping us in the workspace — docs are versioned with the product.