Layer

Last updated on

Rendering output specification for artifacts

A Layer defines how an artifact can be rendered into a specific format. Layers enable artifacts to have multiple output representations (PDF, HTML, Markdown, etc.).

type Layer = InlineLayer | FileLayer

MIME types

The layer's mimeType selects its renderer.

MIME typeLayer kindRendered by
text/markdown, text/html, text/plaininline or fileBuilt-in text renderer
application/pdffileBuilt-in PDF renderer, using bindings
application/vnd.openxmlformats-officedocument.wordprocessingml.documentfileBuilt-in DOCX renderer
text/tsx, text/jsxfile only, forms onlyA renderer you register, such as reactLayerRenderers() from @paradoc/react-pdf

Any other MIME type needs a renderer passed in the renderers option of render(), keyed by MIME type.

A text/tsx or text/jsx layer names a React composition module by path, so it must be a file layer. An inline layer with either MIME type fails validation. The check ignores case, so TEXT/TSX is rejected too. Only a form can declare a React layer: a composition renders a form and its data, so a document or checklist with one fails validation.

Layer Types

InlineLayer

Inline layer with embedded text content. Used when content is stored directly in the artifact definition.

kind: 'inline'
Discriminator for inline layer type
mimeType: string
MIME type of the content (e.g., text/markdown, text/html). Never text/tsx or text/jsx
text: string
Layer content with interpolation placeholders, such as `{{fields.fieldName}}`
title?: string
Human-readable title for this layer
description?: string
Description of what this layer represents
signatures?: Record<string, SignatureSlot>
Signature slots keyed by slot id, each binding a party to a placement

FileLayer

File-backed layer with external file reference. Used when content is stored in a separate file.

kind: 'file'
Discriminator for file layer type
mimeType: string
MIME type of the file (e.g., application/pdf, text/tsx)
path: string
Logical resolver path; the CLI uses the artifact directory, or cwd for stdin
title?: string
Human-readable title for this layer
description?: string
Description of what this layer represents
checksum?: string
SHA-256 checksum for integrity verification
font?: { path: string, checksum?: string }
PDF layers only. A TrueType font (.ttf) for filled values and overlay text, read through the same resolver as `path`. See [PDF renderer fonts](/sdk/renderers/pdf#fonts)
format?: { money?: { currencyDisplay: 'none' } }
PDF layers only. The presentation the template requires of filled values. `none` prints money amounts without a symbol, for a template that pre-prints it. Applies to this layer alone. See [Artifact formatting](/sdk/renderers/pdf#artifact-formatting)
bindings?: Record<string, string>
PDF layers only. Maps each AcroForm field name in the template (key) to the Paradoc path that fills it (value). See [Bindings](#bindings)
bindingsFrom?: string
PDF layers only. Key of a sibling PDF layer whose bindings this layer reuses
signatures?: Record<string, SignatureSlot>
Signature slots keyed by slot id, each binding a party to a placement

Bindings

Only a PDF file layer takes bindings and bindingsFrom. Each key of bindings is a fully qualified AcroForm field name, as paradoc inspect prints it, and each value is the Paradoc path that fills it, such as fields.name or parties.buyer.name. A text, Markdown, HTML or DOCX template names each value directly as {{fields.fieldName}}. Validation rejects bindings or bindingsFrom on any other layer.

{
  "kind": "file",
  "mimeType": "application/pdf",
  "path": "w-9.pdf",
  "bindings": {
    "topmostSubform[0].Page1[0].f1_01[0]": "parties.taxpayer.name",
    "topmostSubform[0].Page1[0].f1_02[0]": "fields.businessName"
  }
}

SignatureSlot

A signature slot declares one signing field on a layer. Each slot binds a party to a placement; the seal pipeline resolves every slot to concrete PDF coordinates.

party: { role: string; index?: number }
Party this slot binds to. index is 0-based for multi-party roles and defaults to 0
type: 'signature' | 'initials' | 'date_signed' | 'capacity' | 'printed_name'
Type of signing field
placement: SignatureSlotPlacement
Where the field lands: 'flow' (in the content flow; located after conversion), a text anchor, or absolute coordinates
required?: boolean
Whether this slot must be signed. Defaults to true
label?: string
Human-readable label
type SignatureSlotPlacement =
  | 'flow'
  | { page: number; x: number; y: number; width: number; height: number }
  | {
      anchor: { text: string; offsetX?: number; offsetY?: number; occurrence?: number }
      width: number
      height: number
    }

signatures is the only place a layer declares signing fields. To update an artifact from an older schema version that uses signatureBlocks or anchorBlocks, run paradoc migrate.

Examples

layers:
  # Inline layer with markdown content
  markdown:
    kind: inline
    mimeType: text/markdown
    title: Markdown Version
    text: |
      # Welcome

      This is the content of the document with {{ fields.name }} placeholder.

  # File layer referencing external PDF
  pdf:
    kind: file
    mimeType: application/pdf
    path: /templates/contract.pdf
    title: PDF Version
    bindings:
      client_name: clientName
      contract_date: contractDate

  # File layer pointing at a React composition module
  composition:
    kind: file
    mimeType: text/tsx
    path: ./contract.tsx
    title: React Version

On this page