Nodes
Image
A picture your data points at, or one a generation endpoint produces.
A static image points at something you hold — a signature, a logo, a site photograph — with every field able to vary per recipient. A dynamic image describes what is wanted and leaves the endpoint to make it.
- Helpers
- image
- Node kind
- image
- Category
- Media
- Resolves
- Both
- Children
- None.
| Option | Type | What it does |
|---|---|---|
id required | string | Stable address for the node. Generation endpoints target it and build artifacts diff on it, so treat a rename as a breaking change. |
src required | string | (data) => string | Static only. Path or URL to the image; lands on the node as path. |
alt | string | (data) => string | Static only. Alternative text — and, while the renderers draw a frame rather than the picture, the words printed inside it. |
width | number | (data) => number | Static only. Intended width. Carried onto the node untouched; no shipped renderer reads it yet. |
height | number | (data) => number | Static only. Intended height, on the same terms as width. |
placeholder | (data, availableTokens) => string | Dynamic only. What previews show in place of generated content. Optional, but a letter that reads badly without one cannot be reviewed. |
generalPrompt required | (data, availableTokens) => string | Dynamic only. What this node should say. |
infoPrompt | (data, availableTokens) => string | Dynamic only. Context the model should have but should not restate. |
negativePrompt | (data, availableTokens) => string | Dynamic only. What to avoid — claims, tones, or facts it must not invent. |
systemPrompt | (data, availableTokens) => string | Dynamic only. Role and voice, applied ahead of the other prompts. |
derivers | DeriverInvocation[] | Values computed before the node resolves, written to derived.* and readable from a template token. Built with derive(). |
Every field takes a function
src, alt, width and height each accept a plain value or a function of
your data. A signature that differs per office, a logo per brand, a photograph
keyed by reference — all of it stays inside the node instead of becoming a
branch in the template:
image<MemberData>({
id: "signature",
src: (data) => data.signatureUrl,
alt: (data) => `Signed by ${data.managerName}`,
width: 180,
});
src becomes path
The option is src; the resolved node calls it path. Expand What it resolves
to on the first variant below to see it.
Dynamic images
A dynamic image is described rather than supplied, taking the same four prompt slots as a dynamic paragraph.
negativePrompt earns its place here more than anywhere. Generated imagery
fails in predictable ways — baked-in text, invented logos, recognisable faces —
and the slot rules them out once, in the node.
Variants
Static
src/nodes/image/static.node.ts A signature whose file and caption both follow the data.
import { image } from "docxcelerate";
import type { SampleData } from "../sample-data.ts";
/**
* Every field takes a plain value or a function of your data, so a signature
* that varies by manager needs no branching in the template.
*/
export const Signature = image<SampleData>({
id: "signature",
src: (data) => data.signatureUrl,
alt: (data) => `Signed by ${data.managerName}`,
width: 180,
height: 60,
}); What it resolves to
The node as it appears in the DocumentModel: the JSON a renderer is handed. No styling, no layout.
{
"id": "signature",
"kind": "image",
"mode": "static",
"path": "assets/signature-lindqvist.png",
"alt": "Signed by Tomas Lindqvist",
"width": 180,
"height": 60
} Dynamic
src/nodes/image/dynamic.node.ts Described rather than supplied, with the failure modes fenced off.
import { image } from "docxcelerate";
import type { SampleData } from "../sample-data.ts";
/**
* The same prompt set as a dynamic paragraph, for artwork the endpoint
* produces rather than something you hold. The placeholder is what previews
* show, so the layout is settled before any image exists.
*/
export const CentrePhoto = image<SampleData>({
id: "centre-photo",
placeholder: (data) => `Photograph of ${data.centreName}`,
generalPrompt: (data) =>
`A wide daylight photograph of the entrance to ${data.centreName}, ` +
`people arriving, no text overlay.`,
negativePrompt: () => `No logos, no recognisable faces, no stock-photo staging.`,
}); What it resolves to
The node as it appears in the DocumentModel: the JSON a renderer is handed. No styling, no layout.
{
"id": "centre-photo",
"kind": "image",
"mode": "dynamic",
"placeholder": "Photograph of Riverside Leisure Centre"
} What the endpoint is asked
Resolved against the same sample data. A preview build stops at the placeholder; a request-time build sends these.
- general
- A wide daylight photograph of the entrance to Riverside Leisure Centre, people arriving, no text overlay.
- negative
- No logos, no recognisable faces, no stock-photo staging.
Notes
- The node holds a path, never the bytes. Nothing is fetched or validated during a build; a broken path fails at render time.
altis worth writing even while the renderers print frames, because the frame printsalt.