Watermarks
Watermarks are page chrome. They render across every page (front-layer overlay on PDF, header-anchored on DOCX) without affecting flow content. The same JSON renders identically in both formats.
Live example
A real-world Mutual NDA with a DRAFT watermark layered behind page content. Open Template to see the JSON.
- Output
- Template
- Data
Schema
Watermarks live at the root of the document definition as an array — they apply to the document as a whole, not to a particular position in the content flow.
{
"document": {
"watermarks": [
{
"content": { "p": "DRAFT" },
"angle": -30,
"repeat": false,
"style": "draft"
}
],
"content": [ ... ]
}
}
| Property | Type | Default | Description |
|---|---|---|---|
content | Content | — | Any content shape — { "p": "..." } paragraph, { "canvas": { … } } block, or inline tags ([image, …], [barcode, …]). Same content vocabulary as body content. |
angle | number | 0 | Rotation in degrees. Negative = counter-clockwise. The content rotates around its own visual center. |
repeat | boolean | false | true = tile across the page using spacing as the step. false = single instance; placement comes from spacing if provided, otherwise centered on the page. |
spacing | [x, y] | — | In points. Meaning depends on repeat: tile step when repeat: true, explicit page-coordinate placement of the visual center when repeat: false. Omit or use [0, 0] for centered placement. |
style | string | — | Named style applied to the watermark content (font size, opacity, color). |
Text watermark
The most common shape — bold rotated text with low opacity behind the document body.
{
"document": {
"styles": {
"draft": { "fontSize": 96, "bold": true, "fontColor": "#CCCCCC", "opacity": 0.30 }
},
"watermarks": [
{
"content": { "p": "DRAFT" },
"angle": -30,
"repeat": false,
"style": "draft"
}
],
"content": [
{ "p": "Body content sits beneath the centered DRAFT mark." }
]
}
}
Image watermark
The watermark content is just a paragraph — drop in an [image, …] inline tag and it renders as an image watermark. Style provides the opacity for "faintness".
{
"document": {
"styles": {
"logoFaint": { "opacity": 0.15 }
},
"watermarks": [
{
"content": { "p": "[image, images/logos/acme.png, 240|72]" },
"angle": -30,
"repeat": false,
"style": "logoFaint"
}
],
"content": [ ... ]
}
}
Repeating tile pattern
For internal-doc branding, tile a small mark across the page.
{
"watermarks": [
{
"content": { "p": "[image, images/logos/acme.png, 120|60]" },
"spacing": [250, 200],
"angle": 0,
"repeat": true,
"style": "logoFaint"
}
]
}
| Layout | repeat | spacing |
|---|---|---|
| Single, centered | false | omitted or [0, 0] |
| Single, positioned | false | [centerX, centerY] in page points |
| Tiled across page | true | [xStep, yStep] in page points |
Positioned watermark — edge-mounted elements
For control numbers, vertical sidebars, edge-mounted barcodes, and other elements anchored to a specific page region, set repeat: false and provide explicit page coordinates in spacing. The values are the visual center of the watermark content in page points (origin at bottom-left).
A vertical sidebar running down the left edge of a portrait LETTER page (612×792):
{
"watermarks": [
{
"content": {
"canvas": {
"size": [22, 620],
"commands": [
{ "type": "line", "points": [{ "x": 6, "y": 14 }, { "x": 6, "y": 606 }], "style": "edgeRule" },
{ "type": "textPath",
"d": "M 14 606 L 14 14",
"text": "[caps]control no. dpa-doc-2026-0457 · scan to verify[/caps]",
"alignment": "middle",
"style": "edgeText" }
]
}
},
"repeat": false,
"spacing": [25, 396]
}
]
}
The canvas (22pt wide × 620pt tall) is anchored with its visual center at [25, 396] — 25pt from the page's left edge, page-center vertically. A mirror watermark with spacing: [587, 396] does the same on the right edge (612 − 25 = 587).
This works for any content shape — a barcode [barcode, code128, …] paragraph rotated with angle: 90 becomes a vertical edge barcode; a small text block at [306, 80] becomes a bottom-edge control number.
achievement-certificate and void-check both ship live examples of this pattern.
Multiple watermarks
The array is composed in order. Layer a faint logo behind a bold DRAFT text overlay:
{
"watermarks": [
{
"content": { "p": "[image, images/logos/acme.png, 200|80]" },
"spacing": [300, 250],
"repeat": true,
"style": "logoFaint"
},
{
"content": { "p": "DRAFT" },
"angle": -35,
"repeat": false,
"style": "draftBold"
}
]
}
Dynamic watermark content
Anywhere $data.* references appear (text, image src, even $data.<key> substitutions inside inline tags), they resolve at render time the same way they do in body content:
{
"watermarks": [
{
"content": { "p": "[image, $data.tenant.logoPath, 120|60]" },
"repeat": true,
"style": "logoFaint"
},
{
"content": { "p": "$data.classification" },
"repeat": false,
"style": "classification"
}
]
}
Style properties that matter for watermarks
| Property | Description |
|---|---|
fontSize | Text size — typically large (60–120pt) for a single centered mark. |
fontColor | Text color. |
bold / italic | Boolean. |
font | Font family — useful for Helvetica-BoldOblique italic-bold combos. |
opacity | 0.0–1.0 translucency. Most watermarks use 0.05–0.30. |
{
"styles": {
"draft": { "fontSize": 96, "bold": true, "fontColor": "#94A3B8", "opacity": 0.25 },
"verified": { "fontSize": 80, "bold": true, "fontColor": "#15803D", "opacity": 0.35 },
"logoFaint": { "opacity": 0.15 }
}
}