DocumentsLast updated on
Last updated on
Create and render static documents with layers
This guide walks through creating a static document with multiple layers and rendering it.
Define the Document
A document needs a name, version, and title. Unlike forms, documents don't have fields or parties—they're static content with one or more layers.
import { p } from '@paradoc/sdk'
const privacyPolicy = p.document({
name: 'privacy-policy',
version: '1.0.0',
title: 'Privacy Policy',
description: 'Our privacy policy document',
code: 'DOC-PRIVACY-001',
})Add Layers
Documents support multiple layers for different formats. Add inline layers for text, HTML, or Markdown content.
const privacyPolicy = p.document({
name: 'privacy-policy',
version: '1.0.0',
title: 'Privacy Policy',
defaultLayer: 'markdown',
layers: {
markdown: {
kind: 'inline',
mimeType: 'text/markdown',
text: `
# Privacy Policy
Last Updated: January 2025
## Data Collection
We collect information you provide directly to us, including name, email, and usage data.
## Data Usage
Your data is used to provide and improve our services.
`,
},
html: {
kind: 'inline',
mimeType: 'text/html',
text: '<h1>Privacy Policy</h1><p>Last Updated: January 2025</p>',
},
},
})Add File Layers
You can also reference external files instead of inline content. A file-backed layer's bytes come from a resolver, and the resolver is bound once, when the document is constructed — every instance derived from it afterward carries it.
import { createFsResolver } from '@paradoc/resolvers/fs'
const resolver = createFsResolver({ root: process.cwd() })
const privacyPolicy = p.document({
name: 'privacy-policy',
version: '1.0.0',
title: 'Privacy Policy',
defaultLayer: 'pdf',
layers: {
pdf: {
kind: 'file',
mimeType: 'application/pdf',
path: '/documents/privacy-policy.pdf',
},
markdown: {
kind: 'file',
mimeType: 'text/markdown',
path: '/documents/privacy-policy.md',
},
},
}, { resolver })Render the Document
Documents return raw content directly—no renderer needed. Use the default layer or specify one explicitly.
// Render using default layer
const output = await privacyPolicy.render()
console.log(output)
// Render specific layer
const htmlOutput = await privacyPolicy.render({ layer: 'html' })
console.log(htmlOutput)A document with file layers, built with a bound resolver as shown above, renders the same way — no resolver in the render call:
const pdfBytes = await privacyPolicy.render()Render a file layer with no resolver bound and Paradoc throws
UnboundResolverError, naming the layer and the path it wanted.
Save the Artifact
Export the document to JSON or YAML for storage or version control.
const json = privacyPolicy.toJSON()
const yaml = privacyPolicy.toYAML(){
"$schema": "https://schema.paradoc.dev/2026-10-02.json",
"kind": "document",
"name": "privacy-policy",
"version": "1.0.0",
"title": "Privacy Policy",
"description": "Our privacy policy document",
"code": "DOC-PRIVACY-001",
"layers": {
"markdown": {
"kind": "inline",
"mimeType": "text/markdown",
"text": "..."
}
},
"defaultLayer": "markdown"
}Load it back with p.load():
const loaded = p.load(jsonString) // works with JSON or YAML