Paradoc
Concepts

Layers & Rendering

Last updated on

How artifacts become output documents

Artifacts define structure. Layers define how that structure becomes output.

A single artifact can have multiple layers—Markdown for AI agents, PDF for printing, HTML for web display—all representing the same underlying data.


What Layers Are

A layer is a view of an artifact. It combines a template with the artifact's data to produce output.

Layers are not transformations—they don't change the artifact. They're representations: different ways of looking at the same source of truth.

const form = para.form()
  .name("invoice")
  .fields({
    customer: { type: "text" },
    total: { type: "money" },
  })
  .defaultLayer("markdown")
  .layers({
    markdown: para.layer().inline().mimeType("text/markdown").text(`
# Invoice
Customer: {{customer}}
Total: {{total}}
    `),
    pdf: para.layer().file().mimeType("application/pdf").path("templates/invoice.pdf"),
  })
  .build()

Inline vs File Layers

Inline layers define the template directly in the artifact—good for simple templates or keeping everything in one place.

File layers reference an external template file—good for complex templates or when designers maintain templates separately.


Templates and Bindings

Text-based layers (Markdown, HTML, plain text) use Paradoc's deterministic template syntax. Field values are inserted with {{fieldName}}; conditionals, loops, context blocks, and helpers are also supported.

PDF layers work differently—they use bindings to map form fields to PDF form fields:

pdf: para.layer()
  .file()
  .mimeType("application/pdf")
  .path("templates/lease.pdf")
  .bindings({
    "PDFFieldName": "formFieldName",
  })

Resolution

When layers reference external files, resolvers tell Paradoc how to load them. This makes Paradoc environment-agnostic—the same artifact works in Node, browsers, or custom environments.

const output = await form.render({
  resolver: fileResolver({ basePath: "./templates" })
})

See Resolvers for available resolvers and how to write custom ones.


Serialization

When rendering, field values are converted to strings. A money value becomes "$1,500.00", a date becomes "March 15, 2024".

Serializers control this formatting. Different serializers produce different formats (US vs EU localization, for example).

const output = await form.render({
  renderer: renderLayer({ serializers: euSerializers })
})

See Serialization for details on formatting and localization.


Renderers

Paradoc selects the built-in implementation from the layer's MIME type. The same API renders Markdown, HTML, plain text, PDF, or DOCX, so applications do not need their own format switch.

const markdown = await filled.render({ layer: 'markdown' })
const pdf = await filled.render({ layer: 'pdf' })

Pass a custom renderer or configured renderLayer() through the optional renderer property. Format entry points remain available for low-level operations. See Renderers for the full API.

On this page