# Layer

Rendering output specification for artifacts

Canonical URL: https://docs.paradoc.dev/schemas/artifacts/shared/layer/

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.).

```typescript
type Layer = InlineLayer | FileLayer
```

## MIME types

The layer's `mimeType` selects its renderer.

| MIME type                                                                 | Layer kind            | Rendered by                                                                        |
| ------------------------------------------------------------------------- | --------------------- | ---------------------------------------------------------------------------------- |
| `text/markdown`, `text/html`, `text/plain`                                | inline or file        | Built-in text renderer                                                             |
| `application/pdf`                                                         | file                  | Built-in PDF renderer, using `bindings`                                            |
| `application/vnd.openxmlformats-officedocument.wordprocessingml.document` | file                  | Built-in DOCX renderer                                                             |
| `text/tsx`, `text/jsx`                                                    | file only, forms only | A 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.

| Name | Type | Description |
| --- | --- | --- |
| `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.

| Name | Type | Description |
| --- | --- | --- |
| `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.

```json
{
  "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.

| Name | Type | Description |
| --- | --- | --- |
| `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 |

```typescript
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



**YAML**

```yaml
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
```

**JSON**

```json
{
  "layers": {
    "markdown": {
      "kind": "inline",
      "mimeType": "text/markdown",
      "title": "Markdown Version",
      "text": "# Welcome\n\nThis is the content of the document with {{ fields.name }} placeholder."
    },
    "pdf": {
      "kind": "file",
      "mimeType": "application/pdf",
      "path": "/templates/contract.pdf",
      "title": "PDF Version",
      "bindings": {
        "client_name": "clientName",
        "contract_date": "contractDate"
      }
    },
    "composition": {
      "kind": "file",
      "mimeType": "text/tsx",
      "path": "./contract.tsx",
      "title": "React Version"
    }
  }
}
```

## Related

* [Document](/schemas/artifacts/document) - Static content artifact
* [Form](/schemas/artifacts/form) - Interactive form artifact
* [Checklist](/schemas/artifacts/checklist) - Task tracking artifact
